<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Jim Vallandingham</title>
 <link href="http://vallandingham.me/atom.xml" rel="self"/>
 <link href="http://vallandingham.me/"/>
 <updated>2022-09-01T23:09:57+00:00</updated>
 <id>http://vallandingham.me/</id>
 <author>
   <name>Jim Vallandingham</name>
 </author>

 
 <entry>
   <title>Animating Uncertainty</title>
   <link href="http://vallandingham.me/animating_uncertainty.html"/>
   <updated>2018-05-28T00:00:00+00:00</updated>
   <id>http://vallandingham.me/animating_uncertainty</id>
   <content type="html">&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/uncertainty/uncertainty_twitter.png&quot; alt=&quot;Examples of what this post is about&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ages and ages ago as part of the &lt;a href=&quot;https://bocoup.com/services/datavis&quot;&gt;Bocoup Data Visualization Team&lt;/a&gt;, I was fortunate to work on a project with &lt;a href=&quot;http://www.ireneros.com/&quot;&gt;Irene Ros&lt;/a&gt; and &lt;a href=&quot;https://peterbeshai.com/&quot;&gt;Peter Beshai&lt;/a&gt; where we were asked to prototype some experiments around visualizing uncertainty.&lt;/p&gt;

&lt;p&gt;As the idea and importance of displaying uncertainty is not going away any time soon, I wanted to document my small contributions to this area with the hopes that it could spark inspiration for future (uncertain) work down the road.&lt;/p&gt;

&lt;h2 id=&quot;axis-of-uncertainty&quot;&gt;Axis of Uncertainty&lt;/h2&gt;

&lt;p&gt;For any topic, it can be useful to define a loose taxonomy around it - to facilitate the exploration of its ‘space’. The space won’t be perfect, but it helps expand from existing work to possible future work (plus it makes you seem more of an expert!).&lt;/p&gt;

&lt;p&gt;For uncertainty visualization, we started conjuring a space along two axes: the possible methods that could be used to visualize the uncertainty, and the data type of the “uncertain” data we are trying to visualize.&lt;/p&gt;

&lt;h3 id=&quot;visualization-methods&quot;&gt;Visualization Methods&lt;/h3&gt;

&lt;p&gt;Now, visualization possibilities are what I typically think of first when I think about visualizing uncertainty. Nathan Yau has a &lt;a href=&quot;http://flowingdata.com/2018/01/08/visualizing-the-uncertainty-in-data/&quot;&gt;great post on visualizing uncertainty&lt;/a&gt; where he outlines a number of different options, all of which (in my opinion) deal directly with encoding choices.&lt;/p&gt;

&lt;p&gt;If I were to rename his headers a bit, the possible options I see him suggesting include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Modification of glyphs (Obscurity)&lt;/li&gt;
  &lt;li&gt;Additional glyphs (error bars and other overlays)&lt;/li&gt;
  &lt;li&gt;Standalone visualizations (e.g. showing distributions)&lt;/li&gt;
  &lt;li&gt;Animation (Simulation)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These categories are a bit generic, and are probably not comprehensive, but provide one way to slice up the uncertainty visualization space.&lt;/p&gt;

&lt;h3 id=&quot;data-types&quot;&gt;Data Types&lt;/h3&gt;

&lt;p&gt;The other dimension we might split on is around different types of data that exist and thus can have uncertainty associated with them. Here I’m talking about &lt;a href=&quot;https://en.wikipedia.org/wiki/Statistical_data_type&quot;&gt;statistical data types&lt;/a&gt; as opposed to data types of a particular programming language. Briefly, the main data types I like to think about are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Categorical (sometimes called &lt;a href=&quot;http://www.mymarketresearchmethods.com/types-of-data-nominal-ordinal-interval-ratio/&quot;&gt;nominal&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Ordinal (where the values are discrete, but order matters)&lt;/li&gt;
  &lt;li&gt;Quantitative (aka continuous or real-valued)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To this basic list, we can add a few more types that I believe warrant separating:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Temporal (dates, hours, minutes - time is special!)&lt;/li&gt;
  &lt;li&gt;Spatial (or geographical, e.g. lat &amp;amp; lon values)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;an-uncertain-taxonomy&quot;&gt;An Uncertain Taxonomy&lt;/h3&gt;

&lt;p&gt;With the possible values set for these two axes, we get a grid of possibilities to explore. And everyone knows that when there’s a grid, there’s a taxonomy! This table provides a tiny framework by which we can start to categorize existing uncertainty visualizations. It also provides a bit of inspiration for where one might explore to create novel uncertainty visuals.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/uncertainty/taxonomy_grid.png&quot; alt=&quot;taxonomy grid&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This grid is super coarse in its capabilities to catalog. It’s my thought that each of the above “visualization methods” could be expanded further, either based on particular encoding options or perhaps by which &lt;a href=&quot;https://eagereyes.org/papers/shaping-of-information-by-visual-metaphors&quot;&gt;visual metaphors&lt;/a&gt; are used, which would form a sort of taxonomy cube!&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/uncertainty/taxonomy_cube.png&quot; alt=&quot;taxonomy cube&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Our ultimate hope with our experimentation was to explore this entire cube, but for now I will just provide some examples from a tiny corner of the taxonomy.&lt;/p&gt;

&lt;p&gt;(Also, I think there is a lot more to say about visual metaphors in data vis, but that is a topic for another time).&lt;/p&gt;

&lt;h2 id=&quot;uncertainty-and-simulation&quot;&gt;Uncertainty and Simulation&lt;/h2&gt;

&lt;p&gt;The area I really wanted to explore more was around how animation was used to visualize the notion of simulating possible outcomes from an uncertain future. As the reactions around the &lt;a href=&quot;https://www.nytimes.com/2018/03/13/upshot/needle-forecast-pennsylvania-special-election.html&quot;&gt;NYT Election Needle&lt;/a&gt; indicated, animation can be a very motivating when displaying uncertainty.&lt;/p&gt;

&lt;p&gt;Fortunately, there is some prior work in this area. Jessica Hulman et al have developed &lt;a href=&quot;http://idl.cs.washington.edu/papers/hops/&quot;&gt;HOP Plots&lt;/a&gt; which I see fitting very nicely in grid for using animation to visualize uncertainty around &lt;strong&gt;quantitative&lt;/strong&gt; values. You can find a nice write up on the &lt;a href=&quot;https://medium.com/hci-design-at-uw/hypothetical-outcomes-plots-experiencing-the-uncertain-b9ea60d7c740&quot;&gt;UW Interactive Data Lab Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some basic recreations of the HOP plot idea where I’ve added a stop/start button, but left out any scale or annotation.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;offset-by-two four columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;A slow HOP plot:&lt;/p&gt;
    &lt;div id=&quot;hop2&quot;&gt;&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class=&quot;four columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;A fast HOP plot:&lt;/p&gt;
    &lt;div id=&quot;hop1&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;As an exercise, we experimented with showing a history of simulations using &lt;a href=&quot;https://en.wikipedia.org/wiki/Onion_skinning&quot;&gt;onion skinning&lt;/a&gt;, which I deemed the “Onion HOP Plot”:&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;offset-by-two four columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;A slow Onion HOP plot:&lt;/p&gt;
    &lt;div id=&quot;hop4&quot;&gt;&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class=&quot;four columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;A fast Onion HOP plot:&lt;/p&gt;
    &lt;div id=&quot;hop3&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;So, using this existing work as guidance, we started thinking about how animation could be used to display uncertainty for these other data types. I’m excited to start to fill in two additional little boxes in the grid for animation and categorical uncertainty and geographic uncertainty.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/uncertainty/taxonomy_grid_filled.png&quot; alt=&quot;taxonomy grid&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;morph-icons&quot;&gt;Morph Icons&lt;/h3&gt;

&lt;p&gt;Let’s start with the simpler of the two: using animation to visualize uncertainty around categorical data.&lt;/p&gt;

&lt;p&gt;Consider some categorical data that can each be one of a few possible values. Say also that these possible values can be represented as icons. Here is our universe of possible iconic values:&lt;/p&gt;

&lt;div id=&quot;iconsall&quot; class=&quot;u-cf&quot;&gt;&lt;/div&gt;

&lt;p&gt;The kicker is that for any particular data point, we aren’t 100% certain which value it should be classified as. And so for each data point we have probabilities associated with a subset of these categories.&lt;/p&gt;

&lt;p&gt;The specifics of &lt;em&gt;what&lt;/em&gt; this data is, is hopefully somewhat generic - and not all that important to the visualization method. Perhaps this is an automatic labelling of a set of images by a computer algorithm, or some other classification problem with a finite number of possible categories.&lt;/p&gt;

&lt;p&gt;Our &lt;strong&gt;Morphing Icons&lt;/strong&gt; idea is a pretty simple one: take those probabilities associated with each possible category and show each icon for a length of time based on that probability. So, if we are 90% certain an item is of type A and 10% it is of type B, then show type A’s icon 90% of the time, and type B’s 10%.&lt;/p&gt;

&lt;p&gt;Here’s examples using 2 and 3 possible icons:&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;offset-by-two four columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Morphing Icon with 2 types:&lt;/p&gt;
    &lt;div id=&quot;icon1&quot; class=&quot;icon-container u-cf&quot;&gt;&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class=&quot;four columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Morphing Icon with 3 types:&lt;/p&gt;
    &lt;div id=&quot;icon2&quot; class=&quot;icon-container u-cf&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The morphing icon on the left is showing 50% A and 50% C probabilities. The one on the right is showing 70% A, 20% D, and 10% E.&lt;/p&gt;

&lt;p&gt;Here are a few other examples, just for fun:&lt;/p&gt;

&lt;div id=&quot;othericons&quot; class=&quot;u-cf&quot;&gt;
  &lt;div id=&quot;icon3&quot;&gt;&lt;/div&gt;
  &lt;div id=&quot;icon4&quot;&gt;&lt;/div&gt;
  &lt;div id=&quot;icon5&quot;&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Of course there are all sorts of caveats and limitations to this approach to displaying categorical uncertainty. It breaks down if there are too many possible categorical values, or if there are no acceptable icon representations. It’s also unclear how long each loop of the animation should take.&lt;/p&gt;

&lt;p&gt;Also, while this visual certainly uses animation, it is not &lt;em&gt;really&lt;/em&gt; a simulation of the possible data. A real simulation would draw results based on the associated probabilities and thus flash back and forth between categories rapidly, based on which one was selected each iteration.&lt;/p&gt;

&lt;p&gt;All that being said, I still enjoyed this representation. One could imagine a toggleable ‘detail’ view that showed the probabilities explicitly when needed.&lt;/p&gt;

&lt;h3 id=&quot;wandering-dots&quot;&gt;Wandering Dots&lt;/h3&gt;

&lt;p&gt;The other prototype I wanted to show also uses animation to show uncertainty, but this time for spatial data.&lt;/p&gt;

&lt;p&gt;Here we have a very similar problem. Say we have events that happen somewhere in a particular region of the world. We want to display them, but don’t know exactly where they happened. For whatever reason, we only know the location of each event at some &lt;em&gt;resolution&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For example, the data might have a group of events as happening at a particular city, but another group we might only know the county or state they occured in. These resolution levels thus indicate the amount of uncertainty associated with each event location.&lt;/p&gt;

&lt;p&gt;One of the approaches we experimented with tackling this type of uncertainty with animation was what we called &lt;strong&gt;Wandering Dots&lt;/strong&gt;. The idea again, is nothing mind-blowing, and has plenty of drawbacks, but is still interesting (at least to me).&lt;/p&gt;

&lt;p&gt;With Wandering Dots, each event is representing as a dot (genius!). Each dot is animated to indicate the resolution of the data. Dots wander far (have a larger radius) for events that we are more uncertain about.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;six columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Wandering Dots with a large radius:&lt;/p&gt;
    &lt;div id=&quot;dot1&quot;&gt;&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class=&quot;six columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Wandering Dots with a small radius:&lt;/p&gt;
    &lt;div id=&quot;dot2&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The wandering is random within the constraints of their assigned radius. But they maintain a fluid trajectory, instead of hoping all over the place, to all the following of an individual event, if need be.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;six columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Wandering Dots with many points:&lt;/p&gt;
    &lt;div id=&quot;dotc1&quot;&gt;&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class=&quot;six columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Wandering Dots with few points:&lt;/p&gt;
    &lt;div id=&quot;dotc3&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;wandering-hulls&quot;&gt;Wandering Hulls&lt;/h3&gt;

&lt;p&gt;Briefly, we also explored the idea of a using a solid plane to represent this uncertainty, called &lt;strong&gt;Wandering Hulls&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;six columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Wandering Hull with large radius:&lt;/p&gt;
    &lt;div id=&quot;hull1&quot;&gt;&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class=&quot;six columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Wandering Hull with small radius:&lt;/p&gt;
    &lt;div id=&quot;hull3&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The idea was that we could perhaps use a choropleth approach with these hulls. However, the lack of access to individual points, as well as worries around occlusion, made us abandon this idea from further exploration.&lt;/p&gt;

&lt;h3 id=&quot;bounded-wandering-dots&quot;&gt;Bounded Wandering Dots&lt;/h3&gt;

&lt;p&gt;Back with our dots, often times the level of resolution for an uncertain spatial data point corresponds with a particular geographic region - like a county or state.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://peterbeshai.com/&quot;&gt;Peter Beshai&lt;/a&gt; made a clever variant, the &lt;strong&gt;Bounded Wandering Dot&lt;/strong&gt; which constrains the wandering to a specific shape.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;six columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Wandering Dots bounded by a square:&lt;/p&gt;
    &lt;div id=&quot;wdot1&quot;&gt;&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class=&quot;six columns&quot;&gt;
    &lt;p class=&quot;label&quot;&gt;Wandering Dots bounded by a map region:&lt;/p&gt;
    &lt;div id=&quot;wdot3&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Pretty cool right?&lt;/p&gt;

&lt;h2 id=&quot;an-uncomfortable-analysis&quot;&gt;An Uncomfortable Analysis&lt;/h2&gt;

&lt;p&gt;As part of our research, some of these prototypes were cleaned up and incorporated with other visuals into a dashboard-style tool for a small group of analysts to try out for a set of decision making activities.&lt;/p&gt;

&lt;p&gt;Unfortunately we didn’t perform a controlled academic study around these representations, but we did get some initial impressions and feedback from these users.&lt;/p&gt;

&lt;p&gt;One of the main pieces of feedback that has stuck with me is that the shifting visual representation made them feel a bit &lt;em&gt;uncomfortable&lt;/em&gt;. But uncomfortable in a good way!&lt;/p&gt;

&lt;p&gt;With more traditional uncertainty visualizations it can be easy to see the level of uncertainty, but ultimately ignore it, choosing the average over the error-bars, for example. While simpler aggregates are easy additions to these visuals, the animation provides perhaps a more visceral experience of the uncertainty that is harder to ignore.&lt;/p&gt;

&lt;h2 id=&quot;filling-in-the-cube&quot;&gt;Filling in the Cube&lt;/h2&gt;

&lt;p&gt;These quick examples are almost certainly &lt;strong&gt;not&lt;/strong&gt; the “best” ways to represent uncertainty in these data types, but they are a start.&lt;/p&gt;

&lt;p&gt;With more research in this area, I’m excited about the expansion and improvement to our informal taxonomy, as well as how other areas of the cube will be filled in with more ways to show the unknown. There are a lot of visual encodings and associated visual metaphors that can, and should be experimented with in this area. I’m looking forward to experimenting more in the future - and seeing how others tackle this uncertain issue!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>An Introduction to Altair</title>
   <link href="http://vallandingham.me/altair_intro.html"/>
   <updated>2018-03-23T00:00:00+00:00</updated>
   <id>http://vallandingham.me/altair_intro</id>
   <content type="html">&lt;p&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/altair/banner.png&quot; alt=&quot;Triangle Example&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Recently I attended a wonderful talk by &lt;a href=&quot;https://twitter.com/jakevdp&quot;&gt;Jake VanderPlas&lt;/a&gt; (and hosted by the always astute &lt;a href=&quot;https://twitter.com/astrobiased&quot;&gt;Eli Bressert&lt;/a&gt;) about a wonderful package he has been working on to make visualization in python easier.&lt;/p&gt;

&lt;p&gt;As a long time &lt;a href=&quot;http://ggplot2.tidyverse.org/&quot;&gt;ggplot2&lt;/a&gt; user, I’m quick to bemoan the challenges of succinctly visualizing data in python. While there are many visualization packages out there, none of them seem to approach the intuitiveness, completeness, and consistency found in R’s go-to tooling.&lt;/p&gt;

&lt;p&gt;I’m happy to say that this new python package &lt;a href=&quot;https://altair-viz.github.io/index.html&quot;&gt;Altair&lt;/a&gt; might put an end to my grumblings (and yours) once and for all.&lt;/p&gt;

&lt;p&gt;I’d like to take you through the basics of experimenting with Altair to show a bit of what it can do. None of my ramblings is really more than what you will find in &lt;a href=&quot;https://altair-viz.github.io/getting_started/overview.html&quot;&gt;the documentation&lt;/a&gt;, but I will describe some of my experiences in starting to learn how to use this tool.&lt;/p&gt;

&lt;h2 id=&quot;what-is-altair&quot;&gt;What is Altair?&lt;/h2&gt;

&lt;p&gt;Altair provides a way to write declarative data visualization code in python by harnessing the power of &lt;a href=&quot;https://vega.github.io/vega/&quot;&gt;Vega&lt;/a&gt; and &lt;a href=&quot;https://vega.github.io/vega-lite/&quot;&gt;Vega-Lite&lt;/a&gt;. Ok, so what is Vega?&lt;/p&gt;

&lt;p&gt;Vega is a visualization grammer (think &lt;a href=&quot;http://vita.had.co.nz/papers/layered-grammar.html&quot;&gt;Grammar of Graphics&lt;/a&gt; the concepts that ggplot2 is built around) that can be written as a JSON specification. Vega-lite provides most of the power of Vega in a much more compact form by relying on smart defaults and simpler encodings.&lt;/p&gt;

&lt;p&gt;Vega-lite provides a format to specify data, data encodings, and even &lt;a href=&quot;https://vega.github.io/vega/docs/event-streams/&quot;&gt;interactions&lt;/a&gt;, all in a relatively simple and intuitive specification.&lt;/p&gt;

&lt;p&gt;These packages and &lt;a href=&quot;https://vega.github.io/&quot;&gt;many more&lt;/a&gt; have been created out of the blood, sweat, and tears of the &lt;a href=&quot;https://idl.cs.washington.edu/&quot;&gt;UW Interactive Data Lab&lt;/a&gt;. &lt;a href=&quot;https://twitter.com/arvindsatya1&quot;&gt;Arvind&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/kanitw&quot;&gt;Ham&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/domoritz&quot;&gt;Dom&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/jeffrey_heer&quot;&gt;Jeff&lt;/a&gt;, and all the rest: we can’t thank you enough for this vision and these amazing tools!&lt;/p&gt;

&lt;p&gt;Anyway, back to Altair.&lt;/p&gt;

&lt;p&gt;Altair provides a way to generate these Vega-lite specifications using an intuitive and pythonic API. So we can write python, but get out Vega-Lite. Intrigued? Then let’s get started!&lt;/p&gt;

&lt;h2 id=&quot;jupyterlab-experimentation&quot;&gt;JupyterLab Experimentation&lt;/h2&gt;

&lt;p&gt;All my experimentation has been done using the newly-ready-for-use &lt;a href=&quot;https://blog.jupyter.org/jupyterlab-is-ready-for-users-5a6f039b8906&quot;&gt;JupyterLab&lt;/a&gt;, the successor to Jupyter Notebooks.&lt;/p&gt;

&lt;p&gt;JupyterLab provides an updated and richer IDE-like experience for building interactive notebooks. While the new features, like an integrated text editor and terminal console, are interesting, the real exciting stuff is under the hood!&lt;/p&gt;

&lt;p&gt;It has been built from the ground up using a plugin-based architecture providing consistent and powerful ways to integrate new features through different types of plugins. One type of plugin, &lt;a href=&quot;http://jupyterlab.readthedocs.io/en/latest/developer/extension_dev.html#mime-renderer-extensions&quot;&gt;Mime Renderer Extensions&lt;/a&gt; allows for custom Javascript-based views of different filetypes.&lt;/p&gt;

&lt;p&gt;It is exactly this new feature that Altair leverages. It generates the Vega-Lite spec and passes it off to the built-in Vega renderer to be visualized.&lt;/p&gt;

&lt;h2 id=&quot;installation-and-setup&quot;&gt;Installation and Setup&lt;/h2&gt;

&lt;p&gt;These instructions are based on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;jupyterlab v0.31.8&lt;/li&gt;
  &lt;li&gt;altair v2.0.0rc1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And might need a bit of updating as Altair is developed. First, I created a new python 3 &lt;a href=&quot;https://conda.io/docs/user-guide/tasks/manage-environments.html#creating-an-environment-with-commands&quot;&gt;conda environment&lt;/a&gt; to work in. Then installed jupyterlab via pip:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;jupyterlab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To install the latest Altair, you need to supply the specific version at the moment:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;altair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;2.0.0rc1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, I had to add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vega3&lt;/code&gt; JupyterLab extension, but this step won’t be necessary for future JupyterLab versions:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jupyter labextension &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; @jupyterlab/vega3-extension
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now open your lab with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jupyter lab&lt;/code&gt; and start a new Python 3 notebook to get started!&lt;/p&gt;

&lt;h2 id=&quot;our-first-altair&quot;&gt;Our First Altair&lt;/h2&gt;

&lt;p&gt;We can start with the ‘Hello World’ of Altair. To do this we first need to import the package.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;altair&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then load some data. Handily, Altair provides some default datasets. We will start with the classic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cars&lt;/code&gt; dataset.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'cars'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s visualize this dataset.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Miles_per_Gallon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: The result is a Vega-Lite specification that is rendered automatically inside of JupyterLab. To show the result in this post, I will use the handy-dandy &lt;a href=&quot;https://github.com/vega/vega-embed&quot;&gt;Vega Embed&lt;/a&gt; to display the spec below.&lt;/p&gt;

&lt;div id=&quot;spec1&quot;&gt;&lt;/div&gt;

&lt;p&gt;Pretty impressive, right? Let’s break this code down a bit.&lt;/p&gt;

&lt;p&gt;First, we are creating a &lt;a href=&quot;https://altair-viz.github.io/user_guide/API.html#altair.Chart&quot;&gt;Chart&lt;/a&gt; instance and passing it the data that will be visualized. Next, we indicate what kind of &lt;a href=&quot;https://altair-viz.github.io/user_guide/marks.html&quot;&gt;Mark&lt;/a&gt; to use in the visualization. For a dot plot, we want the ‘point’ mark, but as we will see, there is a suite of marks to choose from. Finally, each mark has a number of possible ‘channels’ to encode data with. We set these in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encoding()&lt;/code&gt; method, passing in attributes (columns) of our data to use to encode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Again, if you are a ggplot2 user, you can start to see why I was so excited to try Altair! Marks are just another word for &lt;a href=&quot;http://ggplot2.tidyverse.org/reference/#section-layer-geoms&quot;&gt;Geoms&lt;/a&gt;, and encodings look almost exactly like your typical &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aes()&lt;/code&gt; mapping! If you’re not a ggplot2 user, ignore all that - and just marvel at the intuitive reading of the Altair code!&lt;/p&gt;

&lt;h2 id=&quot;same-chart-different-data&quot;&gt;Same Chart, Different Data&lt;/h2&gt;

&lt;p&gt;Now I know these test datasets are boring and dumb and boring and useless and boring. &lt;a href=&quot;https://eagereyes.org/blog/2018/how-to-get-excited-about-standard-datasets&quot;&gt;Robert Kosara&lt;/a&gt; is one of many voices I have heard in the recent past driving this point home.&lt;/p&gt;

&lt;p&gt;If there is one rational to possibly hide my laziness behind, it is that when using a boring dataset for an introductory tutorial we can focus more on the tool used to visualize it, rather than spend time looking for insights in the data. A pitiful rational, I know, so before we move on, I wanted to show how easy it can be to load up your own data and visualize with Altair.&lt;/p&gt;

&lt;p&gt;So we will use the wonderful &lt;a href=&quot;https://github.com/fivethirtyeight/data/tree/master/candy-power-ranking&quot;&gt;FiveThirtyEight data repository&lt;/a&gt; to pick out a dataset about &lt;a href=&quot;http://fivethirtyeight.com/features/the-ultimate-halloween-candy-power-ranking/&quot;&gt;people’s favorite candy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how you would load and visualize this data using &lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;pandas&lt;/a&gt; and Altair:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;candy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'candy-data.csv'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;candy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'sugarpercent'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'winpercent'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'hard:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec4&quot;&gt;&lt;/div&gt;

&lt;p&gt;Nearly the same command, but completely different data (we will explain that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:N&lt;/code&gt; in a second).&lt;/p&gt;

&lt;p&gt;Most of the rest of this tutorial will be using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cars&lt;/code&gt; dataset because of my slovenliness, but keep in mind the ideas can be applied to any data.&lt;/p&gt;

&lt;h2 id=&quot;marks-marks-everywhere&quot;&gt;Marks Marks Everywhere&lt;/h2&gt;

&lt;p&gt;This marks and encodings pattern starts to really shine when you want to visualize the same data differently, using different marks. Let’s make a &lt;em&gt;bad&lt;/em&gt; visualization by replacing our points with bars:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Miles_per_Gallon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec2&quot;&gt;&lt;/div&gt;

&lt;p&gt;We can see the only things that have changed are the use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mark_bar()&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mark_point()&lt;/code&gt;, and the additional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x2&lt;/code&gt; encoding. And with those small changes, we have a whole visualization!&lt;/p&gt;

&lt;p&gt;Each chart can be further customized with constants provided at the mark or encoding level. For example, the opacity for each bar can be reduced by just passing in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opacity&lt;/code&gt; option to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mark_bar()&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Miles_per_Gallon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec3&quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;faceting&quot;&gt;Faceting&lt;/h2&gt;

&lt;p&gt;One feature I always look for in a new visualization tool or package is faceting based on a categorical variable. When dealing with matplotlib, this kind of visualization typically requires loops to create, which I feel takes you out of the ‘what’ you are trying to visualize and keeps you stuck in the ‘how’. Fortunately, Altair doesn’t require this cognitive break.&lt;/p&gt;

&lt;p&gt;You can just use the &lt;a href=&quot;https://altair-viz.github.io/user_guide/compound_charts.html#faceted-charts&quot;&gt;facet()&lt;/a&gt; method!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Miles_per_Gallon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec5&quot;&gt;&lt;/div&gt;

&lt;p&gt;Notice the strange &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Q&lt;/code&gt; trailing our data attribute. This is a special shorthand to indicate to Vega-Lite what type of data value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Origin&lt;/code&gt; is. While you might think that the tool should be able to figure this out automatically, remember we are ultimately just building up a JSON specification - and so some of these nuances need to be supplied explicitly.&lt;/p&gt;

&lt;h2 id=&quot;a-grammar-of-interaction&quot;&gt;A Grammar of Interaction&lt;/h2&gt;

&lt;p&gt;Ok. Grammar of Graphics, big deal right? You could imagine any number of tools and specifications to implement these concepts, so what makes Vega, and thus Altair any different?&lt;/p&gt;

&lt;p&gt;Recently, through some amazing work by the Vega team, Vega and Vega-lite now include a sort of “Grammar of Interaction”.&lt;/p&gt;

&lt;p&gt;This means our specifications can encode not just our data visualizations, but what happens when people interact with our visualizations!&lt;/p&gt;

&lt;p&gt;We can get a simple pan-and-zoom interaction on any chart in Altair by simply adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interactive()&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Miles_per_Gallon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec6&quot;&gt;&lt;/div&gt;

&lt;p&gt;But this is only the beginning! With Altair, we can build up much more complex interactions using &lt;a href=&quot;https://altair-viz.github.io/user_guide/interactions.html&quot;&gt;selections&lt;/a&gt;. As the Vega-Lite documentation &lt;a href=&quot;https://vega.github.io/vega-lite/docs/selection.html&quot;&gt;puts it&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;They map user input (e.g., mouse moves and clicks, touch presses, etc.) into data queries, which can subsequently be used to drive conditional encoding rules, filter data points, or determine scale domains.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Altair comes with 3 basic selection types:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selection_single()&lt;/code&gt; - for interacting with a single element at a time.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selection_multi()&lt;/code&gt; - for selecting multiple items at once through clicking or mouseover.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selection_interval()&lt;/code&gt; - for selecting multiple items through a brushing interaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example of using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selection_interval()&lt;/code&gt; to make a brush interaction that works across our previously faceted chart.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;brush&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selection_interval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Miles_per_Gallon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;brush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'lightgray'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;selection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;brush&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A few interesting pieces come out of this example. First, we can see we pass this brush into our chart as its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selection&lt;/code&gt; property. Next, we use it as part of a &lt;a href=&quot;https://altair-viz.github.io/user_guide/API.html#altair.condition&quot;&gt;condition&lt;/a&gt; - which allows us to use an if-else concept to encode the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt; channel. If the point is included in the current brush, it will be colored based on its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Origin&lt;/code&gt;, else it will be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lightgray&lt;/code&gt;. Try it out below by clicking and dragging the mouse.&lt;/p&gt;

&lt;div id=&quot;spec7&quot;&gt;&lt;/div&gt;

&lt;p&gt;We will play a bit more with selections later on in the tutorial.&lt;/p&gt;

&lt;h2 id=&quot;summarizing-your-data&quot;&gt;Summarizing Your Data&lt;/h2&gt;

&lt;p&gt;Often times we are interested in visualizing an aggregation of the data, rather then just raw values. Altair comes equipped with a number of &lt;a href=&quot;https://altair-viz.github.io/user_guide/encoding.html#binning-and-aggregation&quot;&gt;aggregation and binning&lt;/a&gt; functions that can be applied to specific encoding.&lt;/p&gt;

&lt;p&gt;For example, we can use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count()&lt;/code&gt; aggregation to turn our faceted scatterplot into a histogram.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'count(*):Q'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec8&quot;&gt;&lt;/div&gt;

&lt;p&gt;In this example we also see an alternative way to specify encodings. Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alt.X()&lt;/code&gt; we can provide options to the encoding, like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;And, as you might expect, this default binning can be customized. Altair provides the &lt;a href=&quot;https://altair-viz.github.io/user_guide/API.html#altair.BinParams&quot;&gt;BinParams&lt;/a&gt; object to manage binning specifics.&lt;/p&gt;

&lt;p&gt;Here’s the same chart, but with 40 bins per facet.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BinParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxbins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'count(*):Q'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec9&quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;layering-marks&quot;&gt;Layering Marks&lt;/h2&gt;

&lt;p&gt;We will wrap up this tutorial with a look at how to combine charts to make much more sophisticated visualizations.&lt;/p&gt;

&lt;p&gt;First, we can &lt;a href=&quot;https://altair-viz.github.io/user_guide/compound_charts.html#layered-charts&quot;&gt;layer charts&lt;/a&gt; on top of one another to make Marks that are available by default.&lt;/p&gt;

&lt;p&gt;Altair provides the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layer()&lt;/code&gt; method to do this, as well as a shorthand version using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; operator.&lt;/p&gt;

&lt;p&gt;Here is an example of using this capability to create a box-and-whisker plot (derived from one of the &lt;a href=&quot;https://altair-viz.github.io/gallery/boxplot_max_min.html&quot;&gt;newly created examples&lt;/a&gt;). It uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layer()&lt;/code&gt; so that the data doesn’t have to be repeated over and over in the chart. Also note the use of a base chart that each piece of the box plot reuse.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;boxplot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ytype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Q'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# make all the aggregation strings up front
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;min_agg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'min(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ytype&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;max_agg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'max(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ytype&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;median_agg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'median(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ytype&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;q1_agg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'q1(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ytype&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;q3_agg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'q3(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ytype&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x_val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xtype&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# create a single base chart
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# which the other layers will
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# be augmented from
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_val&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# now we only need to specify what is unique
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# to each layer!
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;whisker_low&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_agg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q1_agg&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;box&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q1_agg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q3_agg&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;midline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_tick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'white'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;median_agg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;median_agg&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;whisker_high&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_agg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q3_agg&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# combine with layer()
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;whisker_low&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;whisker_high&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;midline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# now we can use this function
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;boxplot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec10&quot;&gt;&lt;/div&gt;

&lt;p&gt;Pretty cool, right?&lt;/p&gt;

&lt;h2 id=&quot;layers-and-interactions&quot;&gt;Layers and Interactions&lt;/h2&gt;

&lt;p&gt;We can use interaction with layered charts too!&lt;/p&gt;

&lt;p&gt;Here is a quick attempt at an scatterplot that shows more details when hovering over each point. The text is a separate layer that is conditionally displayed.&lt;/p&gt;

&lt;p&gt;We get to see &lt;a href=&quot;https://altair-viz.github.io/user_guide/API.html#altair.selection_single&quot;&gt;selection_single()&lt;/a&gt; in action, which allows us to select one thing at a time. We can customize it to make it work on mouseover.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# the 'empty' setting makes all text hidden before any mouseover occurs.
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selection_single&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'mouseover'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nearest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'none'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Miles_per_Gallon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;align&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'left'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div id=&quot;spec11&quot;&gt;&lt;/div&gt;

&lt;p&gt;As for real tooltips, the relevant parties are &lt;a href=&quot;https://github.com/altair-viz/altair/issues/240&quot;&gt;still discussing the details&lt;/a&gt;, but I’m sure something will be figured out soon.&lt;/p&gt;

&lt;h2 id=&quot;concatenating-charts&quot;&gt;Concatenating Charts&lt;/h2&gt;

&lt;p&gt;Another way charts can be combined in Altair is through concatenation. We can concatenate charts either vertically or horizontally.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alt.vconcat()&lt;/code&gt; method or the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; operand is used to vertically concat.&lt;/li&gt;
  &lt;li&gt;The&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alt.hconcat()&lt;/code&gt; method or the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; operand is used to horizontally concat.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s finish with an interactive dashboard made from two charts. Brushing on the top chart filters the bottom one. This chart uses Altair’s &lt;a href=&quot;https://altair-viz.github.io/user_guide/transform.html&quot;&gt;data transformation&lt;/a&gt; to filter the bottom chart based on the selection. We won’t discuss this feature more, but definitely worth exploring!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;brush&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'interval'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# the top scatterplot
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Horsepower:Q'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Miles_per_Gallon:Q'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;brush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Origin:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'lightgray'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;selection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;brush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# the bottom bar plot
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Origin:N'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'count(Origin):Q'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;brush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# the filter transform uses the selection
&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;# to filter the input data to this chart
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vconcat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Make sure to brush around on the top chart!&lt;/em&gt;&lt;/p&gt;

&lt;div id=&quot;spec12&quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;limitations-and-looking-forward&quot;&gt;Limitations and Looking Forward&lt;/h2&gt;

&lt;p&gt;Hopefully this long drawn out demo of Altair at least gets people excited about the potential for this tool and the promise of declarative chart making in python.&lt;/p&gt;

&lt;p&gt;That being said, like any great thing, there are some caveats. Here are a few:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The API is still pretty new. Some of this could break!&lt;/li&gt;
  &lt;li&gt;The documentation is still incomplete. Sometimes you need to look at Altair and Vega-Lite docs to find an answer.&lt;/li&gt;
  &lt;li&gt;The number of data points Altair can handle is currently pretty low. Right now it is capped at 5,000, but that is modifiable.&lt;/li&gt;
  &lt;li&gt;As noted above, tooltips are still on the way.&lt;/li&gt;
  &lt;li&gt;It would be cool to have the ability to extend Altair to make new Mark/encoding types. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boxplot&lt;/code&gt; function above would then be created inline as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alt.mark_boxplot()&lt;/code&gt; or something similar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But even with these slight short-comings, I am excited about this great new package, and can’t wait to try it on more interesting datasets in the future. I hope you are excited too!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Multivariate Map Collection</title>
   <link href="http://vallandingham.me/multivariate_maps.html"/>
   <updated>2017-12-10T00:00:00+00:00</updated>
   <id>http://vallandingham.me/multivariate_maps</id>
   <content type="html">&lt;p&gt;There are many types of maps that are used to display data. &lt;a href=&quot;http://axismaps.github.io/thematic-cartography/articles/choropleth.html&quot;&gt;Choropleths&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Cartogram&quot;&gt;Cartograms&lt;/a&gt; provide two great examples. I gave a talk, long long ago, about some of &lt;a href=&quot;http://vallandingham.me/city_camp_abstract_maps_notes.html&quot;&gt;these map varieties&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most of these more common map types focus on a particular variable that is displayed. But what if you have multiple variables that you would like to present on a map at the same time?&lt;/p&gt;

&lt;p&gt;Here is my attempt to collect examples of multivariate maps I’ve found and organize them into a loose categorization. Follow along, or dive into the references, to spur on your own investigations and inspirations!&lt;/p&gt;

&lt;p&gt;Before we begin, certainly you’ve heard by now that, even for geo-related data, a map is &lt;em&gt;not&lt;/em&gt; always the right answer. With this collection, I am just trying to enumerate the various methods that have been attempted, without too much judgement as to whether it is a ‘good’ or ‘bad’ encoding. Ok? Ok!&lt;/p&gt;

&lt;h2 id=&quot;3d&quot;&gt;3D&lt;/h2&gt;

&lt;p&gt;With the interactivity available to the modern map maker, it is not surprising that extending into the third dimension is a popular way to encode data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chicago Energy Map&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/chicago_energy_2.png&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;http://chicagoenergy.datascopeanalytics.com/&quot;&gt;Datascope Analysis Chicago Energy Data Map&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above uses color and 3D height to encode natural gas and electric efficiencies of various neighborhoods in Chicago. It doesn’t provide freeform rotation, but does allow you to rotate to different cardinal directions, which helps with the occlusion. This tool also provides a detailed census block view of the data after clicking a neighborhood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Median Household Income&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/incomes2_small.jpg&quot; alt=&quot;&quot; style=&quot;&quot; data-zoom-target=&quot;https://vallandingham.me/images/multivar_map/incomes2.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;http://metrocosm.com/income-us-cities-1970-2015/&quot;&gt;Visualizing America’s Middle Class Squeeze&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Created by &lt;a href=&quot;https://twitter.com/galka_max&quot;&gt;Max Galka&lt;/a&gt;, this map duel encodes median household income for various cities using both color and tract height. This makes it not strictly multivariate, but it uses the same ideas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choropleth Hillshade&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/hillshades.png&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://github.com/jwasilgeo/choropleth-hillshade&quot;&gt;Choropleth Hillshade&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This tool is provided as an ArcGIS add-on for creating hillshaded versions of choropleth maps. I don’t use ArcGIS, but its interesting to see a generic tool to create these kinds of maps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Topographical Crime Maps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/3d_crime.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;http://www.neatorama.com/2010/06/08/topographical-crime-maps/#!nT1i3&quot;&gt;Topographical Crime Maps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was created by &lt;a href=&quot;http://dougmccune.com/blog/&quot;&gt;Doug McCune&lt;/a&gt;. It is not really multivariate, but I always really loved the style where he retains the basemap visual but uses hillshading to show geo-data in a very organic way. It seems like a technique that should have caught on more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Mountains&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/datamountains_small.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://carto.com/blog/data-mountains/&quot;&gt;CartoDB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Taking the idea from exact shapes toward less precise icons are CartoDB’s Data Mountains. These maps use color and “mountain” size to encode multiple variables. The idea reminds me very much of &lt;a href=&quot;http://spatial.ly/2014/08/population-lines/0/&quot;&gt;geo-based Joyplots&lt;/a&gt;, like this great “&lt;a href=&quot;https://bl.ocks.org/armollica/d19483f314189df73fe0235bc633ae59&quot;&gt;Joymap&lt;/a&gt;” from &lt;a href=&quot;https://twitter.com/armollica&quot;&gt;Andrew Mollica&lt;/a&gt; showing the population density of Wisconsin:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/joymap.png&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;color&quot;&gt;Color&lt;/h2&gt;

&lt;p&gt;The idea of using color alone to represent &lt;em&gt;multiple&lt;/em&gt; pieces of data may seem strange, but it can happen! Let’s take a look at a few examples&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bivariate Choropleth Maps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/health_bivariate_small.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://qz.com/1008167/map-donald-trumps-mean-mean-mean-health-care-bill-is-meanest-to-his-most-crucial-voters/&quot;&gt;Quartz: Where Medicaid Cuts Hit Hardest&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This map of Trump voters vs Medicaid coverage is just one example of a somewhat popular technique. &lt;a href=&quot;https://twitter.com/jscarto&quot;&gt;Joshua Stevens&lt;/a&gt; has a great article with &lt;a href=&quot;http://www.joshuastevens.net/cartography/make-a-bivariate-choropleth-map/&quot;&gt;everything you ever wanted to know about bivariate choropleths&lt;/a&gt;, so make sure you check that out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trivariate Choropleth Map&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/earnings_small.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://www.good.is/infographics/america-s-richest-counties-and-best-educated-counties#open&quot;&gt;Good: Reading, Writing, and Earning Money&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you thought two colors were hard, wait till you see three! This map generated a &lt;a href=&quot;http://flowingdata.com/2011/01/18/open-thread-is-this-map-too-confusing/&quot;&gt;lot&lt;/a&gt; of &lt;a href=&quot;https://thesocietypages.org/graphicsociology/2011/04/05/reading-writing-earning-bad-good-graphic/&quot;&gt;musings&lt;/a&gt; back in 2011, so be sure to check out all the heat it garnered before trying to emulate it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trivariate Dot Map&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/trees.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://hi.stamen.com/trees-cabs-crime-in-the-venice-biennale-968ea4983177&quot;&gt;Stamen: Trees, Cabs &amp;amp; Crime&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally created in 2009 by Shawn Allen while he was at Stamen, this artistic piece no doubt influenced the trivariate choropleth we just looked at. With the city-level data in the dot map, you can see more interesting patterns (if you are familiar with San Francisco).&lt;/p&gt;

&lt;h2 id=&quot;small-multiples&quot;&gt;Small Multiples&lt;/h2&gt;

&lt;p&gt;If one of the variables you are visualizing is categorical in nature, it is possible to show a multitude of maps, one for each category. That is what we find in the map below.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/small_mult1.png&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;http://andrewgelman.com/2009/07/15/hard_sell_for_b/&quot;&gt;Andrew Gelman: Estimates of support for School Vouchers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They also have a modified version with a different color scheme:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/small_mult2.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;http://andrewgelman.com/2011/04/04/irritating_pseu/&quot;&gt;Andrew Gelman&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;embedded-charts-and-symbols&quot;&gt;Embedded Charts and Symbols&lt;/h2&gt;

&lt;p&gt;Now we get to the interesting stuff! When you have multiple values to display specific locations on your map, why not layer in other chart types to display these values?&lt;/p&gt;

&lt;p&gt;It seems in some ways obvious, but as we will see below, this just doesn’t always work out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Circles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/circles1.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source &lt;a href=&quot;https://congosto.carto.com/viz/e5da12e2-9fe7-11e4-bc43-0e853d047bba/public_map&quot;&gt;Carto: Madrid subway complaints by station&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/circles2.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://scherkwa.wordpress.com/2012/12/12/bivariate-map/&quot;&gt;Bill Scherkenbach&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/pies1.png&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://twitter.com/wallacetim/status/440326909767852032&quot;&gt;A Map Analysis of US Airline Competition&lt;/a&gt; (found in a tweet from Tim Wallace)&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/pies2.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;http://webarchive.nationalarchives.gov.uk/20090115123440/http://www.dft.gov.uk/162259/187604/206711/volume2.pdf&quot;&gt;The Eddington Transport Study&lt;/a&gt; (pdf)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Radars&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/radars1.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/radars2.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://projecteuclid.org/download/pdfview_1/euclid.ss/1199285037&quot;&gt;Moral Statistics of France&lt;/a&gt; (pdf)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lines&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/multivar_map/lines.jpg&quot; alt=&quot;&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://archive.org/stream/AtlasOfAmericanAgriculture/5797#page/n33/mode/2up&quot;&gt;Atlas of American Agriculture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probably my favorite of the bunch, but that’s just cause &lt;a href=&quot;http://vallandingham.me/seattle_maps/&quot;&gt;I like old maps&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;see-also&quot;&gt;See Also&lt;/h2&gt;

&lt;p&gt;Hopefully this was a fun romp through the fun and strange possibilities of multivariate map displays. Come back to this page for potential inspiration or jumping off points the next time someone demands a map for your complex data.&lt;/p&gt;

&lt;p&gt;Of course I’m not the only one who likes collecting, nor the first to ponder multivariate map encodings. For more, check out the great &lt;a href=&quot;http://axismaps.github.io/thematic-cartography/&quot;&gt;Axis Maps Thematic Cartography Guide&lt;/a&gt; which includes a multivariate section.&lt;/p&gt;

&lt;p&gt;Have a technique I missed? Let me know!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Histograms to View Oodles of Doodles from Google</title>
   <link href="http://vallandingham.me/quickdraw_talk.html"/>
   <updated>2017-08-31T00:00:00+00:00</updated>
   <id>http://vallandingham.me/quickdraw_talk</id>
   <content type="html">&lt;p&gt;I was honored to be asked to talk at &lt;a href=&quot;https://www.uber.com/p/visualization/visualization-nights/&quot;&gt;Uber’s Visualization Nights&lt;/a&gt; in Seattle, August 31st, 2017. Here’s the &lt;a href=&quot;https://www.meetup.com/Uber-Engineering-Events-Seattle/events/242258284/&quot;&gt;Meetup Link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In May 2018, I also was fortunate to present a version of this talk at the &lt;a href=&quot;http://data.em-lyon.com/2018/04/26/mini-conference-on-data-visualization-and-ai/&quot;&gt;Mini-Conference on Data Visualization and AI&lt;/a&gt; currated by &lt;a href=&quot;http://ghostweather.com/&quot;&gt;Lynn Cherny&lt;/a&gt; in Lyon, France.&lt;/p&gt;

&lt;p&gt;As you can guess by the amazingly clever title, it was a very serious topic. I used my recent &lt;a href=&quot;http://vallandingham.me/quickdraw/&quot;&gt;How Long Does it Take to (Quick) Draw a Dog?&lt;/a&gt; visualization to talk about histograms and other fun aggregate views of data.&lt;/p&gt;

&lt;h2 id=&quot;slides&quot;&gt;Slides&lt;/h2&gt;

&lt;p&gt;I used keynote to make the slides, and included a few animations / videos. Unfortunately, these don’t transfer well to the internet. But here’s a speaker deck to give you most of the content of the talk.&lt;/p&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;5c8c262b66204cfe8cfdf639409498d3&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

&lt;h2 id=&quot;references-and-links&quot;&gt;References and Links&lt;/h2&gt;

&lt;p&gt;Here is a list of references I used during the talk. Thanks to all the prior work and tools listed!&lt;/p&gt;

&lt;h3 id=&quot;quick-draw-links-and-prior-art&quot;&gt;Quick Draw Links and Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://quickdraw.withgoogle.com/&quot;&gt;Quick Draw Game&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://quickdraw.withgoogle.com/data&quot;&gt;Quick Draw Data&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://frauzufall.de/en/2017/google-quick-draw/&quot;&gt;Deborah Schmidt: Letter Collages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://formafluens.io/index.html&quot;&gt;Forma Fluens&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://qz.com/994486/the-way-you-draw-circles-says-a-lot-about-you/&quot;&gt;Quartz: How do you draw a circle?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://clome.info/work/quickdraw/explore/&quot;&gt;Yannick Assogba: PCA Quick Draw Exploration&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;histogram-examples&quot;&gt;Histogram Examples&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://flowingdata.com/2017/06/07/how-histograms-work/&quot;&gt;Flowing Data: How Histograms Work&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://flowingdata.com/2014/02/27/how-to-read-histograms-and-use-them-in-r/&quot;&gt;Flowing Data: How to Read Histograms&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://fivethirtyeight.com/features/a-statistical-analysis-of-the-work-of-bob-ross/&quot;&gt;FiveThirtyEight: Bob Ross Bar Chart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.nytimes.com/interactive/2015/02/17/upshot/what-do-people-actually-order-at-chipotle.html&quot;&gt;NYT Upshot: Chipotle Calories&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Karl_Pearson&quot;&gt;Karl Pearson&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.nytimes.com/2014/04/23/upshot/what-good-marathons-and-bad-investments-have-in-common.html?_r=0&quot;&gt;NYT Upshot: Runners Time&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://pudding.cool/2017/05/song-repetition/&quot;&gt;The Pudding: Song Lyric Repetitiveness&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.nytimes.com/interactive/2017/07/28/climate/more-frequent-extreme-summer-heat.html&quot;&gt;NYT: Summers Getting Hotter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://joeycloud.net/v/pianogram/&quot;&gt;Pianogram&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://infovis-mannheim.de/viavelox/&quot;&gt;Via Velox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.latimes.com/projects/la-fi-disneyland-ride-wait-time/&quot;&gt;LA Times: Disneyland Wait Times&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://pudding.cool/2017/07/cetaceans/&quot;&gt;The Pudding: Free Willy by the Numbers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://tinlizzie.org/histograms/&quot;&gt;Amelia McNamara: What’s so Hard About Histograms&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.darkhorseanalytics.com/blog/visualizing-distributions-3&quot;&gt;Dark Horse Analytics: Visualizing Distributions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://spatial.ly/2017/07/joy-division-population-surfaces-and-pioneering-electronic-cartography/&quot;&gt;James Cheshire: Population Joyplot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/clauswilke/ggjoy&quot;&gt;ggjoy&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>An Intro to regl for Data Visualization</title>
   <link href="http://vallandingham.me/regl_intro.html"/>
   <updated>2017-05-30T00:00:00+00:00</updated>
   <id>http://vallandingham.me/regl_intro</id>
   <content type="html">&lt;p&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/banner.png&quot; alt=&quot;Triangle Example&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/regl-project/regl&quot;&gt;regl&lt;/a&gt; is a technology meant to simplify building awesome things with WebGL. Recently, &lt;a href=&quot;https://twitter.com/MikolaLysenko&quot;&gt;Mikola Lysenko&lt;/a&gt;, one of the creators of regl, gave a great talk at &lt;a href=&quot;https://openvisconf.com/#videos&quot;&gt;OpenVis Conf&lt;/a&gt; that got me wanting to spend more time with WebGL and regl in particular - to see how it could be applied to my data visualization work.&lt;/p&gt;

&lt;p&gt;With this tutorial, I hope to share my brief learnings on this wonderfully mystical technology and remove some of that magic. Specifically, how do we make the jump from the interesting but not so applicable intro triangle example:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/adc721dde94802802810000f481ed744&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/triangle.png&quot; alt=&quot;Triangle Example&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To using regl for some sort of data visualization? At the end of this tutorial, hopefully you (and I) will find out!&lt;/p&gt;

&lt;p&gt;We will start with the triangle. Try to understand WebGL and regl in the context of this example, then work to modify it to expand our understanding. We will cover some basics of WebGL and shaders, setting up your development environment to work with regl, and then explore a subset of regl’s functionality and capabilities.&lt;/p&gt;

&lt;p&gt;The final result will be a data stream visualization:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/af509ae70a7560b5a72cd3e3da4ff8cf&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/data_stream.gif&quot; alt=&quot;Data Stream&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This falls short of the &lt;a href=&quot;http://peterbeshai.com/beautifully-animate-points-with-webgl-and-regl.html&quot;&gt;amazing regl visualizations&lt;/a&gt; Peter Beshai has recently produced and discussed, but hopefully this tutorial can serve as a stepping stone towards this greatness.&lt;/p&gt;

&lt;p&gt;And if you want to just skip to the results, I’ve made a bunch of blocks to illustrate the concepts covered:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/adc721dde94802802810000f481ed744&quot;&gt;Plain regl triangle&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/315500b61d28eb0bba8959ca66a68e37&quot;&gt;regl triangle in a loop&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/48f3abf115332ac4e67f0f86ee9fe61d&quot;&gt;regl triangle moving&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/a925897220c4b1154b091aba6fcf842c&quot;&gt;regl triangle using props&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/0223315b7a1896e5a22c89f283d1b0fc&quot;&gt;Displaying dots with regl&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/af509ae70a7560b5a72cd3e3da4ff8cf&quot;&gt;Data Stream with regl&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-is-webgl&quot;&gt;What is WebGL?&lt;/h2&gt;

&lt;p&gt;First, it might be useful to step back a bit and talk at a high level about WebGL and regl and what they are good for. If you know all this, feel free to skip ahead.&lt;/p&gt;

&lt;p&gt;As the wonderful &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API&quot;&gt;Mozilla Developer Network&lt;/a&gt; so succinctly puts it, WebGL - or the &lt;em&gt;Web Graphics Library&lt;/em&gt; - is a way to create interactive 2D and 3D visuals in a web browser with just Javascript. It is a low level API that utilizes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canvas&lt;/code&gt; tag, and can be used to make some &lt;a href=&quot;http://alteredqualia.com/xg/examples/deferred_skin.html&quot;&gt;pretty&lt;/a&gt; &lt;a href=&quot;https://www.nytimes.com/interactive/2017/05/18/climate/antarctica-ice-melt-climate-change.html&quot;&gt;impressive&lt;/a&gt; &lt;a href=&quot;https://www.nytimes.com/interactive/2015/01/09/sports/the-dawn-wall-el-capitan.html&quot;&gt;stuff&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;WebGL has a lot going for it. Its &lt;a href=&quot;http://caniuse.com/#feat=webgl&quot;&gt;supported in many browsers&lt;/a&gt;, it can be crazy fast as the code is executed on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Graphics_processing_unit&quot;&gt;GPU&lt;/a&gt;, and there are lots of &lt;a href=&quot;https://www.shadertoy.com/&quot;&gt;impressive examples&lt;/a&gt; to get you started.&lt;/p&gt;

&lt;p&gt;But it is also a crazy confusing API for folks just getting started who are not familiar with these types of systems. WebGl is a &lt;a href=&quot;https://hacks.mozilla.org/2013/04/the-concepts-of-webgl/&quot;&gt;graphics pipeline&lt;/a&gt; that includes a number of steps that are used to get an image rendered to the screen. The API is very low-level and it can take a lot of work just to get &lt;em&gt;something&lt;/em&gt; on the screen.&lt;/p&gt;

&lt;h2 id=&quot;what-is-regl&quot;&gt;What is regl?&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/regl-project/regl&quot;&gt;regl&lt;/a&gt; framework simplifies the task of developing WebGL code by providing a more functional interface. It takes cues from the &lt;a href=&quot;https://facebook.github.io/react/&quot;&gt;React&lt;/a&gt; world, providing a consistent and familiar way to pass state and properties into the WebGL code.&lt;/p&gt;

&lt;p&gt;So, you still have to write some WebGL, but the parts that you are responsible for writing are simpler, isolated, and have a defined signature.&lt;/p&gt;

&lt;h2 id=&quot;throwing-shade-with-shaders&quot;&gt;Throwing Shade with Shaders&lt;/h2&gt;

&lt;p&gt;The WebGL code you still need to write are known as shaders. Shaders are functions written in a special C-like graphics language called &lt;strong&gt;GLSL&lt;/strong&gt; or &lt;em&gt;OpenGL Shading Language&lt;/em&gt; (OpenGL being the standard WebGL is based on).&lt;/p&gt;

&lt;p&gt;There are different types of shaders, specifically &lt;strong&gt;two types&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Vertex shaders&lt;/li&gt;
  &lt;li&gt;Fragment shaders&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each type is responsible for configuring a different portion of the WebGL rendering pipeline. You need to implement both to make a complete&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Vertex shader&lt;/strong&gt; is given each point (vertex) of the thing that is being rendered (triangle, sphere, &lt;a href=&quot;http://regl.party/examples/?bunny&quot;&gt;rabbit&lt;/a&gt;, dataset) and its job is to determine the position of each of these vertices in WebGL space. If we ponder this idea from a data visualization / &lt;a href=&quot;http://d3js.org/&quot;&gt;D3&lt;/a&gt; perspective, this is kind of like implementing the most specific &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.scale&lt;/code&gt; ever. Each vertex is a data point, and the shader is a scale that maps each input point to a location in space and time for your specific visual.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Fragment shader&lt;/strong&gt; deals with the visual display of the things rendered in the WebGL pipeline to the screen. Specifically, they need to set the color for each pixel that is being displayed. (Why is it called a fragment shader and not a pixel shader? &lt;a href=&quot;http://t-machine.org/index.php/2013/10/05/why-is-a-fragment-shader-named-a-fragment-shader/&quot;&gt;Good Question!&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;As an aside, shaders are called &lt;em&gt;shaders&lt;/em&gt; because fragment shaders are used to control lighting and other special effects when using GLSL in game development.&lt;/p&gt;

&lt;p&gt;We won’t go into the details of GLSL in this tutorial, but hopefully the simple shaders we use aren’t too confusing. I’d suggest reading a bit of &lt;a href=&quot;https://thebookofshaders.com/&quot;&gt;The Book of Shaders&lt;/a&gt; if you haven’t seen GLSL at all before - it provides a nice smooth introduction (though it focuses soley on fragment shaders).&lt;/p&gt;

&lt;p&gt;As an aside, The Book of Shaders also has a &lt;a href=&quot;http://editor.thebookofshaders.com/&quot;&gt;great shader editor&lt;/a&gt; you should check out that includes all sorts of nice features. You can learn more about it &lt;a href=&quot;https://thebookofshaders.com/04/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some other resources that I shamelessly borrowed from, and might cover these concepts more elegantly than me:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://webglfundamentals.org/webgl/lessons/webgl-fundamentals.html&quot;&gt;WebGL Fundamentals&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.html5rocks.com/en/tutorials/webgl/shaders/&quot;&gt;HTML5 Rocks Shader Intro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;setting-up-an-exploration-environment&quot;&gt;Setting up an Exploration Environment&lt;/h2&gt;

&lt;p&gt;Before we put our pedals to the metals in implementing these concepts in our very own regl program, let’s take a moment to setup an environment that helps facilitate an exploration of these new technologies in a way that doesn’t incite us to throw our computers into the ocean out of frustration.&lt;/p&gt;

&lt;p&gt;My solution to reducing frustration with new technologies is typically to supplement existing tools I like with new features. To this end, I’m going to suggest some &lt;a href=&quot;https://atom.io/&quot;&gt;Atom&lt;/a&gt; plugins to use that could make working with GLSL code easier for you.&lt;/p&gt;

&lt;p&gt;But there are many other approaches! Feel free to ignore these recommendations and &lt;strong&gt;skip ahead&lt;/strong&gt;, if you have a different methodology for WebGL development.&lt;/p&gt;

&lt;p&gt;Also, I’ve included &lt;a href=&quot;https://bl.ocks.org/&quot;&gt;Blocks&lt;/a&gt; for each of the steps in the tutorial - which work without any additional setup - so if you don’t want to setup your coding environment now, you could just start forking those!&lt;/p&gt;

&lt;h3 id=&quot;atom-packages-for-glsl-fun&quot;&gt;Atom Packages for GLSL Fun&lt;/h3&gt;

&lt;p&gt;Here are the Atom packages I would recommend using as we get started. Each can be &lt;a href=&quot;http://flight-manual.atom.io/using-atom/sections/atom-packages/&quot;&gt;installed&lt;/a&gt; via Atom’s “Preferences” menu.&lt;/p&gt;

&lt;p&gt;First, grab the &lt;a href=&quot;https://atom.io/packages/language-glsl&quot;&gt;language-glsl&lt;/a&gt; package for some nice syntax highlighting of our GLSL code. Initially our GLSL code will be written inline as strings, but eventually we will write this code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.glsl&lt;/code&gt; files, so this package will come in handy then.&lt;/p&gt;

&lt;p&gt;Next, you might be interested in the &lt;a href=&quot;https://atom.io/packages/autocomplete-glsl&quot;&gt;autocomplete-glsl&lt;/a&gt; which gives you handy autocompleting of GLSL types and functions. It even provides links to the documentation for each function!&lt;/p&gt;

&lt;p&gt;Finally, I never leave home without a linter - and &lt;a href=&quot;https://atom.io/packages/linter-glsl&quot;&gt;linter-glsl&lt;/a&gt; provides nice inline warnings and errors in your code so you can catch them early and (hopefully) avoid hours of glaring angrily at your screen just because you forgot a ‘.’ somewhere (it might still happen though!).&lt;/p&gt;

&lt;p&gt;To get the linter working, you need to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glslangValidator&lt;/code&gt; - which if you are on a Mac and use &lt;a href=&quot;https://brew.sh/&quot;&gt;homebrew&lt;/a&gt; you can do easily:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install glslang
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;a-baseline-for-good-regling&quot;&gt;A Baseline for good regling&lt;/h2&gt;

&lt;p&gt;Ok, after far too much yawning, let’s get to some code. Here we will add the necessary JS packages to our development environment - so again &lt;strong&gt;skip ahead&lt;/strong&gt; if you are just working with the Blocks for now. Most of this section is a rehash of the lovely &lt;a href=&quot;http://rickyreusser.com/2016/12/07/from-nothing-to-something-in-webgl/&quot;&gt;from nothing to something in WebGL&lt;/a&gt; blog post by Ricky Reusser - so feel free to use the original source.&lt;/p&gt;

&lt;p&gt;First, let’s create a new Javascript project using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm init&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir regl-start
cd regl-start
npm init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can just hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enter&lt;/code&gt; to select the defaults for the project if you like - or tweak them as necessary. This command adds a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file to our new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regl-start&lt;/code&gt; directory. We will use this file to manage the &lt;a href=&quot;https://www.npmjs.com/&quot;&gt;npm&lt;/a&gt; packages we will use.&lt;/p&gt;

&lt;h3 id=&quot;some-nice-to-have-packages&quot;&gt;Some Nice-to-have Packages&lt;/h3&gt;

&lt;p&gt;We will install a few packages to get things up and running quickly. The commands to run inside your project are:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install --save regl
npm install --save-dev browserify budo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s a short description of what the development packages provide us:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://browserify.org/&quot;&gt;browserify&lt;/a&gt; is a package that allows us to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require&lt;/code&gt; other javascript modules in the browser (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require&lt;/code&gt; function comes from the &lt;a href=&quot;https://nodejs.org/en/&quot;&gt;node&lt;/a&gt; world and browserify brings it to the web).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mattdesl/budo&quot;&gt;budo&lt;/a&gt; is a development web server that works well with browserify and provides auto-reloading your browser every time you make a change to your code. Handy!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--save-dev&lt;/code&gt; flag puts them in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devDependencies&lt;/code&gt; of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file. These packages are needed only to develop and build the project.&lt;/p&gt;

&lt;h3 id=&quot;starting-up-with-start&quot;&gt;Starting up with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Next we need to create our Javascript starting point. Let’s name it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;touch index.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;touch&lt;/code&gt; is a unix command that creates an empty file if no file exists. Inside our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.js&lt;/code&gt;, let’s write a simple test to ensure it is getting loaded (regl-less for now)&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we need to make browserify and budo work for us to build and serve this script.&lt;/p&gt;

&lt;p&gt;Back in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt;, we have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;scripts&quot;&lt;/code&gt; section. Here we will remove the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; script for now and add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start&lt;/code&gt; script that looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;scripts&quot;: {
  &quot;start&quot;: &quot;budo index.js --open --live&quot;
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This tells budo to browserify our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.js&lt;/code&gt; file and open a web browser to view it. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--live&lt;/code&gt; indicates to repeat this process any time the code changes.&lt;/p&gt;

&lt;p&gt;Let’s run our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start&lt;/code&gt; script from the command line using npm!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If everything went correctly, a new browser window should open and we should see our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt; in the Console.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/hello_text.png&quot; alt=&quot;Data Stream&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;hello-triangle&quot;&gt;Hello Triangle!&lt;/h2&gt;

&lt;p&gt;Ok, so far that was just a &lt;em&gt;how to get budo and browserify on your machine&lt;/em&gt; tutorial - which is fine but not what we promised. So let’s add some regl!&lt;/p&gt;

&lt;p&gt;We will start by displaying a triangle which is the &lt;a href=&quot;http://regl.party/examples/?basic&quot;&gt;first example&lt;/a&gt; provided on the examples page - and serves as something like the ‘hello world’ of regl.&lt;/p&gt;

&lt;p&gt;Let’s put this in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.js&lt;/code&gt; file, and then go over the details:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)();&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drawTriangle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// fragment shader&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;frag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
  precision mediump float;
  uniform vec4 color;
  void main () {
    gl_FragColor = color;
  }`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// vertex shader&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;vert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
  precision mediump float;
  attribute vec2 position;
  void main () {
    gl_Position = vec4(position, 0, 1);
  }`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// attributes&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// uniforms&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;uniforms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// vertex count&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;drawTriangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(Note the ` around the shader code. They are actually &lt;strong&gt;strings&lt;/strong&gt; passed in to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frag&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vert&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This draws a triangle:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/adc721dde94802802810000f481ed744&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/triangle.png&quot; alt=&quot;Triangle Example&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/adc721dde94802802810000f481ed744&quot;&gt;Block Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hurrah! &lt;strong&gt;But how?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ok, first step is pretty simple. We &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require&lt;/code&gt; regl (remember we are using browserify - so we have that power). On the same line, we are calling the returned function which &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#quick-start&quot;&gt;creates a full screen canvas element&lt;/a&gt;. This sets up our canvas and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext&quot;&gt;WebGLRenderingContext&lt;/a&gt; automatically.&lt;/p&gt;

&lt;p&gt;Next we create a regl draw command by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regl()&lt;/code&gt;. As the &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#commands&quot;&gt;docs state&lt;/a&gt;, draw commands are the main point of the library. They allow for packaging shader code, as well as state and input parameters into a single reusable command.&lt;/p&gt;

&lt;p&gt;Minimally, a regl draw command takes an object with a few &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#parameters&quot;&gt;parameters&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;frag&lt;/strong&gt; which specifies the fragment shader code (written in GLSL).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;vert&lt;/strong&gt; which specifies the vertex shader code (again in GLSL).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;count&lt;/strong&gt; which indicates the number of vertices to draw.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this example, both shaders are written as one big string (we will see how to improve this setup later). This draw command also provides more parameters: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributes&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniforms&lt;/code&gt; which we will look at below.&lt;/p&gt;

&lt;p&gt;Now let’s recap the purpose of these two shaders, and look a bit at how they work.&lt;/p&gt;

&lt;p&gt;The vertex shader needs to accomplish its goal of &lt;strong&gt;positioning&lt;/strong&gt; each vertex. It is called once for each vertex and needs to set the &lt;strong&gt;gl_Position&lt;/strong&gt; global during each call.&lt;/p&gt;

&lt;p&gt;The fragment shader needs to set the &lt;strong&gt;color&lt;/strong&gt; for each fragment. It does this by setting the &lt;strong&gt;gl_FragColor&lt;/strong&gt; global each time it is called.&lt;/p&gt;

&lt;p&gt;No matter what else happens in these shaders, these two variables (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gl_Position&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gl_FragColor&lt;/code&gt;) are what need to be set.&lt;/p&gt;

&lt;p&gt;Also note the general structure of a shader. You start with the declaration of variables and then use these variables in your shader’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main()&lt;/code&gt; function. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;precision mediump float;&lt;/code&gt; line sets the precision of &lt;a href=&quot;https://stackoverflow.com/questions/28540290/why-it-is-necessary-to-set-precision-for-the-fragment-shader&quot;&gt;floating point values&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We run the draw command by calling it on the last line:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;drawTriangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And a triangle is born!&lt;/p&gt;

&lt;p&gt;We can see some of the interactions between regl and shader code - but not everything is immediately clear. For example, we see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt; listed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniforms&lt;/code&gt; section of the regl command, and then we see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniform vec4 color&lt;/code&gt; specified and used in the fragment shader, but what is a uniform?&lt;/p&gt;

&lt;p&gt;Let’s talk more about the different variable types in shaders, then come back to see how we work with these in regl.&lt;/p&gt;

&lt;h3 id=&quot;the-many-shader-variable-types&quot;&gt;The Many Shader Variable Types&lt;/h3&gt;

&lt;p&gt;In shader land, there are three types of variables you can declare. They are all confusing, but I like the explanation provided by &lt;a href=&quot;https://www.html5rocks.com/en/tutorials/webgl/shaders/&quot;&gt;html5rocks&lt;/a&gt;, so I’ll try to summarize here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uniforms&lt;/strong&gt; are accessible in both the vertex and fragment shader. They are ‘uniform’ because they are constant during each frame being rendered. But (as we will see below), their value can change between frames.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attributes&lt;/strong&gt; are only provided to the vertex shader. There is a value for each vertex being displayed. The individual value is provided to the vertex shader when dealing with that specific vertex.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Varyings&lt;/strong&gt; are variables declared in the vertex shader that can be shared with the fragment shader. We won’t use this in the rest of the tutorial, but its good to know they exist!&lt;/p&gt;

&lt;h3 id=&quot;regl-and-variables&quot;&gt;regl and Variables&lt;/h3&gt;

&lt;p&gt;So finally we are getting to what makes regl interesting and worth trying out. How it organizes what you pass in to the fragment shader functions.&lt;/p&gt;

&lt;p&gt;Now that we know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniform&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attribute&lt;/code&gt; are variable types, I bet you can guess what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniforms&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributes&lt;/code&gt; parameters of the draw command object are for, right? They allow us to specify the values of variables that are accessible in our shaders!&lt;/p&gt;

&lt;p&gt;Let’s break it down a bit more.&lt;/p&gt;

&lt;p&gt;Our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniforms&lt;/code&gt; parameter looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;uniforms: {
  color: [1, 0, 0, 1]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This indicates that there will be a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt; uniform available to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vert&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frag&lt;/code&gt; shaders. This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt; variable is a &lt;a href=&quot;https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Vectors&quot;&gt;vec4&lt;/a&gt; - a vector of length 4 - as seen in the declaration in the fragment shader, so it is declared here as an array with 4 values.&lt;/p&gt;

&lt;p&gt;(Check out the Book of Shaders &lt;a href=&quot;https://thebookofshaders.com/06/&quot;&gt;Color Chapter&lt;/a&gt; to learn more about how colors are defined in GLSL).&lt;/p&gt;

&lt;p&gt;Our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributes&lt;/code&gt; parameter looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;attributes: {
  position: [
    [-1, 0],
    [0, -1],
    [1, 1]
  ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can see we define one attribute, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt;, that is an array with 3 values. As we have our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count&lt;/code&gt; parameter set to 3, the vertex shader code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vert&lt;/code&gt; will be run 3 times, each time its corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; attribute will be set to the correct value of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; array inside our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that the coordinate system is a bit different then what you might expect. The x and y scales go from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-1.0&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.0&lt;/code&gt; as shown in this handy diagram from &lt;a href=&quot;https://hacks.mozilla.org/2013/04/the-concepts-of-webgl/&quot;&gt;MDN’s WebGL Concepts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/webgl-axes.png&quot; alt=&quot;Triangle Example&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So thats how this triangle gets drawn. Kind of cool, right?&lt;/p&gt;

&lt;h3 id=&quot;regl-inputs&quot;&gt;regl Inputs&lt;/h3&gt;

&lt;p&gt;But wait there’s more!&lt;/p&gt;

&lt;p&gt;Currently in this example, the input uniforms and attributes are all static values. But it doesn’t have to be this way!&lt;/p&gt;

&lt;p&gt;A big feature of regl is that you can supply inputs to regl &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#inputs&quot;&gt;through a number of different ways&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To see some of these benefits, let’s convert our triangle from a frame that is displayed just once, to a visual that is displaying over and over through time.&lt;/p&gt;

&lt;h2 id=&quot;a-triangle-in-time&quot;&gt;A Triangle In Time&lt;/h2&gt;

&lt;p&gt;Currently our triangle is rendered in &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#one-shot-rendering&quot;&gt;one shot&lt;/a&gt;. It is displayed and then it is done. In order to see the benefits of dynamic data, we want to render this triangle over and over again so we can pass in different value each render.&lt;/p&gt;

&lt;p&gt;Looping can be done in many ways, but regl provides &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#per-frame-callbacks&quot;&gt;regl.frame&lt;/a&gt; for just such a purpose. This allows us to call our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawTriangle&lt;/code&gt; draw command inside a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame&quot;&gt;requestAnimationFrame()&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s modify our code to use it!&lt;/p&gt;

&lt;p&gt;Change our call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawTriangle()&lt;/code&gt; to this:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;drawTriangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, our browser should reload, and we should see our triangle again. In fact, it should look exactly the same.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/315500b61d28eb0bba8959ca66a68e37&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/triangle.png&quot; alt=&quot;Triangle Example with loop&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The difference is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawTriangle()&lt;/code&gt; is now being called over and over again in a loop. We can verify this by console logging a value in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt;. Try tweaking the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regl.frame&lt;/code&gt; call to this:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;drawTriangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the Console, you should see our tick count. And it should be increasing!&lt;/p&gt;

&lt;p&gt;(I would remove that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.log&lt;/code&gt; after verifying that it is indeed looping - cause it clogs up the Console and slows things down).&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/tick_count.png&quot; alt=&quot;Tick count&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; variable is something that regl populates with a few values. Let’s return back to regl and talk about the ways it allows inputs to the draw commands.&lt;/p&gt;

&lt;h3 id=&quot;regl-inputs-context-props-and-this&quot;&gt;regl Inputs: Context, Props, and this&lt;/h3&gt;

&lt;p&gt;So we have learned that a core feature of regl is handling inputs to our shaders. We know that shader variables come in 3 flavors: uniforms, attributes, and varyings. And while the triangle example we have been working with deals with static versions of these inputs, I indicated that dynamic inputs were also possible. So lets’ find out how!&lt;/p&gt;

&lt;p&gt;regl allows for inputs to its draw commands to come from &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#inputs&quot;&gt;3 possible sources&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;: Context variables are state accessible between child draw commands (which we won’t look at here). It is also the place where regl keeps a &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#context&quot;&gt;number of variables&lt;/a&gt; you might find useful - including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;time&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Props&lt;/strong&gt;: Props are the most common way to pass in data to a regl draw command. You can pass them in as an input object when you call the draw command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;this&lt;/strong&gt;: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; variable can be used to save state within a regl command. We won’t look more into this here - but something to keep in mind.&lt;/p&gt;

&lt;p&gt;If you are familiar with React, as the &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#inputs&quot;&gt;regl documentation states&lt;/a&gt;, you can use this knowledge to better understand these input options.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;regl’s Context is analogous to React’s &lt;a href=&quot;https://facebook.github.io/react/docs/context.html&quot;&gt;Context&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;regl’s Props is similar to React’s Component &lt;a href=&quot;https://facebook.github.io/react/docs/components-and-props.html&quot;&gt;Props&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;regl’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; parallels a Component’s &lt;a href=&quot;https://facebook.github.io/react/docs/state-and-lifecycle.html&quot;&gt;State&lt;/a&gt; in React.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But how do you use these regl inputs in your draw command?&lt;/p&gt;

&lt;p&gt;Well it turns out that, &lt;strong&gt;similar to D3 attr&lt;/strong&gt;, the values of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniforms&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributes&lt;/code&gt; properties in regl can be specified using functions! And these functions get access to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;props&lt;/code&gt; of the draw command.&lt;/p&gt;

&lt;p&gt;Pretty cool! Let’s try this out.&lt;/p&gt;

&lt;h3 id=&quot;flying-triangle&quot;&gt;Flying Triangle&lt;/h3&gt;

&lt;p&gt;Let’s use our knowledge of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context.tick&lt;/code&gt; variable and base our vertex position attribute values on its current value. To do this, we will change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; to use a callback function. This function is called inside regl to set the ultimate value of the attribute on each render. This callback function receives the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;props&lt;/code&gt; for the draw command (not unlike having access to the bound data for an element when setting an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attr&lt;/code&gt; in D3).&lt;/p&gt;

&lt;p&gt;Modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributes&lt;/code&gt; portion of your draw command to look like this:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And our triangle should start flying around on the screen!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/48f3abf115332ac4e67f0f86ee9fe61d&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/triangle_loop.gif&quot; alt=&quot;Triangle Example moving in loop&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/48f3abf115332ac4e67f0f86ee9fe61d&quot;&gt;Block&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its interesting to note that we &lt;em&gt;made no changes to our shader code&lt;/em&gt; to make things dynamic. Instead, we simply put our draw command in a loop (using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regl.frame&lt;/code&gt;) and then took advantage of regl’s input capabilities to make it dynamic.&lt;/p&gt;

&lt;p&gt;Note that while I passed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;props&lt;/code&gt; to the callback function, we didn’t actually use it - but I wanted to show that this object is also accessible. Let’s look at using this next!&lt;/p&gt;

&lt;h3 id=&quot;flying-triangle-with-props&quot;&gt;Flying Triangle with Props&lt;/h3&gt;

&lt;p&gt;The regl documentation states that Props are &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#props&quot;&gt;the most common way&lt;/a&gt; to pass data into draw commands, but it doesn’t exactly say &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;With a bit of that React knowledge, and some sample code examination, we can see that a draw commands Props are passed in to it when calling the draw command function.&lt;/p&gt;

&lt;p&gt;So, for example, if instead of using a static value for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt; we wanted to pass in a color Prop to our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawTriangle&lt;/code&gt;, we could do so by changing the call to the function like so:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;drawTriangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.208&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.304&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(I used the &lt;a href=&quot;http://editor.thebookofshaders.com/&quot;&gt;Book of Shaders Editor&lt;/a&gt; to pick out a nice blue).&lt;/p&gt;

&lt;p&gt;And then we can use this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt; prop in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniforms&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;uniforms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now your triangle should be moving, and blue!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/a925897220c4b1154b091aba6fcf842c&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/blue_triangle.png&quot; alt=&quot;Triangle Example with props&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/a925897220c4b1154b091aba6fcf842c&quot;&gt;Block&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Click on the Block link to see the animation).&lt;/p&gt;

&lt;p&gt;If you like shortcuts, regl also provides a handy shorthand notation for accessing props: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regl.prop()&lt;/code&gt;. Rewriting the above uniforms to use this shorthand would look like:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;uniforms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;from-triangles-to-dots&quot;&gt;From Triangles to Dots&lt;/h2&gt;

&lt;p&gt;Hopefully now we know a bit more about how shaders and regl fit together. We’ve learned about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;props&lt;/code&gt; which point to ways to get data into WebGL via regl to visualize.&lt;/p&gt;

&lt;p&gt;Let’s move past the triangle and start using this wisdom on some dot data vis.&lt;/p&gt;

&lt;h3 id=&quot;displaying-points-with-regl&quot;&gt;Displaying Points with regl&lt;/h3&gt;

&lt;p&gt;The first thing I want to cover is the minimum set of changes we need to convert the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawTriangle&lt;/code&gt; draw command into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawDots&lt;/code&gt; draw command.&lt;/p&gt;

&lt;p&gt;Here is the full code to get us started (which should look very similar to our triangle code for now). Below we will go over the changes.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)();&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drawDots&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;frag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
  precision mediump float;
  uniform vec4 color;
  void main () {
    gl_FragColor = color;
  }`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;vert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
  precision mediump float;
  attribute vec2 position;
  // @change acquire the pointWidth uniform
  //  this is set by the uniforms section below
  uniform float pointWidth;

  void main () {
    // @change Set gl_PointSize global to
    //  configure point size
    gl_PointSize = pointWidth;
    gl_Position = vec4(position, 0, 1);
  }`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// @change I tweaked the constants here so&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;//  the dots are not off the screen&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;uniforms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// @change: Add a pointWidth uniform -&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//  set by a prop&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pointWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pointWidth&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// @change: Set our primitive to points&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;primitive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;drawDots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.208&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.304&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// @change: Pass in the pointWidth prop&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pointWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;10.0&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Load this up and you should have 3 dots moving about the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/0223315b7a1896e5a22c89f283d1b0fc&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/dots.png&quot; alt=&quot;Triangle Example with props&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/0223315b7a1896e5a22c89f283d1b0fc&quot;&gt;Block&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(The points are hard to see - click on the Block link to see the animation).&lt;/p&gt;

&lt;p&gt;So what changed?&lt;/p&gt;

&lt;p&gt;The smallest but most important change is near the bottom of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawDots&lt;/code&gt; draw command. We need to switch the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;primitive&lt;/code&gt; type to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;points&quot;&lt;/code&gt; in our regl setup:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;primitive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This tells WebGL which &lt;a href=&quot;https://github.com/regl-project/regl/blob/gh-pages/API.md#drawing&quot;&gt;primitive type&lt;/a&gt; to use in the display.&lt;/p&gt;

&lt;p&gt;The other main change is that we need to specify a value for &lt;strong&gt;gl_PointSize&lt;/strong&gt; in our vertex shader. We could hard code this value, but its more fun - and more flexible - to use our regl props knowledge to pass it in as a prop. Hopefully you can follow along with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@change&lt;/code&gt; comments to see this input setup in the code.&lt;/p&gt;

&lt;h3 id=&quot;dots-representing-data&quot;&gt;Dots Representing Data&lt;/h3&gt;

&lt;p&gt;OK! we are coming to the end of the road. We now have dynamic dots, but what we really want is data-driven dots, right?&lt;/p&gt;

&lt;p&gt;So using our regl knowledge, we are going to pass in some dynamically generated data and get regl displaying it!&lt;/p&gt;

&lt;p&gt;Pretend, if you will, we have a dynamic dataset that represents some collection of values over time. Maybe its car speeds on a length of road, or download speeds for a set of computers, or something more exotic. Probably not the most common of datasets - but what can you do.&lt;/p&gt;

&lt;p&gt;Pretend some more that you might want to create an ambient streaming “data vis” to represent this data. Different nodes will move at different speeds and have varying sizes. I write data vis in quotes as this is still a bit of a stretch in terms of something useful - but at least its a start in mapping data to visual attributes with regl.&lt;/p&gt;

&lt;p&gt;So, hopefully you have some inklings on how you might accomplish this, given what you know about regl so far. Essentially, we are going to take our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawDots&lt;/code&gt; draw command and expand it to use more then three vertices. In fact, our vertices will be controlled by data passed in as Props to the draw command.&lt;/p&gt;

&lt;p&gt;Here is the final code block:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Helper function to create a random float between&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// some defined range. This is used to create some&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// fake data. In a real setting, you would probably&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// use D3 to map data to display coordinates.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomFromInterval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Helper function to create a random integer between&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// some defined range. Again, you would want to use&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// D3 for mapping real data to display coordinates.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomIntFromInterval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;randomFromInterval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Some constants to use&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MAX_WIDTH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MAX_HEIGHT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MAX_SPEED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;POINT_SIZE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;POINT_COUNT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Helper function to generate some fake data.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Each data point has an x and y and a 'speed'&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// value that indicates how fast it travels&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dataCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dataCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;speed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomFromInterval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MAX_SPEED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomIntFromInterval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;POINT_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MAX_HEIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomIntFromInterval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;POINT_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;POINT_SIZE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;datum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Helper function, goes through each&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// element in the fake data and updates&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// its x position.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;updateData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;datum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;datum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;speed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// reset x if its gone past max width&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;datum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MAX_WIDTH&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drawDots&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;frag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
  precision mediump float;
  uniform vec4 color;
  void main () {
    gl_FragColor = color;
  }`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;vert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
  precision mediump float;
  attribute vec2 position;
  attribute float pointWidth;

  uniform float stageWidth;
  uniform float stageHeight;

  // helper function to transform from pixel space to normalized
  // device coordinates (NDC). In NDC (0,0) is the middle,
  // (-1, 1) is the top left and (1, -1) is the bottom right.
  // Stolen from Peter Beshai's great blog post:
  // http://peterbeshai.com/beautifully-animate-points-with-webgl-and-regl.html
  vec2 normalizeCoords(vec2 position) {
    // read in the positions into x and y vars
    float x = position[0];
    float y = position[1];

    return vec2(
      2.0 * ((x / stageWidth) - 0.5),
      // invert y to treat [0,0] as bottom left in pixel space
      -(2.0 * ((y / stageHeight) - 0.5)));
  }

  void main () {
    gl_PointSize = pointWidth;
    gl_Position = vec4(normalizeCoords(position), 0, 1);
  }`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// There will be a position value for each point&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// we pass in&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Now pointWidth is an attribute, as each&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// point will have a different size.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pointWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;uniforms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// just to be a bit strange, oscillate the color a bit.&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.304&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// FYI: there is a helper method for grabbing&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// values out of the context as well.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// These uniforms are used in our fragment shader to&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// convert our x / y values to WebGL coordinate space.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;stageWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;drawingBufferWidth&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;stageHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;drawingBufferHeight&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// set the count based on the number of points we have&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;primitive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;POINT_COUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;regl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Each loop, update the data&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;updateData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// And draw it!&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;drawDots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pointWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;POINT_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;points&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And this makes a data stream!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/af509ae70a7560b5a72cd3e3da4ff8cf&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/data_stream.gif&quot; alt=&quot;Triangle Example with props&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/af509ae70a7560b5a72cd3e3da4ff8cf&quot;&gt;Block&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a look and see if it makes any sense (and let me know if it doesn’t!). I’ve added some helper functions to generate fake data. Each datum is an object with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;speed&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;size&lt;/code&gt; attributes.&lt;/p&gt;

&lt;p&gt;The main difference between our previous three-dotted visual and this one is that we are passing in the points data as a Prop, and using this array to derive uniforms and attributes.&lt;/p&gt;

&lt;p&gt;As a quick example, here is how the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; attribute is now created:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, this makes an array of arrays, with each inner array containing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; value from our points. As before, the vertex shader will be called once for each point in the points data (thanks to our modification to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count&lt;/code&gt;) and the position for that particular vertex will be set by its corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; entry.&lt;/p&gt;

&lt;p&gt;The other trick in this code is that the vertex shader has a helper function to convert our data x and y values into WebGL coordinate space. This was stolen right out of Beshai’s tutorial, so you will have to read that to find out more.&lt;/p&gt;

&lt;p&gt;You’ll notice we are still using the CPU (code outside of a shader) to handle positioning the data values. Wouldn’t it be great if we could do that on the GPU as well? Turn in next week when we attack this critical issue!&lt;/p&gt;

&lt;h2 id=&quot;glslify-your-life&quot;&gt;GLSLify Your Life&lt;/h2&gt;

&lt;p&gt;One last thing! So far we haven’t gotten a chance to use all those Atom packages or that linter I made you install. What gives?&lt;/p&gt;

&lt;p&gt;Well, to simplify the generation of the blocks, I decided to keep all the GLSL shader code as strings - like you see in most of the regl examples.&lt;/p&gt;

&lt;p&gt;But do you like coding complex C-like languages in strings?? Me neither.&lt;/p&gt;

&lt;p&gt;So with one additional package, we can throw off the chains of shader strings and feel the warm embrace of better development tools. Trust me? Ok, let’s do it.&lt;/p&gt;

&lt;p&gt;Return, if you will, to your command line and install the &lt;a href=&quot;https://github.com/stackgl/glslify&quot;&gt;glslify&lt;/a&gt; package:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install --save-dev glslify
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What is glslify? Two things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A way to import glsl code from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.glsl&lt;/code&gt; file so you don’t have to write shaders as giant strings.&lt;/li&gt;
  &lt;li&gt;A mechanism that allows you to import glsl code that other people have written - so you can use them in your own shaders. This provides a sort of NPM for shader code (which is a pretty cool idea).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will focus on the first of glslify’s abilities, but I hope to get to experiment with &lt;a href=&quot;http://stack.gl/packages/&quot;&gt;existing glsl packages&lt;/a&gt; soon.&lt;/p&gt;

&lt;p&gt;In order to enable glslify in our development environment, we need to tell browserfiy to use it as a transform when processing our scripts. We can do this in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; by adding a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;browserify&lt;/code&gt; section:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;browserify&quot;: {
  &quot;transform&quot;: [
    &quot;glslify&quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we are ready to extract our GLSL code into their own files.&lt;/p&gt;

&lt;p&gt;To do this you can create a sub-directory in your project (I called it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shaders&lt;/code&gt;) and here create two files:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shaders/draw_dots.fs.glsl&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shaders/draw_dots.vs.glsl&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fs&lt;/code&gt; will store our fragment shader, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vs&lt;/code&gt; will store our vertex shader.&lt;/p&gt;

&lt;p&gt;We can pretty much copy and paste over the shader code out from the strings in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.js&lt;/code&gt; and into these new files (don’t copy over the string ticks - just the code inside them).&lt;/p&gt;

&lt;p&gt;If you installed all those packages I told you about, you should see syntax highlighting and linting in these files. Pretty cool right?&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/glsl_highlighting.png&quot; alt=&quot;syntax highlighting&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To import these shader files back into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.js&lt;/code&gt;, use glslify:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// import glslify at the top
var glslify = require('glslify');

// ...

// use glslify to import shader code!
regl({
  frag: glslify('./shaders/draw_dots.fs.glsl'),
  vert: glslify('./shaders/draw_dots.vs.glsl'),
  // ...
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve made a little starter repo that has this all setup in it, if you’d like to start with it for your explorations:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/regl_explore&quot;&gt;regl explorations repo&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;go-forth-you-regl-beings&quot;&gt;Go Forth you regl Beings&lt;/h2&gt;

&lt;p&gt;That’s all I have on my experiences with regl. If this piqued your interests and you want to go further - or if this was too boring an intro - be sure to check out Peter Beshai’s &lt;a href=&quot;http://peterbeshai.com/beautifully-animate-points-with-webgl-and-regl.html&quot;&gt;Beautiful regl Point Animations&lt;/a&gt;. Hopefully, though this tutorial does repeat a bit of his (and hey its good to repeat things sometimes), they work together to provide an intro and exploration of point visualizations in regl.&lt;/p&gt;

&lt;p&gt;There is plenty more to explore! As always, be sure to share your regl experiences or questions in a regal manner in the comments or &lt;a href=&quot;https://twitter.com/vlandham&quot;&gt;@vlandham&lt;/a&gt; on Twitter.&lt;/p&gt;

&lt;h2 id=&quot;bonus-circle-points&quot;&gt;Bonus: Circle Points&lt;/h2&gt;

&lt;p&gt;Just in case your next comment is “great, but how do I make these points circles?”, I’ve got you covered!&lt;/p&gt;

&lt;p&gt;Check out this &lt;a href=&quot;https://bl.ocks.org/vlandham/0415aa443992f71288e86137208fa690&quot;&gt;block&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/0415aa443992f71288e86137208fa690&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/regl/regl_circles.png&quot; alt=&quot;Triangle Example with props&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bl.ocks.org/vlandham/0415aa443992f71288e86137208fa690&quot;&gt;Block&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A Data Driven Exploration of Kung Fu Films</title>
   <link href="http://vallandingham.me/shaw_bros_analysis.html"/>
   <updated>2017-01-24T00:00:00+00:00</updated>
   <id>http://vallandingham.me/shaw_bros_analysis</id>
   <content type="html">&lt;p&gt;Recently, I’ve been a bit caught up in old Kung Fu movies. Shorting any technical explorations, I have instead been diving head-first into any and all Netflix accessible martial arts masterpieces from the 70’s and 80’s.&lt;/p&gt;

&lt;p&gt;While I’ve definitely been enjoying the films, I realized recently that I had little context for the movies I was watching. I wondered if some films, like our latest favorite, &lt;a href=&quot;http://www.imdb.com/title/tt0076168/&quot;&gt;Executioners from Shaolin&lt;/a&gt;, could be enjoyed even more, with better understanding of the context in which these films exist in the Kung Fu universe.&lt;/p&gt;

&lt;p&gt;So, I began a data driven quest for truth and understanding (or at least a semi-interesting dataset to explore) of all Shaw Brothers Kung Fu movies ever made!&lt;/p&gt;

&lt;p&gt;For those not dedicating some portion of their finite lives to these retro wonders, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Shaw_Brothers_Studio&quot;&gt;Shaw Brothers Studio&lt;/a&gt; is the most famous (to me) Kung Fu film producer of all time. Their memorable title screen is almost always a part of my Kung Fu watching experience.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/shaw_scope.jpg&quot; alt=&quot;Shaw Bros Title Screen&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I figured this company’s entire martial arts collection would provide for a consistent and thorough look at the genre. Fortunately, after a &lt;a href=&quot;http://shawbrothersuniverse.com/shaw-brothers-classic-film-collection/&quot;&gt;bit&lt;/a&gt; &lt;a href=&quot;http://www.silveremulsion.com/review-series/ongoing-review-series/shaw-brothers-martial-arts-films/&quot;&gt;of&lt;/a&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_Shaw_Brothers_films&quot;&gt;searching&lt;/a&gt;, I stumbled on what appears to be a &lt;a href=&quot;https://letterboxd.com/jewbo23/list/shaw-brothers-martial-arts-films/&quot;&gt;comprehensive list of Shaw Brothers Films&lt;/a&gt;. I decided to &lt;a href=&quot;https://github.com/vlandham/scrape_shaw_bros&quot;&gt;pull down details&lt;/a&gt; for each of these movies from the amazingly useful &lt;a href=&quot;https://letterboxd.com/&quot;&gt;Letterboxd&lt;/a&gt; movie-list-creation site to explore them in a data driven way to see what patterns could be discovered and what context I could learn from those patterns.&lt;/p&gt;

&lt;p&gt;So here is a bit of data exploration fun. The analysis is in R, using tips and tricks from Hadley Wickham’s wonderful new &lt;a href=&quot;http://r4ds.had.co.nz/&quot;&gt;Data Science in R&lt;/a&gt; book.&lt;/p&gt;

&lt;p&gt;The full analysis code can be found in this &lt;a href=&quot;http://vallandingham.me/shaw_bros/analyze/analyze_shaw.nb.html&quot;&gt;R Notebook&lt;/a&gt;, which includes the code and graphs in an integrated format. And (spoilers!), the end &lt;a href=&quot;http://vallandingham.me/shaw_bros/&quot;&gt;Actor Collaboration Network&lt;/a&gt; and the rest of the code can be &lt;a href=&quot;https://github.com/vlandham/shaw_bros&quot;&gt;found on github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Come for the Kung Fu, stay for the &lt;a href=&quot;http://vallandingham.me/shaw_bros_analysis.html#silly-kung-fu-titles-with-word2vec&quot;&gt;word embedding&lt;/a&gt; and &lt;a href=&quot;http://vallandingham.me/shaw_bros_analysis.html#finding-a-mob-of-venoms&quot;&gt;interactive networks&lt;/a&gt;!&lt;/p&gt;

&lt;h3 id=&quot;shaw-brothers-through-the-ages&quot;&gt;Shaw Brothers, Through The Ages&lt;/h3&gt;

&lt;p&gt;To get started, here is a look at the count of Shaw Brothers films by year.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/films_by_year.png&quot; alt=&quot;Shaw Bros Films by Year&quot; style=&quot;&quot; /&gt;
&lt;em&gt;I’m using the wonderful &lt;a href=&quot;https://github.com/jrnold/ggthemes&quot;&gt;theme_fivethirtyeight&lt;/a&gt; for these charts. Someday, I’ll make my own.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s &lt;strong&gt;260&lt;/strong&gt; films over 22 years.&lt;/p&gt;

&lt;p&gt;The first Kung Fu Shaw Brothers film in this data set is &lt;a href=&quot;https://letterboxd.com/film/temple-of-the-red-lotus/&quot;&gt;Temple of the Red Lotus&lt;/a&gt; from 1965. From the reviews, it sounds like it was a bit rough around the edges - but that’s about what you would expect from this burgeoning genre.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/temple_of_the_red_lotus.png&quot; alt=&quot;Temple of the Red Lotus&quot; style=&quot;&quot; /&gt;
&lt;em&gt;Looks pretty sweet to me, I’ll have to check it out&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The studio hits its stride in the early 70’s, with a lull in the mid 70’s and another spike in the late 70’s / early 80’s. Keep in mind that even during the lull, most years the studio is still putting out 10 or more Kung Fu movies.&lt;/p&gt;

&lt;p&gt;To create this graph, I first loaded my raw JSON file into R using the &lt;a href=&quot;https://github.com/sailthru/tidyjson&quot;&gt;tidyjson&lt;/a&gt; package like this:&lt;/p&gt;

&lt;div class=&quot;language-R highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# load the library&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tidyjson&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# read the raw json as text&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'../out/shaw.json'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shaw_json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paste&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readLines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collapse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# parse the json into a table, pulling out&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# the variables we want to explore.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shaw_json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;as.tbl_json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gather_array&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spread_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jstring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;director&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jstring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'director'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jstring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'year'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;watches&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jnumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;watches&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;likes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jnumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;likes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jnumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;time&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I then graphed count by year using &lt;a href=&quot;&quot;&gt;ggplot&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-R highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;films&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ggplot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;geom_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Shaw Bros Films by Year'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not too shabby.&lt;/p&gt;

&lt;h3 id=&quot;which-shaw-brothers-film-should-i-watch&quot;&gt;Which Shaw Brothers Film should I watch?&lt;/h3&gt;

&lt;p&gt;If you are just getting started with the Kung Fu classics, 260 movies can be difficult to wade through. How do you get to the best of the best to make your initial experience in this genre a pleasant one?&lt;/p&gt;

&lt;p&gt;Well, we can use the Letterboxd “watches” and “likes” metrics to help winnow down to the films that are the best bang-for-your-buck.&lt;/p&gt;

&lt;p&gt;As you might expect, these two metrics are highly correlated:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/watches_vs_likes.png&quot; alt=&quot;Watches vs Likes&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Basically, anything with more than 400 watches or 100 likes seems like a good place to start. The standout, with over 800 watches is 1984’s &lt;a href=&quot;https://letterboxd.com/film/eight-diagram-pole-fighter/&quot;&gt;Eight Diagram Pole Fighter&lt;/a&gt;. Not the catchiest title, but as one reviewer puts it:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Some of the raddest fights from any Shaw Bros films I’ve seen (specially that last one).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I haven’t seen this one yet, so I can’t comment - but it’s definitely on my list!&lt;/p&gt;

&lt;h3 id=&quot;prolific-directors&quot;&gt;Prolific Directors&lt;/h3&gt;

&lt;p&gt;We have the director for each movie in our dataset, let’s look to see if there are any popular standouts.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/director_count.png&quot; alt=&quot;Top Directors&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’d say! &lt;a href=&quot;https://en.wikipedia.org/wiki/Chang_Cheh&quot;&gt;Chang Cheh&lt;/a&gt; directed 67 or roughly 26% of all Shaw Brothers Kung Fu!&lt;/p&gt;

&lt;p&gt;According to his Wikipedia page, he was known as the “The Godfather of Hong Kong cinema”, and rightly so - at least in terms of quantity.&lt;/p&gt;

&lt;p&gt;Let’s pull out the top 5 directors, in terms of movie count, and see when they were most active.&lt;/p&gt;

&lt;p&gt;Here’s the R code:&lt;/p&gt;

&lt;div class=&quot;language-R highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# pull out just the top 5 directors&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top_directors&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;by_director&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# filter films to those directed by these titans of Kung Fu&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films_top_director&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;director&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%in%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top_directors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;director&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# add a label to distinguish top directors from everyone else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films_top_director_all&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;director_label&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifelse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;director&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%in%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top_directors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;director&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;director&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Other'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# graph&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films_top_director_all&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ggplot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;geom_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;director_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Shaw Bros Director Count by Year'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;theme_fivethirtyeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and plot:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/top_directors_by_year.png&quot; alt=&quot;Top Directors by Year&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can kind of see that Chang Cheh’s reign is towards the beginning of the Shaw Brothers timeline and tapers towards the end. Let’s view the same data as a percentage of the total movies made each year:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/top_directors_by_year_fill.png&quot; alt=&quot;Top Directors by Year&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This shows how dominate Chang Cheh was in directing nearly half of Shaw Brothers films in some years. In the mid and later years, Chor Yuen came in to direct many films as well.&lt;/p&gt;

&lt;h2 id=&quot;title-showdown-shaolin-vs-swordsman&quot;&gt;Title Showdown: Shaolin vs Swordsman&lt;/h2&gt;

&lt;p&gt;We will get to the actors in these films in a second, but first I wanted to explore the words used in the titles of these movies.&lt;/p&gt;

&lt;p&gt;These classic Kung Fu films typically have thrilling and mysterious names, like &lt;a href=&quot;https://letterboxd.com/film/the-thundering-sword/&quot;&gt;The Thundering Sword&lt;/a&gt; and &lt;a href=&quot;https://letterboxd.com/film/the-invincible-fist/&quot;&gt;The Invincible Fist&lt;/a&gt;. I wondered if there were any terms used frequently in titles, common threads or themes that became popular in the genre.&lt;/p&gt;

&lt;p&gt;As I really wanted a chance to play a bit with the exciting new &lt;a href=&quot;https://github.com/juliasilge/tidytext&quot;&gt;tidytext&lt;/a&gt; package, I decided to use it for this very simple text analysis.&lt;/p&gt;

&lt;p&gt;This package works well to extract text-based data into a format ready to be analyzed and parsed with dplyr, ggplot, and other packages from the &lt;a href=&quot;https://blog.rstudio.org/2016/09/15/tidyverse-1-0-0/&quot;&gt;tidyverse&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is how to split the titles column of our dataset so that each word is a separate row in a new data frame.&lt;/p&gt;

&lt;div class=&quot;language-R highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# load the library&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tidytext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# saves entire title in `title_all` column,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# then splits up title column creating the `word` column -&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# with a row for every token (word).&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titles&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title_all&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unnest_tokens&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not too difficult right?&lt;/p&gt;

&lt;p&gt;I also wanted to remove &lt;a href=&quot;https://en.wikipedia.org/wiki/Stop_words&quot;&gt;stop words&lt;/a&gt;, and that can be easily done with the included &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stop_words&lt;/code&gt; data:&lt;/p&gt;

&lt;div class=&quot;language-R highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# load stop_words into R environment&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;stop_words&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# filter stopwords&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titles_filter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titles&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anti_join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop_words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;word&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anti_join&lt;/code&gt; is part of the dplyr package.&lt;/p&gt;

&lt;p&gt;Let’s take a look at the most frequently used words in these Shaw Brothers films.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/top_words_in_titles.png&quot; alt=&quot;Top Words in Titles&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Interesting! Our latest two films from my Netflix history were the afore mentioned &lt;a href=&quot;https://letterboxd.com/film/executioners-from-shaolin/&quot;&gt;Executioners of Shaolin&lt;/a&gt; and &lt;a href=&quot;https://letterboxd.com/film/shaolin-martial-arts/&quot;&gt;Shaolin Martial Arts&lt;/a&gt;, but I hadn’t realized “Shaolin” movies were so prevalent in the Shaw Brothers cannon.&lt;/p&gt;

&lt;p&gt;Also interesting is the number of “Swordsman” movies - a term I don’t remember seeing yet.&lt;/p&gt;

&lt;p&gt;Were these terms associated with different eras? Let’s graph their usage over time:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/top_words_by_time.png&quot; alt=&quot;Top Words in Titles over time&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It would appear as if “Swordsman” movies were the hot stuff during early Shaw Brothers years, but they switched to mostly Shaolin’s in the mid-seventies. Here are the two terms overlaid:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/shaolin_swordsman.png&quot; alt=&quot;Top Words in Titles over time&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now the count-per-year isn’t mind-blowing or anything, but it does seem interesting that there was at least one movie with “Swordsman” in the title for six straight years, before an explosion of “Shaolin”.&lt;/p&gt;

&lt;p&gt;I wanted to investigate a bit further. One of the first Swordsman movies they created was &lt;a href=&quot;https://letterboxd.com/film/the-one-armed-swordsman/&quot;&gt;The One Armed Swordsman&lt;/a&gt;, and &lt;a href=&quot;https://en.wikipedia.org/wiki/One-Armed_Swordsman&quot;&gt;according to Wikipedia&lt;/a&gt; it was a big hit.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It was the first of the new style of wuxia films emphasizing male anti-heroes, violent swordplay and heavy bloodletting. It was the first Hong Kong film to make HK$1 million at the local box office, propelling its star Jimmy Wang to super stardom.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I must confess, being a casual enjoyer of Kung Fu, I was not familiar with the term “Wuxia”, so this needed a bit more investigation.&lt;/p&gt;

&lt;p&gt;Almost immediately, I found a useful description from &lt;a href=&quot;https://theendofcinema.net/2016/02/11/30-essential-wuxia-films/&quot;&gt;This essential guide to Wuxia&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Chinese martial arts movie is generally split into two primary subgeneres: the kung fu film and the wuxia film. The kung fu film is newer and focuses primarily on hand-to-hand combat, it’s steeped in traditional fighting forms and there’s a general emphasis on the physical skill of the performer: special effects are generally disdained.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wuxia is a much older form, based ultimately in the long tradition of Chinese adventure literature … Its heroes follow a very specific code of honor as they navigate the jianghu, an underworld of outlaws and bandits outside the normal streams of civilization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ah Ha! So the Swordsman / Shaolin dichotomy could be representative of the switch from this older style wuxia, to the new hip pure Kung Fu. The reappearance of both terms in the eighties could indicate a new found enjoyment for both styles. Apparently more famous modern films like &lt;a href=&quot;http://www.imdb.com/title/tt0190332/?ref_=nv_sr_1&quot;&gt;Crouching Tiger, Hidden Dragon&lt;/a&gt; fall into the wuxia category.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/crouching_tiger.jpg&quot; alt=&quot;Crouching Tiger&quot; style=&quot;&quot; /&gt;
&lt;em&gt;I say “modern” here, but can you believe this movie is 17 years old? Time flies!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Or, it could be that the creators of these movies were lazy and just wanted to rely on the success of &lt;em&gt;The One Armed Swordsman&lt;/em&gt; to make some money. Either way, its an interesting split.&lt;/p&gt;

&lt;p&gt;Not knowing much about Chinese culture from that time period, I was also interested in learning more as to why “Shaolin” in particular was such a buzzword for Kung Fu movies. I’m still learning, but I found a great essay on &lt;a href=&quot;http://thevulgarcinema.com/2015/12/history-in-the-shaw-brothers/&quot;&gt;history in the Shaw Brothers&lt;/a&gt; that points to an answer:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;These films, focused on the Shaolin Temple as a center for anti-Qing resistance, provide a dizzying metaphorical potential, with the Qing variously standing in for Western imperialists, the Japanese, the Nationalist Kuomingtang, the Communists, or even simply the Manchurians themselves, while the Buddhism of the monks allows for examining of the contradictions at the heart of traditional Chinese belief systems, between the imperatives of social justice and withdrawal from worldly concerns.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;silly-kung-fu-titles-with-word2vec&quot;&gt;Silly Kung Fu Titles with word2vec&lt;/h2&gt;

&lt;p&gt;Inspired by the ever wonderful &lt;a href=&quot;https://twitter.com/arnicas&quot;&gt;Lynn Cherny’s&lt;/a&gt; &lt;a href=&quot;http://blogger.ghostweather.com/2014/11/visualizing-word-embeddings-in-pride.html&quot;&gt;word2vec experimentation&lt;/a&gt;, I wanted to use this opportunity to experiment just a bit with word embeddings and &lt;a href=&quot;http://p.migdal.pl/2017/01/06/king-man-woman-queen-why.html&quot;&gt;“word arithmetic”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I came up with an idea too silly to be useful, but fun for me to play with. For each noun detected in a title, I used &lt;a href=&quot;https://radimrehurek.com/gensim/models/word2vec.html&quot;&gt;Gensim’s word2vec&lt;/a&gt; implementation to find the nearest word to that noun, after subtracting “Chinese”, and adding another country.&lt;/p&gt;

&lt;p&gt;Again, don’t take this seriously, I was just wanting to see what would happen.&lt;/p&gt;

&lt;p&gt;So, cherry-picking a comical example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;buddha - Chinese + American = God Fearin'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See? kind of funny at least in theory. I did this for every title, for a number of different countries. In practice, the results aren’t as hilarious as I had hopped for, probably because country vectors don’t impact the trajectory of most of these words much. Also, I used a &lt;a href=&quot;https://code.google.com/archive/p/word2vec/&quot;&gt;pre-trained model&lt;/a&gt; which obviously impacts the embeddings.&lt;/p&gt;

&lt;p&gt;But, I made a little toy for exploring these new titles anyways, check it out!&lt;/p&gt;

&lt;iframe frameborder=&quot;0&quot; height=&quot;300px&quot; src=&quot;https://vallandingham.me/shaw_bros/titles.html&quot; width=&quot;100%&quot; id=&quot;titlesIframe&quot; scrolling=&quot;no&quot; style=&quot;overflow: hidden;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/vlandham/shaw_bros/tree/master/data/titles&quot;&gt;raw results&lt;/a&gt; and the &lt;a href=&quot;https://github.com/vlandham/shaw_bros/blob/master/tools/title_fun.ipynb&quot;&gt;code I used&lt;/a&gt; to generate these are also available.&lt;/p&gt;

&lt;h2 id=&quot;actor-troupes-groups-and-clusters&quot;&gt;Actor Troupes, Groups, and Clusters&lt;/h2&gt;

&lt;p&gt;Let’s end this exploration with a few insights into the actors in these films.&lt;/p&gt;

&lt;p&gt;Even with my novice-level consumption of Shaw Brothers films, one thing you notice early on is a lot of familiar faces show up over and over in many of the movies.&lt;/p&gt;

&lt;p&gt;We can see the extent of actor-over-use with another simple chart counting the number of movies frequently seen actors are found in.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/actor_counts.png&quot; alt=&quot;Actors in Movies&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wow! &lt;a href=&quot;https://en.wikipedia.org/wiki/Ku_Feng&quot;&gt;Ku Feng&lt;/a&gt; apparently appeared in 82 Kung Fu movies. That’s a lot of Kung Fu!&lt;/p&gt;

&lt;p&gt;His Wikipedia page isn’t as impressed with this feat as I am, providing little information on this Martial Arts Maniac. Apparently his real name is Chan Sze-man, and his first film was in 1959, and he is still acting today! The &lt;a href=&quot;http://hkmdb.com/db/people/view.mhtml?id=3579&amp;amp;display_set=eng&quot;&gt;HKMDB&lt;/a&gt;, or Hong Kong Movie Database, provides just a bit more info:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In 1965, Ku formally signed an acting contract with Shaw Brothers where he made around 100 films for them and became most notably known as one of their top character actors. He has worked with just about every top Hong Kong director in a variety of films.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok then, well props to you Ku.&lt;/p&gt;

&lt;p&gt;Did most of the top actors’ careers span multiple decades, or did actors come and go quickly?&lt;/p&gt;

&lt;p&gt;We can graph the number of years an actor was featured in a movie over the total number of years in our dataset:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/actor_percent_active.png&quot; alt=&quot;Percent Actors in Movies&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For the top actors, we see most were active more than half of the entire time Shaw Brothers Studios was making Kung Fu movies.&lt;/p&gt;

&lt;p&gt;Here’s another quick graph showing the beginning and ending of these actors’ tenures:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/actor_career_span.png&quot; alt=&quot;Actors start and end&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;finding-a-mob-of-venoms&quot;&gt;Finding a Mob of Venoms&lt;/h3&gt;

&lt;p&gt;One phrase that came up when researching these Shaw Brothers films, related to actor-reuse, is &lt;a href=&quot;https://en.wikipedia.org/wiki/Venom_Mob&quot;&gt;the Venom Mob&lt;/a&gt;, a group of actors that did indeed appear in a lot of Shaw Brothers films together. They became well known after the success of &lt;a href=&quot;https://letterboxd.com/film/the-five-venoms/&quot;&gt;The Five Venoms&lt;/a&gt;, hence the catchy name.&lt;/p&gt;

&lt;p&gt;So, can we find a &lt;em&gt;Mob of Venoms&lt;/em&gt; in our data?&lt;/p&gt;

&lt;p&gt;Inspired by David Robinson’s &lt;a href=&quot;http://varianceexplained.org/r/love-actually-network/&quot;&gt;network analysis of Love Actually&lt;/a&gt;, I decided to try out the &lt;a href=&quot;http://igraph.org/r/&quot;&gt;igraph&lt;/a&gt; package for a bit of network exploration.&lt;/p&gt;

&lt;p&gt;After a lot of filtering and frustration, I ended up with a basic, but still fairly hairball-y network:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;zoom center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/actor_network.png&quot; alt=&quot;Actor Network&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this network, the nodes are actors who have appeared in many films. The edges are co-occurrences of actors in the same movies, with the width of the edges proportional to the number of movies they were found together in.&lt;/p&gt;

&lt;p&gt;You can see that there are a lot of actors appear together.&lt;/p&gt;

&lt;p&gt;The Venom Mob includes &lt;a href=&quot;https://en.wikipedia.org/wiki/Chiang_Sheng&quot;&gt;Chiang Sheng&lt;/a&gt;, so here, I’ve highlighted in red everyone he is connected with. In this sub-cluster, you can see &lt;a href=&quot;https://en.wikipedia.org/wiki/Philip_Kwok&quot;&gt;Philip Kwok&lt;/a&gt;, Lu Feng, and many of the other Venoms.&lt;/p&gt;

&lt;p&gt;igraph is great for digging into properties of nodes, edges, and networks - and there is plenty more that could be done in this tool just for this simple dataset. I however, was wanting a bit more of an interactive exploratory tool that I could use to browse Kung Fu actor connections.&lt;/p&gt;

&lt;p&gt;You were too? Great! That’s why I created the amazing &lt;a href=&quot;http://vallandingham.me/shaw_bros/&quot;&gt;Shaw Brothers Actors Network Visualization&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/shaw_bros/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/shaw_bros/shaw_networktool2.png&quot; alt=&quot;Actor Network&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With it, you can clearly pick out the Venom Mob on the right, in the screenshot. But that’s not all, you can also browse all the movies actors appeared together in, and modify the network in lots of fun ways.&lt;/p&gt;

&lt;p&gt;The code is based on my &lt;a href=&quot;http://flowingdata.com/2012/08/02/how-to-make-an-interactive-network-visualization/&quot;&gt;interactive network Flowing Data tutorial&lt;/a&gt;, which recently has been updated to use &lt;a href=&quot;https://github.com/vlandham/interactive-network-v4&quot;&gt;plain old Javascript and D3v4&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That wraps up my little data-driven exploration of Shaw Brothers films. As with any analysis, there’s plenty more to explore - but hopefully this was fun for you too, and inspires some data-driven exploration of your own.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Creating Bubble Charts with D3v4</title>
   <link href="http://vallandingham.me/bubble_charts_with_d3v4.html"/>
   <updated>2016-11-13T00:00:00+00:00</updated>
   <id>http://vallandingham.me/bubble_charts_with_d3v4</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/bubble_chart_v4/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/bubble_chart_d3v4/bubbles_header.jpg&quot; style=&quot;width:700px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, as you probably have seen, heard, and experienced, our beloved D3 has shed its skin, and metamorphosed into a shiny new version. &lt;a href=&quot;https://d3js.org/&quot;&gt;D3v4&lt;/a&gt; is out and ready for engaging with by interactive data visualizationers world wide. Its full of fun new features and optimizations for us all to appreciate and enjoy.&lt;/p&gt;

&lt;p&gt;But as you would expect from a major version increment, there are some breaking changes as you move from v3 to v4. Most of these, like the &lt;a href=&quot;https://github.com/d3/d3/blob/master/CHANGES.md#scales-d3-scale&quot;&gt;renaming of scales&lt;/a&gt; and using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.merge&lt;/code&gt; because &lt;a href=&quot;https://bl.ocks.org/mbostock/3808218&quot;&gt;selections are now immutable&lt;/a&gt; are fairly straightforward to find and modify in existing code.&lt;/p&gt;

&lt;p&gt;The force layout, however, has received a significant facelift, which may cause it to not be all that recognizable anymore, even to close friends. I believe &lt;a href=&quot;https://twitter.com/jburnmurdoch&quot;&gt;John Burn-Murdoch&lt;/a&gt; puts it well, when he says:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Transitioning to &lt;a href=&quot;https://twitter.com/hashtag/d3js?src=hash&quot;&gt;#d3js&lt;/a&gt; version 4 was going so well, and then ... force layouts &lt;a href=&quot;https://t.co/EAWcRpsspX&quot;&gt;pic.twitter.com/EAWcRpsspX&lt;/a&gt;&lt;/p&gt;&amp;mdash; John Burn-Murdoch (@jburnmurdoch) &lt;a href=&quot;https://twitter.com/jburnmurdoch/status/791590687070355458&quot;&gt;October 27, 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;As many of &lt;em&gt;my&lt;/em&gt; previous tutorials and talks use the force layout to some effect, I wanted to share what I’ve learned from converting some of them to use the new v4 API and stymie just a bit the inevitable bit rot and decay that accompanies the never-ending march of technology.&lt;/p&gt;

&lt;p&gt;To that end, I’ve reimplemented my &lt;a href=&quot;http://vallandingham.me/bubble_charts_in_js.html&quot;&gt;old bubble chart tutorial&lt;/a&gt; and example to use D3v4. I’d like to share what I’ve learned along the way and how you can use the new force simulation in your own projects.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;http://vallandingham.me/bubble_chart_v4&quot;&gt;demo&lt;/a&gt; and &lt;a href=&quot;https://github.com/vlandham/bubble_chart_v4&quot;&gt;source code&lt;/a&gt; to see the new cool version, then come back here to see how its done.&lt;/p&gt;

&lt;p&gt;The bubble chart makes use of the force simulation capabilities of D3 so its useful to get an overview of what the new force API looks like. Then we will dive into the code to make this fun, splittable bubble chart.&lt;/p&gt;

&lt;h2 id=&quot;force-fundamentals&quot;&gt;Force Fundamentals&lt;/h2&gt;

&lt;p&gt;Fundamentally, the general idea of the force hasn’t changed. It works as a little physics simulation, ran multiple times until it runs out of energy and stabilizes. Each iteration or “tick” of the simulation, forces are “applied” to nodes and edges - meaning they push and pull on them in various manners.&lt;/p&gt;

&lt;p&gt;These forces (and other parameters of the simulation) determine where the nodes should be each tick, then it is up to us to visually represent the nodes and edges as we see fit and move them to their specified positions.&lt;/p&gt;

&lt;p&gt;With this general framework in mind, let’s look at how this is implemented in D3v4 and how it differs from the previous versions of D3.&lt;/p&gt;

&lt;h2 id=&quot;starting-up-a-simulation&quot;&gt;Starting up a Simulation&lt;/h2&gt;

&lt;p&gt;In the old world of D3 version 3, the force layout was an amalgamation of parameters and functions that configured a good baseline of effects applied to the nodes and edges of your graph.&lt;/p&gt;

&lt;p&gt;The new D3v4 force more cleanly separates the setup of the &lt;em&gt;force simulation&lt;/em&gt; from the forces applied to entities in the simulation. Instead of the old all-in-one approach, this abstraction provides an easy way to compose multiple simple forces together in a simulation to make something magical.&lt;/p&gt;

&lt;p&gt;Let’s take a look at this new API in comparison with the old one.&lt;/p&gt;

&lt;p&gt;Previously, as mentioned, we would create a new force layout with a bunch of parameters, like so:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// old v3 layout creation&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gravity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;friction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With v4, we create a new instance of the &lt;em&gt;forceSimulation&lt;/em&gt; to house our nodes and edges as well as the forces applied to them. Most of the configuration of the old API is gone. Instead, as we will see, we configure the individual forces, instead of the simulation as a whole.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// new v4 force simulation creation&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;simulation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;forceSimulation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;velocityDecay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We don’t even specify a size anymore! There are still some things you can configure at the simulation level. Here we adjust the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;velocityDecay&lt;/code&gt; which &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/README.md#simulation_velocityDecay&quot;&gt;as stated in the documentation&lt;/a&gt;, works like friction, adjusting the velocity of the nodes by multiplying by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 - velocityDecay&lt;/code&gt; each tick.&lt;/p&gt;

&lt;p&gt;This points to some changes in what attributes are stored in each node, which we will look more closely at in a bit.&lt;/p&gt;

&lt;p&gt;The simulation also controls the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; or “energy” of the simulation  (&lt;em&gt;this&lt;/em&gt; alpha has nothing to do with opacity - as it is sometimes indicates when talking about colors). As the simulation progresses, the alpha decreases, and the simulation loses power and slows down. Eventually, when alpha reaches a threshold, the simulation stops. The rate of decay of the simulation can be adjusted via the &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/README.md#simulation_alphaDecay&quot;&gt;alphaDecay&lt;/a&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; that in v4, the simulation &lt;strong&gt;starts automatically&lt;/strong&gt;, without having a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.start()&lt;/code&gt; method. If you want it to hold off, say until you have added some nodes to the simulation, then you want to follow the creation of the simulation with:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;simulation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To keep that from happening.&lt;/p&gt;

&lt;h2 id=&quot;noodling-on-the-nodes&quot;&gt;Noodling on the Nodes&lt;/h2&gt;

&lt;p&gt;Ok, I’ve said “nodes” about a hundred times already, but what are they?&lt;/p&gt;

&lt;p&gt;Nodes are the input data to your simulation. You can pass in an array of nodes when you initially call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forceSimulation&lt;/code&gt;, or you can add them more explicitly via the &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/README.md#simulation_nodes&quot;&gt;nodes&lt;/a&gt; method:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myNodes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}];&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;simulation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;myNodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see from the above example, each node should be an object. This object can contain attributes about the data you are representing, but it also is where the force simulation puts node positioning information.&lt;/p&gt;

&lt;p&gt;With D3v4, each node object you provide will get the following attributes added to it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; - the current x position of the node.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; - the current y position of the node.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vx&lt;/code&gt; - the node’s velocity in the x direction.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vy&lt;/code&gt; - the node’s velocity in the y direction.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt; - the index of the node in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nodes&lt;/code&gt; array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main differences between old and new force with respect to nodes, are those velocity bits.&lt;/p&gt;

&lt;p&gt;In D3v3, there was no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vx&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vy&lt;/code&gt;. Instead, the simulation kept track of the &lt;em&gt;previous position&lt;/em&gt; that the node was in using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dx&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dy&lt;/code&gt;. This doesn’t matter too much for our Bubble Chart implementation, but affects things like how collision prevention works.&lt;/p&gt;

&lt;h2 id=&quot;forces-galore&quot;&gt;Forces Galore&lt;/h2&gt;

&lt;p&gt;Finally we get to the coolest part of the D3v4 force simulation - and also the most different and confusing part (at least to me): forces!&lt;/p&gt;

&lt;p&gt;That collision prevention I just mentioned above? Thats powered by a force! In fact most of the details of positioning nodes in the force simulation is now left in the capable hands of one or more forces that get added to the simulation.&lt;/p&gt;

&lt;p&gt;Each force is a function that gets called during each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; of the simulation. Its job is the modify the position of some or all nodes in the simulation, using those node attributes discussed above.&lt;/p&gt;

&lt;p&gt;And while creating our own force functions should be fairly easy, thanks to Mike Bostock’s hard work, we get a great force starter pack built right in to D3! Check out &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/README.md#forces&quot;&gt;the forces API docs&lt;/a&gt; to find forces made for x and y positioning, centering, and preventing collisions.&lt;/p&gt;

&lt;p&gt;This distinction between the simulation and the forces applied to the simulation allows each force to care only about configuring itself. This also allows the users of these forces (us) to combine them in interesting ways to solve the unique problems of our force layout needs.&lt;/p&gt;

&lt;p&gt;Adding a force to the simulation is straightforward. Here is an example of adding the &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/README.md#centering&quot;&gt;centering force&lt;/a&gt; which keeps nodes centered on a particular point:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;simulation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceCenter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding a force using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;force&lt;/code&gt; method takes a name for the force and then the instance of the force itself. We can configure the force as it is constructed. For the centering force, this means telling it where you want the nodes centered.&lt;/p&gt;

&lt;p&gt;Each force has its own quirks and configurations, so go check out the &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/README.md#forces&quot;&gt;documentation&lt;/a&gt; for the details.&lt;/p&gt;

&lt;h2 id=&quot;bigger-stronger-faster-bubble-charts&quot;&gt;Bigger, Stronger, Faster, Bubble Charts&lt;/h2&gt;

&lt;p&gt;Now that we have seen all the great new stuff about forces in D3v4, let’s finish off with how to implement a bubble chart with it.&lt;/p&gt;

&lt;p&gt;As pointed out a few times now, &lt;a href=&quot;https://github.com/vlandham/bubble_chart_v4&quot;&gt;the code is on Github&lt;/a&gt; and &lt;a href=&quot;http://vallandingham.me/bubble_chart_v4&quot;&gt;here is a demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most of the code is fairly generic D3 - so let’s focus on the interesting force simulation bits.&lt;/p&gt;

&lt;p&gt;We initialize the simulation with a few forces in place:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// constants used in the simulation&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;forceStrength&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.03&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;simulation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceSimulation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;velocityDecay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceStrength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceStrength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceManyBody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ticked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we create a new simulation and add some forces to it. The forces named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; use positioning forces to push our nodes (which haven’t been added yet) towards the center of the visualization. We use these positioning forces instead of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forceCenter&lt;/code&gt; because, as the documentation states:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This force helps keeps nodes in the center of the viewport, and unlike the positioning force, it does not distort their relative positions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But I &lt;em&gt;want&lt;/em&gt; to distort their relative positions. I want them to all crowd around and jostle for the center.&lt;/p&gt;

&lt;p&gt;Then we add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forceManyBody&lt;/code&gt; force to make the nodes repulse away from each other. In D3v3, we had access to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; method, which assigned a positive or negative charge for each node. The many body force provides a similar capability, but is a heck of a lot faster then before.&lt;/p&gt;

&lt;p&gt;And as you would expect, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strength&lt;/code&gt; of this force is a function that gets called &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/README.md#manyBody_strength&quot;&gt;for every node&lt;/a&gt; so we can adjust the charge based on some data attribute of our nodes.&lt;/p&gt;

&lt;p&gt;Here is what the charge function looks like that is passed in as the force’s strength:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceStrength&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We based the charge on each node’s radius. The same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forceStrength&lt;/code&gt; as what is used in the positioning forces is used here, so that all the forces work with the same amount of strength (which took some experimentation to make look “right”). The value returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; is negative, so the nodes repulse one another.&lt;/p&gt;

&lt;p&gt;The end result of this many body force is that each node will avoid overlapping other nodes. We could have also used the &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/README.md#collision&quot;&gt;Collision&lt;/a&gt; force, to prevent overlap, but with the many body force, the effect is more “organic” looking.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href=&quot;https://github.com/MichaelCurrie/bubble_chart&quot;&gt;Michael Currie’s awesome version&lt;/a&gt; of the bubble chart to see how to use collision instead of many body.&lt;/p&gt;

&lt;p&gt;Finally we provide a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; callback method that will draw the nodes after each iteration of the simulation.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ticked&lt;/code&gt; function for this is super simple, as it just moves the SVG circles used to make the bubbles to their new positions:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ticked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;bubbles&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;cx&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;cy&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Awesome. So now we have our bubbles all coalescing together in a big bubble pile.&lt;/p&gt;

&lt;p&gt;Note that we aren’t using any transitions here. The “animation” is taken care of by the rapid repeated execution of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ticked&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;But how do we get them to split apart and into their categorical groupings? Well, that might be &lt;em&gt;the one interesting trick&lt;/em&gt; this post can reveal.&lt;/p&gt;

&lt;p&gt;It turns out if we add a force to a force simulation using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;force()&lt;/code&gt; and use the name of an existing force, it will first remove that existing force and then initialize our new force. You can see this &lt;a href=&quot;https://github.com/d3/d3-force/blob/master/src/simulation.js&quot;&gt;in the force function’s  implementation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This means we can clobber our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; force with a new one, then restart the simulation, and it will start using the new force with no issues. Great stuff!&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/bubble_chart_d3v4/split_bubbles.jpg&quot; style=&quot;width:700px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For our bubble chart, we can use the following new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forceX&lt;/code&gt; that will replace the “move to the center” force with a “move to your year” force.&lt;/p&gt;

&lt;p&gt;Here’s what it looks like:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// This function is called once for each&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//  node and provides the appropriate&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//  x position for that node&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;nodeYearPos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yearCenters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Reset the x force of the simulation&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;simulation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forceStrength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nodeYearPos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s it! Because of the beautiful composability of forces, the many body and y forces will work together with this new x force to create the node groupings.&lt;/p&gt;

&lt;p&gt;There is one additional detail in that we need to restart the simulation to get the nodes to move to their new locations. We also need to “recharge” the simulation so the nodes have enough energy to get to their new locations.&lt;/p&gt;

&lt;p&gt;We can do that simply by resetting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; of the simulation to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; and restarting:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;simulation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is pretty much it! There are a few additional tweaks to the rest of the code, for scale renaming and such, but rest of the logic is the same. In the &lt;a href=&quot;https://github.com/vlandham/bubble_chart_v4&quot;&gt;source code for the bubble chart&lt;/a&gt; I’ve used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@v4&lt;/code&gt; in the comments for sections that were modified in the switch to D3v4.&lt;/p&gt;

&lt;p&gt;Hopefully this helps kick start your experimentation with the new force simulation awesomeness. Now go out there, build something cool, and let me know what you make!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Becoming a Data Visualization Practitioner</title>
   <link href="http://vallandingham.me/becoming_datavis_practitioner.html"/>
   <updated>2016-08-11T00:00:00+00:00</updated>
   <id>http://vallandingham.me/becoming_datavis_practitioner</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;If I can do it - so can you!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here are some notes on an anecdotal path towards becoming a data visualization practitioner -
Someone who &lt;em&gt;does data vis&lt;/em&gt;. These steps are in rough sequential order, with of course overlap and repeating expected. All resources are tiny subsets of what could or should be included. Such is the nature of resource lists.&lt;/p&gt;

&lt;h2 id=&quot;step-1---ponder&quot;&gt;Step 1 - Ponder&lt;/h2&gt;

&lt;p&gt;Ponder what type of practitioner you would like to be.&lt;/p&gt;

&lt;p&gt;Some options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technically focused&lt;/strong&gt;, typically with computer science background&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.ireneros.com/projects.html&quot;&gt;Irene Ros&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://peterbeshai.com/academic/projects.html&quot;&gt;Peter Beshai&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Design focused&lt;/strong&gt;, with entry points into data vis&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://giorgialupi.com/work&quot;&gt;Giorgia Lupi&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.stefanieposavec.co.uk/&quot;&gt;Stefanie Posavec&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://feltron.com/&quot;&gt;Nicholas Felton&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://tonyhschu.ca/&quot;&gt;Tony Chu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Domain focused&lt;/strong&gt;, providing expertise to a narrow&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Biology - &lt;a href=&quot;http://clearscience.info/wp/&quot;&gt;Bang Wong&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Music - &lt;a href=&quot;http://www.chenalexander.com/&quot;&gt;Alexander Chen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;General Advocate&lt;/strong&gt;, preaching to the masses.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://policyviz.com/&quot;&gt;Jon Schwabish&lt;/a&gt; (also is a domain expert on vis in government)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://complexdiagrams.com/&quot;&gt;Noah Illinsky&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Academic focused&lt;/strong&gt;, do data vis in a research setting (often overlaps with domain expert)&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://vialab.science.uoit.ca/portfolio/christopher-m-collins&quot;&gt;Christopher Collins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Journalism focused&lt;/strong&gt;, some of the best vis out there comes from newspapers&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://roadtolarissa.com/&quot;&gt;Adam Pearce&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/kennelliott&quot;&gt;Kennedy Elliott&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course many people expand, overlap, and break out of these categories.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://truth-and-beauty.net/&quot;&gt;Moritz Stefaner&lt;/a&gt; is a example of someone who has combined technical, design, and academic focuses.&lt;/p&gt;

&lt;p&gt;Also, you don’t have to use any of these generalized “templates” or even decide which type to become now, its just useful to keep these broad categories in your head.&lt;/p&gt;

&lt;h2 id=&quot;step-2-read&quot;&gt;Step 2: Read&lt;/h2&gt;

&lt;p&gt;You need to get a base line of existing data visualization examples, practices, and research. You will start to develop methodologies of how to talk about data vis, and what has been done in data vis. This comes in the form of books, blogs, and research papers.&lt;/p&gt;

&lt;p&gt;Suggested reading list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Books:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.edwardtufte.com/tufte/books_vdqi&quot;&gt;The Visual Display of Quantitative Information&lt;/a&gt; - Tufte&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://book.flowingdata.com/&quot;&gt;Visualize This&lt;/a&gt; - Nathan Yau&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.thefunctionalart.com/p/about-book.html&quot;&gt;The Functional Art&lt;/a&gt; - Alberto Cairo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Research Papers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://fellinlovewithdata.com/guides/7-classic-foundational-vis-papers&quot;&gt;All classics from this post&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://worrydream.com/&quot;&gt;All Bret Victor’s Work&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://benfry.com/phd/dissertation-110323c.pdf&quot;&gt;Ben fry’s dissertation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Blog Posts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.visualcomplexity.com/vc/blog/?p=644&quot;&gt;Information Visualization Manifesto&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://fellinlovewithdata.com/interviews/data-visualization-freelancin&quot;&gt;How to become a data vis freelancer (video)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;step-3-monitor&quot;&gt;Step 3: Monitor&lt;/h2&gt;

&lt;p&gt;Get a sense of what has been happening in the world of data visualization recently.&lt;/p&gt;

&lt;p&gt;The readings address the history of data vis, but you also want to see what is going on RIGHT NOW.&lt;/p&gt;

&lt;p&gt;Blogs to scroll through:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://flowingdata.com/&quot;&gt;Flowing Data&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.nytimes.com/interactive/2014/12/29/us/year-in-interactive-storytelling.html&quot;&gt;2014 New York Times Interactives&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.nytimes.com/interactive/2015/us/year-in-interactive-storytelling.html&quot;&gt;2015 New York Times Interactives&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://bl.ocks.org/mbostock&quot;&gt;Mike Bostock’s Visual Creations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://visualizingeconomics.com/&quot;&gt;Visualizing Economics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://junkcharts.typepad.com/junk_charts/&quot;&gt;Junk Charts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://eagereyes.org/&quot;&gt;Eagereyes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.thefunctionalart.com/&quot;&gt;the functional art&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additional Twitter People to follow:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/arnicas&quot;&gt;Lynn Cherney&lt;/a&gt; - vis, data science &amp;amp; python&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/NadiehBremer&quot;&gt;Nadieh Bremer&lt;/a&gt; - d3, style &amp;amp; interactives&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/Elijah_Meeks&quot;&gt;Elijah Meeks&lt;/a&gt; - networks &amp;amp; opinions&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/krees&quot;&gt;Kim Rees&lt;/a&gt; - do good with data&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/wattenberg&quot;&gt;Martin Wattenberg&lt;/a&gt; - google and famous&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/13pt&quot;&gt;Jonathan Corum&lt;/a&gt; - science and news&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/hadleywickham&quot;&gt;Hadley Wickham&lt;/a&gt; - R, data science&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/mbostock&quot;&gt;Mike Bostock&lt;/a&gt; - D3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Audio:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://datastori.es/&quot;&gt;Data Stories&lt;/a&gt; - podcasts&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://policyviz.com/&quot;&gt;Policy Vis&lt;/a&gt; - podcasts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;step-4-learn&quot;&gt;Step 4: Learn&lt;/h2&gt;

&lt;p&gt;Should be done concurrently with Step 3 and Step 5.&lt;/p&gt;

&lt;p&gt;In order to create visualizations or talk about the creation of visualizations, you are going to need to learn how to use some tools.&lt;/p&gt;

&lt;p&gt;These tools could be programming languages, code libraries or toolkits, or even GUI-based desktop applications.&lt;/p&gt;

&lt;p&gt;Some suggestions. The important thing is to not try to learn them all at once, but pick one or two to explore based on your current strengths:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Programming Languages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.r-project.org/&quot;&gt;R&lt;/a&gt; - if you want to do static images and data exploration, its hard to beat R. The ‘&lt;a href=&quot;https://www.tidyverse.org/&quot;&gt;tidyverse&lt;/a&gt;’(ggplot2, dplyr, etc) of tools originally built by Hadley Wickham is really a full stack for researching and visualizing data. The R language is weird and not the easiest - but with a few concepts under your belt, you become very powerful.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt; - if you want a more standard scripting language to work with, try python. &lt;a href=&quot;http://pandas.pydata.org/&quot;&gt;Pandas&lt;/a&gt;, &lt;a href=&quot;http://matplotlib.org/&quot;&gt;Matplotlib&lt;/a&gt;, and &lt;a href=&quot;https://seaborn.pydata.org/&quot;&gt;Seaborn&lt;/a&gt;: go a long way to munging and visualizing data.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://processing.org/&quot;&gt;Processing&lt;/a&gt; - for more design / educational tool, processing is great. Many of the tutorials are moving to Processing.js - a javascript port of the tool. This allows for the creation of web-based interactive visualizations as well. But standard Processing is still a powerful and interesting option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Libraries &amp;amp; Toolkits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://d3js.org/&quot;&gt;D3&lt;/a&gt; - Javascript library, still the Czar of interactive data visualizations. If you want to make interactives, and want them on the web - you should probably take a look at D3.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://processingjs.org/&quot;&gt;Processing.js&lt;/a&gt; - as mentioned, Processing.js is a great tool for ‘painting with data’. it takes a different paradigm then D3 - which some might find easier to reason about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Desktop Applications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://office.live.com/start/Excel.aspx&quot;&gt;Excel&lt;/a&gt; - Still the workhorse of the non-programmer data world, its good to have some basic knowledge of Excel just to be able to share spreadsheets and quick analysis with others. And you can make some pretty interesting visualizations with it (as long as you stay away from the defaults).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.tableau.com/&quot;&gt;Tableau&lt;/a&gt; - Success story of the Business Intelligence (BI) world, Tableau has matured into a robust and fast data exploration and visualization suite. I would pick this over Excel for non-coding exploration. Their flagship product is expensive, but they also have &lt;a href=&quot;https://public.tableau.com/s/&quot;&gt;Tableau Public&lt;/a&gt; which is free and the way to start.&lt;/p&gt;

&lt;h2 id=&quot;step-5-create&quot;&gt;Step 5: Create&lt;/h2&gt;

&lt;p&gt;Should be done concurrently with Step 3 and Step 4&lt;/p&gt;

&lt;p&gt;Creations can be in the form of&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a visualization (static or interactive)&lt;/li&gt;
  &lt;li&gt;an analysis of a topic or dataset&lt;/li&gt;
  &lt;li&gt;an opinion of a hot data visualization topic&lt;/li&gt;
  &lt;li&gt;an aggregation or collection of visualizations around a central theme&lt;/li&gt;
  &lt;li&gt;a visualization book review&lt;/li&gt;
  &lt;li&gt;a code tutorial or process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start by creating a website to hold your creations.&lt;/p&gt;

&lt;p&gt;I would hands down recommend using &lt;a href=&quot;https://pages.github.com/&quot;&gt;Github Pages&lt;/a&gt; with a custom domain name.
Jekyll (the tool powering these sites) is powerful and useful tool to learn and use.&lt;/p&gt;

&lt;p&gt;You can put javascript interactive as separate repos. its awesome.
And, it only costs ~15$ a year (for the domain name).&lt;/p&gt;

&lt;p&gt;Hopefully you have seen visualizations that resonate with you, or visual forms you might want to explore more.
Alternatively, you might have seen or heard or thought about interesting topics with data you might want to visualize.&lt;/p&gt;

&lt;p&gt;Follow one of these routes down a path to capitalize on your learning and start the creation process.
Creations can be simple, but well done - the best you can at this point in time.
And always cite inspirations and data sources in an ‘about’ section!&lt;/p&gt;

&lt;p&gt;Data to explore:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://tinyletter.com/data-is-plural/archive&quot;&gt;Data is Plural&lt;/a&gt; - hand curated and always interesting.&lt;/li&gt;
  &lt;li&gt;Open data portals: &lt;a href=&quot;https://data.cityofnewyork.us/data&quot;&gt;New York&lt;/a&gt;, &lt;a href=&quot;https://data.seattle.gov/&quot;&gt;Seattle&lt;/a&gt;, and more!&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pinboard.in/u:vlandham/t:data/&quot;&gt;My Pinboard of data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Text Analysis and Visualization Workshop</title>
   <link href="http://vallandingham.me/text-vis-workshop.html"/>
   <updated>2016-04-24T00:00:00+00:00</updated>
   <id>http://vallandingham.me/text-vis-workshop</id>
   <content type="html">&lt;p&gt;For &lt;a href=&quot;https://openvisconf.com/2016/&quot;&gt;OpenVis Conf 2016&lt;/a&gt;, we had the wonderful opportunity of offering workshops to conference goers.&lt;/p&gt;

&lt;p&gt;In collaboration with my amazingly talented coworker, &lt;a href=&quot;http://clome.info/&quot;&gt;Yannick Assogba&lt;/a&gt;, we created a brand new, full day, text analysis and visualization workshop. It was a lot of hard work, but it was all worth it. For one magical day, we overcame internet difficulties and hurdled bad IT policy to provide an experience that impacted deeply my teaching approach and was universally enjoyed by our 30+ attendees.&lt;/p&gt;

&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://bocoup.github.io/text-vis-ovc/&quot;&gt;The workshop content is available here&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://bocoup.github.io/text-vis-ovc/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/textvis_workshop.png&quot; alt=&quot;talk&quot; style=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;We started with A series of Jupyter notebooks that familiarized everyone with the basics of working in a iterative notebook environment. We covered the basics of notebook use and of python - in case folks were unfamiliar.&lt;/p&gt;

&lt;p&gt;Then we dove into text analysis, starting at the sentence level and working our way up to corpora. We looked at how to turn raw text into data, and a number of different metrics useful for understanding and visualizing the text.&lt;/p&gt;

&lt;p&gt;Attendees each copied these notebooks to their machines, and used them as starting points for hands-on exercises throughout the morning.&lt;/p&gt;

&lt;p&gt;After learning ‘enough to be dangerous’ about text analysis methods, we jumped over to the visualization side of things. Yannick and I gave a short intro to D3 and Processing.js before diving into an &lt;a href=&quot;http://bocoup.github.io/text-vis-ovc/24-text-vis-examples/slides.html#1&quot;&gt;exploration of text visualization examples&lt;/a&gt;. The content for this presentation was organized based on visual encoding strategies of the text visualization methods.&lt;/p&gt;

&lt;p&gt;The day ended with a short collaborative hackathon. Small groups were formed based on common interests and we all got to work building our own text visualizations. The results were impressive! Even after a full day of workshopping, the amount of interaction and the progress made by the teams was far more than I expected.&lt;/p&gt;

&lt;p&gt;It was a great day, and I believe from the reviews and the interactions I’ve had since then that folks really enjoyed it.&lt;/p&gt;

&lt;h2 id=&quot;talk&quot;&gt;Talk&lt;/h2&gt;

&lt;p&gt;After the conference, I truncated this workshop into a talk around text analysis and visualization methods and presented it to a visualization class at the &lt;a href=&quot;https://ischool.uw.edu/&quot;&gt;University of Washington iSchool&lt;/a&gt;, hosted by &lt;a href=&quot;http://mfviz.com/&quot;&gt;Mike Freeman&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/textvis-talk/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/textvis-talk.png&quot; alt=&quot;talk&quot; style=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/textvis-talk/#1&quot;&gt;Those slides can be viewed on my site&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/textvis-talk&quot;&gt;The source is available on github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The material is probably more suited to the workshop experience - but at least the visualization examples are interesting!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Creating Bubble Charts in JavaScript</title>
   <link href="http://vallandingham.me/bubble_charts_in_js.html"/>
   <updated>2016-04-11T00:00:00+00:00</updated>
   <id>http://vallandingham.me/bubble_charts_in_js</id>
   <content type="html">&lt;div class=&quot;left&quot;&gt;
&lt;img style=&quot;width:200px;&quot; src=&quot;http://vallandingham.me/images/vis/bubble_chart/thumb.png&quot; alt=&quot;nyt bubble chart&quot; /&gt;
&lt;/div&gt;

&lt;div class=&quot;alert alert-danger&quot;&gt;
  &lt;p&gt;This post is very old and no longer represents the current state of how to use D3 properly. You should check out my updated &lt;a href=&quot;http://vallandingham.me/bubble_charts_with_d3v4.html&quot;&gt;Creating Bubble Charts with D3v4&lt;/a&gt; instead!&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;This tutorial is a &lt;strong&gt;remake&lt;/strong&gt; of my &lt;a href=&quot;http://vallandingham.me/bubble_charts_in_d3.html&quot;&gt;original Gates bubble chart&lt;/a&gt; tutorial. The content, data, and visualization are all the same. The difference is this one is remade &lt;strong&gt;with absolutely no CoffeeScript&lt;/strong&gt;. JavaScript has moved on. I’ve moved on. I hope this tutorial continues to be useful for folks who don’t want to learn or deal with CoffeeScript. I’ve also stripped out jQuery, Bootstrap, and other cruft - allowing us to focus just on the bubbles.&lt;/p&gt;

&lt;p&gt;You can find the &lt;a href=&quot;https://github.com/vlandham/bubble_chart/blob/gh-pages/src/bubble_chart.js&quot;&gt;wonderfully annotated sourcecode on GitHub&lt;/a&gt; and see it does indeed work as expected on the &lt;a href=&quot;http://vallandingham.me/bubble_chart/&quot;&gt;live demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are JS bubble chart implementations from other folks too! If you are interested, check out &lt;a href=&quot;https://gist.github.com/ducky427/5583054&quot;&gt;ducky’s gist translation&lt;/a&gt; and the great &lt;a href=&quot;https://github.com/lflores/gravity-bubbles&quot;&gt;Gravity Bubbles&lt;/a&gt; from Leonardo Flores.&lt;/p&gt;

&lt;p&gt;Below, I’ve updated the original tutorial to match the content of the new implementation. It is a light touch, so if you’ve read it before, you probably won’t miss anything by skipping it now.&lt;/p&gt;

&lt;h2 id=&quot;bubbles&quot;&gt;Bubbles!&lt;/h2&gt;

&lt;p&gt;A now classic New York Times piece featured a &lt;a href=&quot;http://www.nytimes.com/interactive/2012/02/13/us/politics/2013-budget-proposal-graphic.html&quot;&gt;bubble chart of the proposed budget for 2013&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/#!/shancarter&quot;&gt;Shan Carter&lt;/a&gt;. It features some nice organic animations, and smooth transitions that add a lot of visual appeal to the graphic. This was all done using &lt;a href=&quot;d3js.org&quot;&gt;D3.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As &lt;a href=&quot;http://flowingdata.com/2012/02/15/slicing-obamas-2013-budget-proposal-four-ways/&quot;&gt;FlowingData commenters point out&lt;/a&gt; , the use of bubbles may or may not be the best way to display this dataset. Still, the way this visualization draws you in and gets you to interact makes it a nice piece and one that makes you wonder how they did it.&lt;/p&gt;

&lt;p&gt;In this post, we attempt to tease out some of the details of how this graphic works.&lt;/p&gt;

&lt;h2 id=&quot;an-animated-bubble-chart&quot;&gt;An Animated Bubble Chart&lt;/h2&gt;

&lt;p&gt;In order to better understand the budget visualization, I’ve created a similar bubble chart that displays information about what education-based donations the Gates Foundation has made.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/bubble_chart/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/bubble_chart/bubbles.jpg&quot; style=&quot;width:700px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/bubble_chart/&quot;&gt;You can see the full visualization here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the &lt;a href=&quot;https://github.com/vlandham/bubble_chart&quot;&gt;visualization code is on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bubbles are color coded based on grant amount (I know the double encoding using size and color isn’t very helpful - but this data set didn’t have any quick and easy categorical fields besides year).&lt;/p&gt;

&lt;p&gt;The data for this visualization comes from the Washington Post’s DataPost. I’ve added a categorization to the amount for each grant (low, medium, high) and pulled out the start year, but otherwise have left the data alone.&lt;/p&gt;

&lt;p&gt;The rest of this tutorial will walk through the functionality behind this Gates Foundation visualization. This visualization is just a sketch of the functionality in the New York Times graphic - so we can see the relevant parts clearly.&lt;/p&gt;

&lt;h2 id=&quot;d3-force-layout-quick-reference&quot;&gt;D3 Force Layout Quick Reference&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout&quot;&gt;Force Layout&lt;/a&gt; component of D3.js is used to great effect to provide most of the functionality behind the transitions, animations, and collisions in the visualization.&lt;/p&gt;

&lt;p&gt;This layout essentially starts up a little physics simulation in your visualization. Components push and pull at one another, eventually settling into their final positions. Typically, this layout is used for &lt;a href=&quot;http://mbostock.github.com/d3/ex/force.html&quot;&gt;graph visualization&lt;/a&gt; . Here, however, we forgo the use of edges and instead use it just to move around the nodes of a graph.&lt;/p&gt;

&lt;p&gt;This means we don’t really need to know much about graph theory to understand how this graphic works. However, we do need to know the components that make up a force layout, and how to use them.&lt;/p&gt;

&lt;h3 id=&quot;nodes&quot;&gt;nodes&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nodes&lt;/code&gt; is an array of objects that will be used as the nodes (i.e. bubbles in this graph) in the layout. Each node in the array needs a few attributes like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this visualization, we set some of the required attributes manually - so we are in full control of them. The rest we let D3 set and handle internally.&lt;/p&gt;

&lt;h3 id=&quot;gravity&quot;&gt;gravity&lt;/h3&gt;

&lt;p&gt;In D3’s force layout, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; isn’t really a force pushing downwards. Rather, it is a force that can push nodes towards the center of the layout.&lt;/p&gt;

&lt;p&gt;The closer to the center a node is, the less of an impact the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; parameter has on it.&lt;/p&gt;

&lt;p&gt;Setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; to 0 disables it. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; can also be negative. This gives the nodes a push away from the center.&lt;/p&gt;

&lt;h3 id=&quot;friction&quot;&gt;friction&lt;/h3&gt;

&lt;p&gt;As &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout#wiki-friction&quot;&gt;the documentation states&lt;/a&gt;, perhaps a more accurate term for this force attribute would be &lt;strong&gt;velocity decay&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At each step of the physics simulation (or &lt;strong&gt;tick&lt;/strong&gt; as it is called in D3), node movement is scaled by this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;friction&lt;/code&gt;. The recommended range of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;friction&lt;/code&gt; is 0 to 1, with 0 being no movement and 1 being no friction.&lt;/p&gt;

&lt;h3 id=&quot;charge&quot;&gt;charge&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; in a force layout refers to how nodes in the environment push away from one another or attract one another. Kind of like magnets, nodes have a charge that can be positive (attraction force) or negative (repelling force).&lt;/p&gt;

&lt;h3 id=&quot;alpha&quot;&gt;alpha&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; is the layout is described as the simulation’s &lt;em&gt;cooling factor&lt;/em&gt; . I don’t know if that makes sense to me or not.&lt;/p&gt;

&lt;p&gt;What I do know is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; starts at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.1&lt;/code&gt;. After a few hundred ticks, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; is decreased some amount. This continues until &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; is really small (for example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.005&lt;/code&gt;), and then the simulation ends.&lt;/p&gt;

&lt;p&gt;What this means is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; can be used to scale the movement of nodes in the simulation. So at the start, nodes will move relatively quickly. When the simulation is almost over, the nodes will just barely be tweaking their positions.&lt;/p&gt;

&lt;p&gt;This allows you to damper the effects of the forces in your visualization over time. Without taking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; into account, things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; would exert a consistent force on your nodes and pull them all into a clump.&lt;/p&gt;

&lt;h2 id=&quot;how-this-bubble-chart-works&quot;&gt;How This Bubble Chart Works&lt;/h2&gt;

&lt;p&gt;Ok, we didn’t cover everything in the force layout, but we got through all the relevant bits for this visualization. Let me know if I messed anything up.&lt;/p&gt;

&lt;p&gt;Now on to the interesting part!&lt;/p&gt;

&lt;p&gt;There are two features of this bubble chart I want to talk about in more detail: collision detection and transitions.&lt;/p&gt;

&lt;h3 id=&quot;bubble-collision-detection&quot;&gt;Bubble Collision Detection&lt;/h3&gt;

&lt;p&gt;When I first saw the NYT chart, I was intrigued by how they could use different sized bubbles but not have them overlap or sit on top of one another.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; of a force layout specifies node-node repulsions, so it could be used to push nodes away from one another, creating this effect. But how can this work with different sizes if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; is just a single parameter?&lt;/p&gt;

&lt;p&gt;The trick is that along with a static value, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; can also take a &lt;strong&gt;function&lt;/strong&gt;, which is evaluated for each node in the layout, passing in that node’s data. Here is the charge function for this visualization:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Charge Function&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Creation of d3 force layout&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;layout&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;lt;- Using the charge function in the force layout&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gravity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;friction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pretty simple right? The &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout#wiki-charge&quot;&gt;charge documentation&lt;/a&gt; provides us with the understanding that this parameter can be a constant, but can also be a function. Sweet!&lt;/p&gt;

&lt;p&gt;The charge function takes in an input parameter, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt;, which is the data associated with a node. The method returns the negative of the radius squared of the node, divided by 8.&lt;/p&gt;

&lt;p&gt;The negative is for pushing away nodes. Dividing by 8 scales the repulsion to an appropriate scale for the size of the visualization.&lt;/p&gt;

&lt;p&gt;A couple of other factors are at work that also contribute to the nice looking placement of these nodes.&lt;/p&gt;

&lt;p&gt;We set its gravity to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-0.01&lt;/code&gt; and its friction value to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.9&lt;/code&gt; (which is the default). This says that nodes should be ever so slightly pushed away from the center of the layout, but there should be just enough friction to prevent them from scattering away.&lt;/p&gt;

&lt;p&gt;So, nodes push away from one another based on their diameter - providing nice looking collision detection. The gravity and friction settings work along with this pushing to ensure nodes are sucked together or pushed away too far. It is a nice combo.&lt;/p&gt;

&lt;p&gt;Here is the code that is used to configure and startup the force directed simulation:&lt;/p&gt;

&lt;h3 id=&quot;animation-and-transitions&quot;&gt;Animation and Transitions&lt;/h3&gt;

&lt;p&gt;The capstone of the original graphic is the nice transitions between views of the data, where bubbles are pulled apart into separate groups. I’ve replicated this somewhat by having a view that divides up Gate’s grants by year.&lt;/p&gt;

&lt;p&gt;How is this done? Well, let’s start with the “single group” view first. The position of each node is determined by the function called for each &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout#tick&quot;&gt;tick&lt;/a&gt; of the simulation. This function gets passed in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; for this iteration of the simulation.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Group circles into a single blob.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;groupBubbles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;bubbles&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;moveToCenter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;cx&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;cy&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moveToCenter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;damper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;damper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bubbles&lt;/code&gt; variable holds the svg circles that represent each node. So for every tick event, for each circle in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bubbles&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moveToCenter&lt;/code&gt; function is called, with the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; value passed in. Then, The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cx&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cy&lt;/code&gt; of each circle is set based on it’s data’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; values.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moveToCenter&lt;/code&gt; is charged with modifying the circle’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; values based on the current alpha and the circle’s position in the previous iteration of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To reiterate, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moveToCenter&lt;/code&gt; returns a function that is called for each circle, passing in its data. Inside this function, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; values of the data are pushed towards the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;center&lt;/code&gt; point (which is set to the center of the visualization). This push towards the center is dampened by a constant, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;damper&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; dampening allows the push towards the center to be reduced over the course of the simulation, giving other forces like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; the opportunity to push back.&lt;/p&gt;

&lt;p&gt;The variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;damper&lt;/code&gt; is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.102&lt;/code&gt;. This probably took some time to find a good value for, and I just copied that from the original. Thanks NYT!&lt;/p&gt;

&lt;p&gt;Ok, we’ve now seen how the nodes in the simulation move towards one point, what about multiple locations? The code is just about the same:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Split circles based on year.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;splitBubbles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;bubbles&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;moveToYears&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;cx&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;cy&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moveToYears&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yearCenters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;damper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;damper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The switch to displaying by year is done by restarting the force simulation using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;force.start()&lt;/code&gt;. This time the &lt;em&gt;tick&lt;/em&gt; function calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moveToYears&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moveToYears&lt;/code&gt; is almost the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moveToCenter&lt;/code&gt;. The difference being that first the correct year point is extracted from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yearCenters&lt;/code&gt;. Here’s what that object looks like:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yearCenters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;2008&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;2009&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;2010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see each year has its own centroid position mapped to it.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moveToYears&lt;/code&gt; also multiplied by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.1&lt;/code&gt; to speed up the transition a bit. Again, these numbers take some tweaking and experimentation to find. The code could be simplified a bit if you wanted to pass in the unique multipliers for each transition.&lt;/p&gt;

&lt;p&gt;So we’ve seen a general pattern for both of these views: setup the &lt;em&gt;tick&lt;/em&gt; method to iterate over all the nodes to change their locations. This was done using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;each&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;In fact you can chain multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;each&lt;/code&gt; methods that call different move functions. This would allow you to push and pull your nodes in various ways depending on their features. The NYT graphic uses at least two move functions for these transitions. One to move nodes towards a group point (like above), and one to move nodes towards their respective color band.&lt;/p&gt;

&lt;p&gt;Hope this tutorial shows you some interesting ways to use D3’s force layout. I thought the original NYT visualization was interesting enough to find out more about it. Again, the full visualization code &lt;a href=&quot;https://github.com/vlandham/bubble_chart/blob/gh-pages/src/bubble_chart.js&quot;&gt;can be found on github&lt;/a&gt;. It is about 400 lines long, but includes copious comments for your perusing pleasure.&lt;/p&gt;

&lt;p&gt;Force layouts: they are not just for force-directed graphs anymore!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>What is Data Visualization?</title>
   <link href="http://vallandingham.me/what_is_data_vis.html"/>
   <updated>2016-03-01T00:00:00+00:00</updated>
   <id>http://vallandingham.me/what_is_data_vis</id>
   <content type="html">&lt;p&gt;In 2016 I got the opportunity to speak in front of a small group of highschoolers who were part of the &lt;a href=&quot;https://girlswhocode.com/&quot;&gt;Girls Who Code&lt;/a&gt; group at Ingraham High School. Though we were interrupted by a power outage, I did my best to talk through my (always expanding) ideas about the point and power of data visualization.&lt;/p&gt;

&lt;p&gt;Thanks very much to &lt;a href=&quot;http://www.erinshellman.com/&quot;&gt;Erin Shellman&lt;/a&gt; for the invite!&lt;/p&gt;

&lt;h2 id=&quot;slides&quot;&gt;Slides&lt;/h2&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;bcfb8ca9b8164bb69fc2c315090b93e5&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;p&gt;Here are a bunch of links of things referenced in my talk. Thanks to all those who make great visualizations that I can show off!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://classes.dma.ucla.edu/Spring13/161/projects/students/david/project-4/html/&quot;&gt;Data visualization intersection&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://napitupulu-jon.appspot.com/posts/design-principles-ud507.html&quot;&gt;Visual encoding accuracy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://cvcl.mit.edu/papers/Borkin_etal_MemorableVisualization_TVCG2013.pdf&quot;&gt;Visualization memorability paper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://eagereyes.org/papers/the-connected-scatterplot-for-presenting-paired-time-series&quot;&gt;Connected scatter plot paper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://alignedleft.com/talks&quot;&gt;Scott Murray talks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://hint.fm/wind/&quot;&gt;Wind map&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.nytimes.com/interactive/2014/08/13/upshot/where-people-in-each-state-were-born.html&quot;&gt;NYT - where we came from&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://selfiecity.net/&quot;&gt;Selfiecity&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.nytimes.com/interactive/2015/05/17/us/elections/2016-presidential-campaigns-staff-connections-clinton-bush-cruz-paul-rubio-walker.html&quot;&gt;NYT - connecting the dots&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.nytimes.com/interactive/2014/06/20/sports/worldcup/how-world-cup-players-are-connected.html&quot;&gt;Clubs that connect the world&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://projects.propublica.org/graphics/workers-compensation-benefits-by-limb&quot;&gt;How much is a limb worth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.martingrandjean.ch/network-visualization-shakespeare/&quot;&gt;Visualizing Shakespeare&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.nytimes.com/interactive/2015/12/10/us/gun-sales-terrorism-obama-restrictions.html&quot;&gt;NYT - gun sales soar&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.bloomberg.com/graphics/2015-pace-of-social-change/&quot;&gt;Bloomberg - tracking pace of social change&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.nytimes.com/interactive/2014/03/17/world/asia/search-for-flight-370.html&quot;&gt;NYT - jet debris&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://qz.com/582720/americas-most-prolific-wall-punchers-charted/&quot;&gt;Americas prolific Wallpunchers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.dear-data.com/&quot;&gt;Dear Data&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://flowingdata.com/2009/11/26/fox-news-makes-the-best-pie-chart-ever/&quot;&gt;Fox best pie chart ever&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://flowingdata.com/2012/08/06/fox-news-continues-charting-excellence/&quot;&gt;Fox bar chart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bost.ocks.org/mike/algorithms/&quot;&gt;Visualizing algorithms&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.r2d3.us/visual-intro-to-machine-learning-part-1/&quot;&gt;Visualizing machine learning&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.bloomberg.com/graphics/2014-hottest-year-on-record/&quot;&gt;Bloomberg hottest year&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://guns.periscopic.com/?year=2013&quot;&gt;Gun deaths&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://raw.densitydesign.org/&quot;&gt;RAW by Design Density&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.tableau.com/&quot;&gt;Tableau&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://idl.cs.washington.edu/projects/lyra/&quot;&gt;Lyra&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.databasic.io/en/&quot;&gt;DataBasic&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://matplotlib.org/&quot;&gt;matplotlib&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://stanford.edu/~mwaskom/software/seaborn/&quot;&gt;seaboard&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://ggplot2.org/&quot;&gt;ggplot2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://p5js.org/&quot;&gt;p5.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://d3js.org/&quot;&gt;d3.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Quartz/bad-data-guide&quot;&gt;Quartz guide to bad data&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://learnjsdata.com/&quot;&gt;Learn JS data&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.storytellingwithdata.com/blog/2015/06/audience-audience-audience&quot;&gt;Storytelling with data&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.labnol.org/software/find-right-chart-type-for-your-data/6523/&quot;&gt;The right chart for your data&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=d9ryPC8bxqE&quot;&gt;Everything is a remix video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/remix/&quot;&gt;Everything is a remix visual&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://flowingdata.com/&quot;&gt;Flowing Data&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.pinterest.com/arnicas/&quot;&gt;Lynn Cherny pintrests&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://stephanieevergreen.com/females-in-dataviz/&quot;&gt;Women in Data Vis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://chartsnthings.tumblr.com/post/35615197681/sketches-from-the-swinging-swing-states&quot;&gt;NYT chart iterations&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Trends in Data Visualization</title>
   <link href="http://vallandingham.me/trends_in_data_vis.html"/>
   <updated>2016-02-22T00:00:00+00:00</updated>
   <id>http://vallandingham.me/trends_in_data_vis</id>
   <content type="html">&lt;p&gt;In 2016 I was honored to speak at a visualization symposium held at Stanford University. The title of the talk was &lt;em&gt;Exciting Trends in Data Visualization&lt;/em&gt; where I attempted to map things we were working on at Bocoup to larger trends seen in the industry, and then project where these trends might lead in the future.&lt;/p&gt;

&lt;h2 id=&quot;slides&quot;&gt;Slides&lt;/h2&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;46c8d4f983d5476cbede0b5c4e800e27&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

</content>
 </entry>
 
 <entry>
   <title>Stereotropes</title>
   <link href="http://vallandingham.me/stereotropes.html"/>
   <updated>2015-08-29T00:00:00+00:00</updated>
   <id>http://vallandingham.me/stereotropes</id>
   <content type="html">&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://stereotropes.bocoup.com&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/stereotropes/logo-raster-medium.png&quot; alt=&quot;logo&quot; style=&quot;width:700px;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;A project I was fortunate to work on, in collaboration with the other members of the &lt;a href=&quot;https://bocoup.com/datavis/&quot;&gt;Bocoup Data Vis Team&lt;/a&gt;, Stereotropes looks at the descriptions made for &lt;a href=&quot;http://tvtropes.org/pmwiki/pmwiki.php/Main/Trope&quot;&gt;TV and film tropes&lt;/a&gt; through the lens of gender.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://stereotropes.bocoup.com&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/stereotropes/trope-page-adjectives.png&quot; alt=&quot;trope words&quot; style=&quot;width:700px;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Also check out our detailed &lt;a href=&quot;https://bocoup.com/weblog/stereotropes-design/&quot;&gt;Stereotropes Design Post&lt;/a&gt; for more on how and why it was made.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://stereotropes.bocoup.com&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/stereotropes/gender-visualization.png&quot; alt=&quot;trope adjectives&quot; style=&quot;width:700px;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>A Git Workflow Walkthrough Series</title>
   <link href="http://vallandingham.me/git-workflow.html"/>
   <updated>2015-08-28T00:00:00+00:00</updated>
   <id>http://vallandingham.me/git-workflow</id>
   <content type="html">&lt;p&gt;I wrote a bunch of words about how you can use Git in a simplistic, sane manner when collaborating with others on code. Check out the whole series!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://bocoup.com/weblog/git-workflow-walkthrough-feature-branches&quot;&gt;Part 1: Feature Branches&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bocoup.com/weblog/git-workflow-walkthrough-reviewing-pull-requests&quot;&gt;Part 2: Reviewing Pull Requests&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bocoup.com/weblog/git-workflow-walkthrough-reviewing-pull-requests-local&quot;&gt;Part 3: Reviewing Pull Requests Locally&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bocoup.com/weblog/git-workflow-walkthrough-merging-pull-requests&quot;&gt;Part 4: Merging Pull Requests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;https://vallandingham.me/images/git/git_diagrams.png&quot; alt=&quot;git diagram&quot; style=&quot;width:700px;&quot; /&gt;
&lt;/div&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/git/git_happy.png&quot; alt=&quot;git happy&quot; style=&quot;width:700px;&quot; /&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Implementing a Vintage Bump Chart</title>
   <link href="http://vallandingham.me/vintage_bump_chart.html"/>
   <updated>2015-04-29T00:00:00+00:00</updated>
   <id>http://vallandingham.me/vintage_bump_chart</id>
   <content type="html">&lt;p&gt;A quick shoutout for another vintage visualization I implemented in code:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/census_bump/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/census_bump.png&quot; alt=&quot;census bump&quot; style=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The entire thing was implementing using JavaScript and D3.js. It’s about 700 lines of code with 200 lines of data and configuration.&lt;/p&gt;

&lt;p&gt;Learn more about this classic visualization, and the code that was used to build it, in my &lt;a href=&quot;http://bocoup.com/weblog/vintage-visualization-restoration-bump-chart/&quot;&gt;Bocoup blog post&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>So You Think You Can Scroll Talk</title>
   <link href="http://vallandingham.me/think_you_can_scroll.html"/>
   <updated>2015-04-06T00:00:00+00:00</updated>
   <id>http://vallandingham.me/think_you_can_scroll</id>
   <content type="html">&lt;p&gt;This April, I had the privilege of coming back to &lt;a href=&quot;http://openvisconf.com/&quot;&gt;OpenVis Conf&lt;/a&gt; for a second time as a presenter. This is doublely special for me as I recently became an &lt;a href=&quot;http://bocoup.com/weblog/author/jim-vallandingham/&quot;&gt;Open Web Engineer&lt;/a&gt; at Bocoup - the organizers of this great conference (though it was after they had already accepted my talk).&lt;/p&gt;

&lt;h2 id=&quot;video&quot;&gt;Video&lt;/h2&gt;

&lt;p&gt;Check out the video &lt;a href=&quot;https://youtu.be/fYQGgaE_b4I&quot;&gt;on youtube&lt;/a&gt;:&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/fYQGgaE_b4I&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;or on the &lt;a href=&quot;https://openvisconf.com/2015/&quot;&gt;OpenVis Conf Site&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;slides&quot;&gt;Slides&lt;/h2&gt;

&lt;p&gt;The slides for the talk &lt;a href=&quot;http://vallandingham.me/scroll_talk/&quot;&gt;are online&lt;/a&gt; - but because of all the videos used, this can talk quite a while to load remotely.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/scroll_talk/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/scroll/talk.png&quot; alt=&quot;talk&quot; style=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Alternatively, you can &lt;a href=&quot;https://github.com/vlandham/scroll_talk&quot;&gt;clone the talk repo&lt;/a&gt;, and get all the content on your own machine!&lt;/p&gt;

&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;

&lt;p&gt;Perhaps, more usefully, I’ve collected the examples used in the talk, and some that didn’t make it in but are still awesome, as an &lt;a href=&quot;http://vallandingham.me/scroll_talk/examples/&quot;&gt;examples page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Update: I’ve updated this code to use D3v4. Please Enjoy!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://vallandingham.me/scroll_demo&quot;&gt;demo application&lt;/a&gt; and &lt;a href=&quot;http://vallandingham.me/scroller.html&quot;&gt;associated tutorial&lt;/a&gt; can also be found on my site.&lt;/p&gt;

&lt;p&gt;And of course, make your own scrolling art with &lt;a href=&quot;http://vallandingham.me/embroiden/&quot;&gt;embroiden&lt;/a&gt; - my fun little bookmarklet.&lt;/p&gt;

&lt;p&gt;Hope these resources are useful to you!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>So You Want to Build A Scroller</title>
   <link href="http://vallandingham.me/scroller.html"/>
   <updated>2015-04-06T00:00:00+00:00</updated>
   <id>http://vallandingham.me/scroller</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Update: This code has been updated to use D3v4. &lt;a href=&quot;https://github.com/vlandham/scroll_demo&quot;&gt;Please Enjoy!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A critical component of successful interactive visualizations is orienting the users to what they are looking at. In a multi-faceted data story, it can be useful to explicitly move a user through the different views of the data.&lt;/p&gt;

&lt;p&gt;Previously, we’ve &lt;a href=&quot;http://vallandingham.me/stepper_steps.html&quot;&gt;looked at steppers&lt;/a&gt; as a way to implement this guidance system.&lt;/p&gt;

&lt;p&gt;Here, I’d like to look at how the simple act of scrolling can be harnessed to direct a user through a complex visualization combined intuitively with a guiding narration.&lt;/p&gt;

&lt;h2 id=&quot;data-scrolling&quot;&gt;Data Scrolling&lt;/h2&gt;

&lt;p&gt;There have been many interesting uses of scrolling in data visualization and interactive storytelling (which I will talk a lot more about in my &lt;a href=&quot;http://openvisconf.com/&quot;&gt;upcoming presentation&lt;/a&gt;). In fact, Mike Bostock recently published a wonderful set of best practices on &lt;a href=&quot;http://bost.ocks.org/mike/scroll/&quot;&gt;How To Scroll&lt;/a&gt; to maximize the use of this tool.&lt;/p&gt;

&lt;p&gt;For this tutorial we will look at some of the implementation details for scrolling in data visualizations. I’ll focus on a common pattern that moves the user through discrete sections of content, while modifying the visualizations accompanying the text to create a unified data driven story.&lt;/p&gt;

&lt;p&gt;This technique has been used in many places including the New York Times with &lt;a href=&quot;https://twitter.com/driven_by_data&quot;&gt;Gregor Aisch’s&lt;/a&gt; &lt;a href=&quot;http://www.nytimes.com/interactive/2014/06/20/sports/worldcup/how-world-cup-players-are-connected.html&quot;&gt;The Clubs That Connect The World Cup&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/scroll/nyt_world_cup.jpg&quot; alt=&quot;world cup&quot; style=&quot;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;And at Bloomberg with &lt;a href=&quot;https://twitter.com/adamrpearce&quot;&gt;Adam Pearce’s&lt;/a&gt; &lt;a href=&quot;http://www.bloomberg.com/graphics/2015-auto-sales/&quot;&gt;American Truck Addiction&lt;/a&gt; and &lt;a href=&quot;http://www.bloomberg.com/graphics/2015-measles-outbreaks/&quot;&gt;Measles Outbreak&lt;/a&gt; visualizations.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/scroll/bloomberg_measles.jpg&quot; alt=&quot;measles&quot; style=&quot;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;You can find a lot more examples &lt;a href=&quot;http://vallandingham.me/think_you_can_scroll.html&quot;&gt;in my talk&lt;/a&gt; and associated &lt;a href=&quot;http://vallandingham.me/scroll_talk/examples/&quot;&gt;resources page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve &lt;a href=&quot;http://vallandingham.me/scroll_demo/&quot;&gt;created a demo&lt;/a&gt; that attempts to explain a lot of how to make these types of interactives, but covering a much less serious topic then these actual news reporters. As this tutorial will contribute to my upcoming &lt;a href=&quot;http://openvisconf.com/&quot;&gt;OpenVis Conf&lt;/a&gt; talk in April, I decided to take a look at all the mistakes I made in my &lt;a href=&quot;http://vallandingham.me/abusing_the_force.html&quot;&gt;2013 talk&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/scroll_demo/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/scroll/filler_words.jpg&quot; alt=&quot;measles&quot; style=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Specifically, it is a story around the frequency of filler words - “ah”, “um”, and “uh” - said during the talk. &lt;a href=&quot;http://vallandingham.me/scroll_demo/&quot;&gt;Take a look&lt;/a&gt;, and then, lets get started with looking behind the curtain at how to build this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As usual, the &lt;a href=&quot;https://github.com/vlandham/scroll_demo&quot;&gt;code is available on github&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;html-and-css-structure&quot;&gt;HTML and CSS Structure&lt;/h2&gt;

&lt;p&gt;Like all great web-based masterpieces, we must start with the basic, but critical task of getting our HTML framework for this visualization in place.&lt;/p&gt;

&lt;p&gt;Let’s create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#sections&lt;/code&gt; div that will be used to hold the text portion of our interactive. Each section of text will live in a separate &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section&quot;&gt;section element&lt;/a&gt;. The visualization component go in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#vis&lt;/code&gt; which is put after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sections&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'graphic'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'sections'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;step&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;OpenVis Conf 2013&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        I did what no presenter should ever do: I watched my own talk...
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;step&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- another section --&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'vis'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now the CSS needs to get the scrolling text next to the visual display. Here is the gist of it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nf&quot;&gt;#sections&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;relative&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inline-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;250px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.step&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;200px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;#vis&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inline-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fixed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;60px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;600px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;600px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#ddd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;a href=&quot;http://learnlayout.com/inline-block.html&quot;&gt;inline-block&lt;/a&gt; display type allows us to position the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#sections&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#vis&lt;/code&gt; elements side-by-side while still providing a width and height. We also make the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#vis&lt;/code&gt; position &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/position&quot;&gt;fixed&lt;/a&gt;, which makes it stay in the same place, even as we scroll. The margin on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.step&lt;/code&gt; elements ensures we have some space to scroll in for each section.&lt;/p&gt;

&lt;p&gt;I’ve added a height, width, and background to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#vis&lt;/code&gt; - just so we can see where it will be. Even without any JavaScript, we can start to see the structure. Pretty cool!&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/scroll/structure.png&quot; alt=&quot;basic structure&quot; style=&quot;&quot; /&gt;
&lt;/div&gt;

&lt;h2 id=&quot;a-reusable-scroller&quot;&gt;A Reusable Scroller&lt;/h2&gt;

&lt;p&gt;Now, let’s turn to the details of figuring out where the page will be scrolled to. With a bit of work, we can encapsulate most of this code into a stand-alone function that can be reused in other projects. Most of this is based on the Bloomberg Visual’s excellent work - so thanks again to &lt;a href=&quot;https://twitter.com/adamrpearce&quot;&gt;Adam Pearce&lt;/a&gt; for all his help!&lt;/p&gt;

&lt;p&gt;The code for this scroll detection capability is in &lt;a href=&quot;https://github.com/vlandham/scroll_demo/blob/gh-pages/js/scroller.js&quot;&gt;scroller.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The basic idea of what the code does is fairly straightforward:&lt;/p&gt;

&lt;p&gt;Given a set of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sections&lt;/code&gt;, figure out where these elements are located vertically down the page. When the page is scrolled, figure out which of these elements is currently front-and-center in the browser’s &lt;a href=&quot;http://www.quirksmode.org/mobile/viewports.html&quot;&gt;viewport&lt;/a&gt;. If this element is different than the last ‘active’ element, then switch to this new section and tell the visualization.&lt;/p&gt;

&lt;p&gt;Easy right? Well, plenty of details to get right.&lt;/p&gt;

&lt;p&gt;First, our main function takes a D3 selection that indicates the scrollable elements. In the demo, we call it by passing in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.selectAll('.step')&lt;/code&gt;, but it is generic enough to accept any selection.&lt;/p&gt;

&lt;p&gt;We want to get the vertical coordinates of where these sections start on the page so that we can find the nearest one as we scroll. There are probably a dozen ways to do this, but here is one:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;sectionPositions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;startPos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;sections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getBoundingClientRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;startPos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;sectionPositions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;startPos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sections&lt;/code&gt; is again, the text steps that our users will scroll through. We use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect&quot;&gt;getBoundingClientRect&lt;/a&gt; to get the position of each element. The trick is that this position is &lt;em&gt;relative to the viewport&lt;/em&gt;. If the user has scrolled partway down the page and then reloads, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;top&lt;/code&gt; value for all the sections they have already passed will be negative.&lt;/p&gt;

&lt;p&gt;To accommodate this, we make all section positions relative to the first section. So the section at index &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; has a section position of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; and all other sections follow from that.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sectionPositions&lt;/code&gt; will be accessible to the code that figures out which section the user has scrolled to, which we will look at next.&lt;/p&gt;

&lt;h2 id=&quot;detecting-the-active-section&quot;&gt;Detecting the Active Section&lt;/h2&gt;

&lt;p&gt;The next step of our little scrolling algorithm is to detect which section the user is scrolled to. This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; function will be called initially on load, and then whenever the window is scrolled by binding to the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Events/scroll&quot;&gt;scroll event&lt;/a&gt; like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;scroll.scroller&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.scroller&lt;/code&gt; suffix is how &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Selections#on&quot;&gt;event namespaces&lt;/a&gt; are created in D3, so we don’t accidentally clobber event binding in other parts of our code.&lt;/p&gt;

&lt;p&gt;Here is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; function. We will walk through it in detail below:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pageYOffset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bisect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sectionPositions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;currentIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;currentIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The first step is to find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pos&lt;/code&gt; - the users current position on the page. Here, we use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY&quot;&gt;pageYOffset&lt;/a&gt; which is an alias to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrollY&lt;/code&gt;. This gives the vertical position on the page that the browser is currently scrolled to. We offset it just a bit with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;- 10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, we turn to the power of &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Arrays#d3_bisect&quot;&gt;d3.bisect&lt;/a&gt; to pull out the index of the current section that has been scrolled to. I discussed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.bisect&lt;/code&gt; in my &lt;a href=&quot;http://flowingdata.com/2014/10/15/linked-small-multiples/&quot;&gt;linked small multiples&lt;/a&gt; tutorial, but it merits another look.&lt;/p&gt;

&lt;p&gt;Given a sorted array of data and a new data element, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.bisect&lt;/code&gt; will find the right spot for inserting that new element in the array to maintain its sorted-ness. It &lt;em&gt;bisects&lt;/em&gt; the current array in the right spot to insert the new element. Its does this by performing a &lt;a href=&quot;http://en.wikipedia.org/wiki/Binary_search_algorithm&quot;&gt;binary search&lt;/a&gt; on the array to find the insertion position.&lt;/p&gt;

&lt;p&gt;The default bisect provides the index to the right of the insertion point. Using it here, we are asking for the index of the section after the section that was just scrolled passed.&lt;/p&gt;

&lt;p&gt;It took me awhile to wrap my head around this, so perhaps an example will help. Here is an array of sorted values:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;nums&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.bisect&lt;/code&gt; returns the index to the right of a match:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bisect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And also:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bisect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bisect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is why we subtract 10 from the current position, so we start at index 0:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bisect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The index can be one past the length of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sectionPositions&lt;/code&gt; array, so we make sure to keep it within bounds using:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This index serves as the key to the visualization component of our site to know what it should be displaying. If the currently scrolled to section index doesn’t match the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentIndex&lt;/code&gt;, indicate the new index using &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Selections#d3_event&quot;&gt;d3.event&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;event-dispatching-and-binding&quot;&gt;Event Dispatching and Binding&lt;/h2&gt;

&lt;p&gt;Events are a great way to keep your code de-coupled and free of explicit dependencies, so let’s deviate a bit from the code flow to talk about them a bit more.&lt;/p&gt;

&lt;p&gt;Like a &lt;a href=&quot;http://api.jquery.com/category/events/&quot;&gt;lot&lt;/a&gt; of &lt;a href=&quot;http://backbonejs.org/#Events&quot;&gt;frameworks&lt;/a&gt;, D3 has its event generation and dispatching capabilities. Though, this works a bit differently than other eventing libraries I’ve used.&lt;/p&gt;

&lt;p&gt;First, you need to create a dispatcher, using &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Internals#d3_dispatch&quot;&gt;d3.dispatch&lt;/a&gt;. On creation, you indicate the event types the dispatcher will be able to dispatch. For our scroller, our dispatcher code looks like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This means we can dispatch the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; event and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;progress&lt;/code&gt; event, which we will get to in a bit.&lt;/p&gt;

&lt;p&gt;Now these event types are methods on our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dispatch&lt;/code&gt; object. So, as we saw in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; function, we can send a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; event like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sectionIndex&lt;/code&gt; is passed as an input parameter to the handler of this event type.&lt;/p&gt;

&lt;p&gt;In our visualization code, we will handle this event by adding a listener to the dispatcher’s event using &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Internals#dispatch_on&quot;&gt;dispatch.on&lt;/a&gt;. The code to listen to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; events will look something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;scroll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;One hiccup is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.on&lt;/code&gt; is a method of the dispatcher, but our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dispatch&lt;/code&gt; object is internal to our scroller code. We don’t really want to expose this internal detail to users of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scroller&lt;/code&gt;. A cool trick to solve this issue is to use &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Internals#rebind&quot;&gt;d3.rebind&lt;/a&gt; to copy our dispatch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.on&lt;/code&gt; method to our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scroller&lt;/code&gt; instance:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rebind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scroll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Check out the details &lt;a href=&quot;https://github.com/vlandham/scroll_demo/blob/gh-pages/js/scroller.js#L125&quot;&gt;in the example&lt;/a&gt; but this gives the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scroll&lt;/code&gt; object the power of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.on&lt;/code&gt;, which acts like a pass through - sending it on to the dispatcher to handle things.&lt;/p&gt;

&lt;h2 id=&quot;progressing-through-a-section&quot;&gt;Progressing Through a Section&lt;/h2&gt;

&lt;p&gt;So the code we have now will let us get notified when the user scrolls to a different section of text. This is great. It means we will be able to trigger visualization changes on these section changes.&lt;/p&gt;

&lt;p&gt;But there are times when you might want to hook up animations within a section as the user scrolls. &lt;a href=&quot;https://twitter.com/tonyhschu&quot;&gt;Tony Chu&lt;/a&gt; provides a great example of this kind of interaction with his &lt;a href=&quot;http://letsfreecongress.org/&quot;&gt;Let’s Free Congress&lt;/a&gt; project. Scrolling within sections modifies the visuals in interesting and fun ways.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/scroll/freecongress.jpg&quot; alt=&quot;basic structure&quot; style=&quot;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.tonyhschu.ca/post/49488608263/technical-write-up-scroll-linked-animations&quot;&gt;Inspired by this functionality&lt;/a&gt;, we can modify our code slightly to also allow for these kinds of within-section interactions.&lt;/p&gt;

&lt;p&gt;Back in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt; function, I’ve added this little snippet to the end of the function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prevIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prevTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sectionPositions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prevIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;progress&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prevTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sectionPositions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sectionIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prevTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;currentIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here we just find the previous section’s top value, and compute how far into the current section we are. The number will range from 0.0 to 1.0, and we send that value along with the current index in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;progress&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;With this little change, we can now get updates as to where the user has scrolled within a section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt; : there is some inconsistencies with how far different scrolling mechanisms move the page. If you want to get real specific, you might checkout a tool like &lt;a href=&quot;https://github.com/jquery/jquery-mousewheel&quot;&gt;jQuery Mouse Wheel&lt;/a&gt; that attempts to normalize this scrolling across devices.&lt;/p&gt;

&lt;p&gt;Now, let’s &lt;strong&gt;finally&lt;/strong&gt; use our scroll events to make some visualizations move!&lt;/p&gt;

&lt;h2 id=&quot;visual-transition-tips&quot;&gt;Visual Transition Tips&lt;/h2&gt;

&lt;p&gt;With the scrolling events in place, most of the visualization work becomes standard D3 functionality. The &lt;a href=&quot;https://github.com/vlandham/scroll_demo/blob/gh-pages/js/sections.js&quot;&gt;code for this part of the demo&lt;/a&gt; should be well commented. Its long, but not all that exciting, from a cool-new-code perspective.&lt;/p&gt;

&lt;p&gt;But there are still a few details worth talking through. Here are the steps, and perhaps a set of suggested best practices that I’ve compiled while examining example code and building up this visualization.&lt;/p&gt;

&lt;h3 id=&quot;setup-all-visual-elements-on-start&quot;&gt;Setup All Visual Elements on Start&lt;/h3&gt;

&lt;p&gt;Sometimes I enjoy getting the enter, exit, and update functions of D3 working together in the same place. But with so many visual elements, I found it easier to just append all of them at one time during the initialization of the visualization.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setupVis&lt;/code&gt; is the function that performs this initialization. The elements for each section are added, and then hidden. Here is an example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// square grid&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;squares&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.square&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;wordData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;squares&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;squareSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;squareSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;#fff&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;classed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;classed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;fill-square&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here, I’m setting up all my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.square&lt;/code&gt;’s with width, height, and position. Then hiding them by setting their opacity to 0.&lt;/p&gt;

&lt;p&gt;If you visualization was even more complicated, you could have a separate function for setting up each sections elements to keep things more module.&lt;/p&gt;

&lt;h3 id=&quot;each-section-executes-a-function&quot;&gt;Each Section Executes a Function&lt;/h3&gt;

&lt;p&gt;When the user scrolls to a new section, we want to show the new visuals for this section. Each of these visual changes is encapsulated in its own function&lt;/p&gt;

&lt;p&gt;As we will be passed in the index of the current section, we can organize our section functions in an array:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showFillerTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showGrid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;highlightGrid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showBar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showHistPart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showHistAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showCough&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showHistAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then bind to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; event to activate the right function&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;scroll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate&lt;/code&gt; function will call the current section’s function using this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activateFunctions&lt;/code&gt; array:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It does some other work as well, so we will look at it in more detail in a minute.&lt;/p&gt;

&lt;p&gt;Our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;progress&lt;/code&gt; event is processed in a similar fashion.&lt;/p&gt;

&lt;h3 id=&quot;section-functions-show-their-section-and-hide-their-neighbor-sections&quot;&gt;Section Functions Show Their Section and Hide Their Neighbor Sections&lt;/h3&gt;

&lt;p&gt;Technically, each section function could comprehensively deal with every single element of the visualization. With a few sections, this might not be terrible, but the complexity would quickly spiral out of control with more sections added.&lt;/p&gt;

&lt;p&gt;Fortunately, this is not necessary. If you think about it, a section function really only needs to worry about showing the elements used for that section, and hiding the elements that were used in the section before it. But since a user can scroll both ways, we need to ensure the section that comes &lt;em&gt;after&lt;/em&gt; is dealt with as well.&lt;/p&gt;

&lt;p&gt;A simple example from the code is the first title section function. As nothing comes before it, it only needs to be concerned with showing its text elements and hiding elements of the title that comes after it in the second section.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.count-title&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.openvis-title&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;track-last-section-seen-to-deal-with-fast-scrolling&quot;&gt;Track Last Section Seen to Deal with Fast Scrolling&lt;/h3&gt;

&lt;p&gt;Unfortunately, what I’ve just told you about these simplistic section functions was a lie. A lie I wanted to believe myself. It’s true that under normal scrolling conditions, dealing with neighboring sections is all that needs to be done. With speedy scrolling, there is a chance that our scrolling event won’t fire for sections that are passed through too quickly.&lt;/p&gt;

&lt;p&gt;So there is a chance that these intermediate step functions won’t get executed, leaving your visualization in an invalid state.&lt;/p&gt;

&lt;p&gt;We could deal with this issue in the scroller code, but that seems a bit too brittle and specific to this particular use case. Instead, we can perform a little extra work in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate&lt;/code&gt; function to ensure that all functions that should be are executed in order.&lt;/p&gt;

&lt;p&gt;Here is the full code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;chart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;activate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activeIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sign&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;activeIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lastIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrolledSections&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lastIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;activeIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;scrolledSections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;activateFunctions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;lastIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;activeIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So, we track the last &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeIndex&lt;/code&gt; we have seen. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate&lt;/code&gt; is called, we create an array of indexes using &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Arrays#d3_range&quot;&gt;d3.range&lt;/a&gt;. With normal scrolling behavior, this range will just go from the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeIndex&lt;/code&gt; to the new one. But with faster scrolling, the array will contain all the in-between steps, so we can call them in the right sequence.&lt;/p&gt;

&lt;h3 id=&quot;make-everything-a-transition&quot;&gt;Make Everything a Transition&lt;/h3&gt;

&lt;p&gt;Inside these section functions we are moving around elements and modifying lots of their attributes. The important thing to remember is to make all these modifications &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Transitions&quot;&gt;d3.transitions&lt;/a&gt;, even if you want them to happen immediately. This way, if the user is scrolling from one section to another during a transition, the transition will be interrupted and the transition for the current section will come into effect.&lt;/p&gt;

&lt;p&gt;Here are some examples to help clarify the issue. Each example shows a circle being animated back and forth across the screen using transitions.&lt;/p&gt;

&lt;p&gt;First we have the general case. The left-to-right transition finishes, and then the right-to-left one begins. No problems here. Everything looks dandy.&lt;/p&gt;

&lt;div&gt;
  &lt;svg style=&quot;&quot; id=&quot;circleSVG&quot; height=&quot;200&quot; width=&quot;790&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot;&gt;
  &lt;/svg&gt;
&lt;/div&gt;

&lt;p&gt;What happens if a transition isn’t completed before the next transition starts? For example, the user scrolls to a different section before the current sections animations are complete. Here is &lt;em&gt;what we want to have happen&lt;/em&gt;. The left-to-right transition takes too long, and the right-to-left transition starts before it has a chance to complete. As long as they are both transitions, it doesn’t matter. The first transition is interrupted and the second one starts, as expected.&lt;/p&gt;

&lt;div&gt;
  &lt;svg style=&quot;&quot; id=&quot;circle2SVG&quot; height=&quot;200&quot; width=&quot;790&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot;&gt;
  &lt;/svg&gt;
&lt;/div&gt;

&lt;p&gt;But, if we had &lt;strong&gt;not&lt;/strong&gt; been using transitions for both movements? Say, we had tried to set the circle’s position directly with something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;vis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.circle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;cx&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Well, that would be bad! Instead of interrupting the transition, the animation would just continue unexpectedly - putting your visualization into an invalid state, until another transition corrected things:&lt;/p&gt;

&lt;div&gt;
  &lt;svg style=&quot;&quot; id=&quot;circle3SVG&quot; height=&quot;200&quot; width=&quot;790&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot;&gt;
  &lt;/svg&gt;
&lt;/div&gt;

&lt;p&gt;If you want an effect to be immediate, use a duration of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; for that transition.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.bar-text&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you try to mix transitions with straight attribute modifications, you most likely will end up with visualizations in strange states.&lt;/p&gt;

&lt;h3 id=&quot;use-named-transitions-for-transitions-that-shouldnt-be-interrupted&quot;&gt;Use Named Transitions for Transitions that Shouldn’t Be Interrupted&lt;/h3&gt;

&lt;p&gt;For a few of my transitions, like where the little filler squares leave their spot on the grid, they can be interrupted multiple times with fast scrolling and not quite make it back to their spot. The results are less than flattering.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/scroll/bad_squares.png&quot; alt=&quot;bad squares&quot; style=&quot;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;This was happening because transitions focused on changing these square’s fill value were interrupting this movement transition. I could double check the square’s locations in multiple different section functions, but this would complicate these unrelated functions unnecessarily.&lt;/p&gt;

&lt;p&gt;Instead, I used the new-ish D3 feature of &lt;a href=&quot;http://bl.ocks.org/mbostock/5d8039fb983a29e2ad49&quot;&gt;named transitions&lt;/a&gt; to ensure other transitions wouldn’t clobber this one.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.fill-square&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;move-fills&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The name allows it to run concurrently with other transitions, ensuring the squares will always make it back to their homes!&lt;/p&gt;

&lt;p&gt;Here is an example of using named transitions to change the color and position of the circle. The two transitions don’t interrupt one another, as they have two different names.&lt;/p&gt;

&lt;div&gt;
  &lt;svg style=&quot;&quot; id=&quot;namedSVG&quot; height=&quot;200&quot; width=&quot;790&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot;&gt;
  &lt;/svg&gt;
&lt;/div&gt;

&lt;p&gt;I haven’t used this feature much, but I’m excited to try it in other complex transition scenarios.&lt;/p&gt;

&lt;h2 id=&quot;go-forth-and-scroll&quot;&gt;Go Forth and Scroll&lt;/h2&gt;

&lt;p&gt;Hopefully with this post I’ve dispelled some of the dark art of scrolling for you, and for myself.&lt;/p&gt;

&lt;p&gt;Scrolling should still be used carefully and with the end user always in mind. And as pros like the New York Times &lt;a href=&quot;http://www.nytimes.com/interactive/2015/03/19/upshot/3d-yield-curve-economic-growth.html&quot;&gt;continue to show us&lt;/a&gt;, sometimes a stepper is exactly the right tool for the job.&lt;/p&gt;

&lt;p&gt;But when scrolling is what you want, check out the details of this post and the demo code. And if you want to hear me blather even more about scrolling, then you’ll be excited about my upcoming &lt;a href=&quot;http://openvisconf.com/&quot;&gt;OpenVis Conf talk&lt;/a&gt; on this very subject!&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/scroll_demo/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/scroll/bars.png&quot; alt=&quot;measles&quot; style=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;As always, the code for this demo &lt;a href=&quot;https://github.com/vlandham/scroll_demo&quot;&gt;is on github&lt;/a&gt; Have suggestions or comments or complaints? Let me know!&lt;/p&gt;

&lt;p&gt;An aside: The title comes from the epic Sierra Adventures Game &lt;a href=&quot;http://en.wikipedia.org/wiki/Quest_for_Glory&quot;&gt;Quest for Glory I&lt;/a&gt; - which I try to bring up in almost every conversation. If you haven’t tried it yet, go download &lt;a href=&quot;http://boxerapp.com/&quot;&gt;Boxer&lt;/a&gt;, grab &lt;a href=&quot;http://www.myabandonware.com/game/quest-for-glory-i-so-you-want-to-be-a-hero-1kc&quot;&gt;a copy&lt;/a&gt; and enjoy. Scrolling can wait for a bit.&lt;/p&gt;

&lt;script src=&quot;js/d3.min.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;js/scroller/examples.js&quot;&gt;&lt;/script&gt;

</content>
 </entry>
 
 <entry>
   <title>Making Learn JS Data</title>
   <link href="http://vallandingham.me/learnjsdata.html"/>
   <updated>2015-03-23T00:00:00+00:00</updated>
   <id>http://vallandingham.me/learnjsdata</id>
   <content type="html">&lt;p&gt;Recently Bocoup released a new guide: &lt;a href=&quot;http://learnjsdata.com/&quot;&gt;LearnJSData.com&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://learnjsdata.com/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/learnjsdata/learnjsdata.png&quot; alt=&quot;learn js data&quot; style=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;LearnJSData.com attempts to be a starting point for data processing and analysis using JavaScript. In it, &lt;a href=&quot;https://twitter.com/iros&quot;&gt;Irene Ros&lt;/a&gt; and I, and a number of other collaborators, try to provide examples of common processing techniques using native JavasScript and a minimal set of libraries, namely &lt;a href=&quot;http://d3js.org/&quot;&gt;D3.js&lt;/a&gt; and &lt;a href=&quot;https://lodash.com/&quot;&gt;lodash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The idea behind this project is to help those who may have some JavaScript experience, but have not really dealt much with data. Also, the guide can help those who have done data processing in other scripting languages, like python or R, and now have a need for similar data manipulation tools in JavaScript.&lt;/p&gt;

&lt;p&gt;The guide serves as a starting point, and it is by no means comprehensive, but it suggests a way to get started and contains some handy tips that I, Irene, and others have learned along the way.&lt;/p&gt;

&lt;p&gt;For a while, I have been wanting to create a tutorial around all the uses of &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Arrays#d3_nest&quot;&gt;d3.nest&lt;/a&gt; in terms of restructuring and summarizing data. Its a powerful tool, but one that isn’t often considered when processing data. It took a small tweet from &lt;a href=&quot;https://twitter.com/arnicas&quot;&gt;Lynn Cherney&lt;/a&gt; regarding the lack of comprehensive data munging guides for JavaScript to suggest that there might be a need for this kind of introductory material.&lt;/p&gt;

&lt;p&gt;Recently, the Bocoup family participated in their extra-special week-long Bocoupfest extravaganza. This is a special time for Bocoupers where we are encouraged to connect with others on collaborative projects. As a new member of the Bocoup Data Visualization team, my teammates, Irene Ros and &lt;a href=&quot;https://twitter.com/tafsiri&quot;&gt;Yannick Assogba&lt;/a&gt; suggested that this would be a good time to focus on this fledgling guide idea, and turn it into something real.&lt;/p&gt;

&lt;p&gt;The process was incredible. During the week, Irene productionized the build system, wrote the difficult tasks of string manipulation and regular expressions, provided expert guidance, and even made an awesome logo for the project! Yannick and other Bocoupers, &lt;a href=&quot;https://twitter.com/mrspeaker&quot;&gt;Earle Castledine&lt;/a&gt;, and &lt;a href=&quot;https://twitter.com/JugglinMike&quot;&gt;Mike Pennisi&lt;/a&gt; helped with content suggestions and ways to make the guide more interactive in the future. Even &lt;a href=&quot;https://twitter.com/ajpiano&quot;&gt;Adam Sontag&lt;/a&gt; got involved by giving it a name and a place to live. It was a real team effort! Given their previous work with &lt;a href=&quot;http://learnlayout.com/&quot;&gt;Learn CSS Layout&lt;/a&gt;, I guess that should come as no surprise.&lt;/p&gt;

&lt;p&gt;At the end of the week, this scrap of an idea had been transformed into a real live thing!&lt;/p&gt;

&lt;p&gt;It’s only been up for a few days, but so far the response from the community has really been fun to watch and be a part of. Even as we released it to the public via Twitter at the end of Bocoupfest, I was dubious of how others would perceive an introduction to a topic in a language not really known for its data processing functionality. I expected a few tweets and then perhaps some snarky comments of this being a bad idea, and that would be that.&lt;/p&gt;

&lt;p&gt;But in just 7 days, Learn JS Data has had nearly 4,000 visitors. And people seem to be actually reading some of it! With an average of 2.5 pageviews per session. According to Twitter analytics, &lt;a href=&quot;https://twitter.com/vlandham/status/576457270625701888&quot;&gt;my tweet about the project&lt;/a&gt; was retweeted 95 times and has been seen by nearly 20,000 pairs of eyeballs (if you believe the measure of &lt;em&gt;impressions&lt;/em&gt; is legitimate which I have my doubts about).&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/learnjsdata/visitors.png&quot; alt=&quot;learn js data&quot; style=&quot;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;And the community isn’t just consuming. Folks are actively improving and adding content!&lt;/p&gt;

&lt;p&gt;Already, we have a completely new task around &lt;a href=&quot;http://learnjsdata.com/combine_data.html&quot;&gt;combining data&lt;/a&gt; contributed completely by &lt;a href=&quot;https://twitter.com/grssnbchr&quot;&gt;Timo Grossenbacher&lt;/a&gt;. And &lt;a href=&quot;https://gyrosco.pe/davo/&quot;&gt;Davo Galavotti&lt;/a&gt; and friends are already working on a Spanish translation of the entire guide!&lt;/p&gt;

&lt;p&gt;The experience has really driven home the power of collaboration for me. This project wouldn’t have been nearly as successful without the selfless contributions of those mentioned above.&lt;/p&gt;

&lt;p&gt;This process also allowed me to get a bit more insight into the &lt;em&gt;specialness&lt;/em&gt; of Bocoup. Because of the responsibility, dedication, and care Bocoup has shown in the Open Source and Open Web worlds, people seem to feel comfortable with contributing to Bocoup projects. They know that the same care and responsibility will be taken with their contributions. Its an interesting facet of these communities that I hadn’t experienced, or even considered before.&lt;/p&gt;

&lt;p&gt;So, go checkout &lt;a href=&quot;http://learnjsdata.com/&quot;&gt;LearnJSData.com&lt;/a&gt;, and give us some &lt;a href=&quot;https://github.com/vlandham/js_data/issues&quot;&gt;feedback&lt;/a&gt; on how to improve it. And who knows, you just might find it useful yourself!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Interactive Small Multiples</title>
   <link href="http://vallandingham.me/interactive_small_multiples_talk.html"/>
   <updated>2015-02-28T00:00:00+00:00</updated>
   <id>http://vallandingham.me/interactive_small_multiples_talk</id>
   <content type="html">&lt;p&gt;Based around the findings of my &lt;a href=&quot;http://vallandingham.me/linked_small_multiples.html&quot;&gt;linked small multiples tutorial&lt;/a&gt; - I gave a talk about different types of interactions you can use with small multiples and how you might build one yourself.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;http://vallandingham.me/small_mults_talk/&quot;&gt;slides here&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/small_mults_talk/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/small_mults_talk.png&quot; alt=&quot;small mults slides&quot; style=&quot;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;I gave this talk at &lt;a href=&quot;http://bocoup.com/&quot;&gt;Bocoup&lt;/a&gt; (to silence-is-golden rave reviews).&lt;/p&gt;

&lt;p&gt;I love talking about awesome visualization techniques like small multiples. If I can present this to your group - let me know!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kansas City Streets Map Remix</title>
   <link href="http://vallandingham.me/kansas_city_streets_map_remix.html"/>
   <updated>2014-12-31T00:00:00+00:00</updated>
   <id>http://vallandingham.me/kansas_city_streets_map_remix</id>
   <content type="html">&lt;p&gt;Technologies change with the times. Nothing stays the same. Awhile back, I &lt;a href=&quot;http://vallandingham.me/kansas_city_streets_map_with_tilemill.html&quot;&gt;experimented with TileMill&lt;/a&gt; to create a “streets only” view of Kansas City - with hopefully enough detail in the instructions that you could do it yourself for your own hometown.&lt;/p&gt;

&lt;p&gt;Recently, Mapbox has released &lt;a href=&quot;https://www.mapbox.com/design/&quot;&gt;Mapbox Studio&lt;/a&gt; - which looks to be &lt;a href=&quot;https://www.mapbox.com/mapbox-studio/common-questions/#how-is-mapbox-studio-related-to-tilemill&quot;&gt;the successor to TileMill&lt;/a&gt; for all your map design needs. A revolutionary feature is the use of &lt;a href=&quot;https://www.mapbox.com/blog/vector-tiles/&quot;&gt;vector tiles&lt;/a&gt; to power the maps, instead of traditional image based solutions. Mapbox has been kind enough to include lots of data sources &lt;a href=&quot;https://www.mapbox.com/data-platform/&quot;&gt;built right into Mapbox Studio&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;This means, to make street maps, we might not need to import any additional data. Wow!&lt;/p&gt;

&lt;p&gt;I wanted to try my hand at revamping the simple streets only Kansas City map using these new technologies. Join me, won’t you, on this adventure!&lt;/p&gt;

&lt;h2 id=&quot;start-me-up&quot;&gt;Start Me Up&lt;/h2&gt;

&lt;p&gt;After registering for a Mapbox account and downloading Mapbox Studio, we are introduced to Mapbox Studio by a nice little default map.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/01_starting_point.png&quot; alt=&quot;starting mapbox studio&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;While we could probably start styling right now, I’d like to explore the project creation part of Mapbox Studio. Clicking on the “Projects” button in the lower-left portion of the window, opens the project menu.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/02_new_project_anno.png&quot; alt=&quot;new project&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;It took me a second to figure out that there were two types of projects - &lt;em&gt;style&lt;/em&gt; projects that deal with the look and feel of the map, and &lt;em&gt;source&lt;/em&gt; projects that are used to define data sources. Guess I should have read a &lt;a href=&quot;https://www.mapbox.com/mapbox-studio/common-questions/#what-is-the-difference-between-style-and-source-projects&quot;&gt;bit more of the documentation&lt;/a&gt; !&lt;/p&gt;

&lt;p&gt;So, I want a new style project, which is toggled by default.&lt;/p&gt;

&lt;p&gt;Clicking on “New Project” provides a plethora of built-in styles to start from.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/03_styles.png&quot; alt=&quot;new project&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;We could start with a blank slate, but I was intrigued by the “High Contrast” style - which looked a bit like a supped up version of the streets map. Selecting this style, we are transported back to the map panel, but we a new view and a new starting location.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/04_styled.png&quot; alt=&quot;new project&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;h2 id=&quot;style-me-up&quot;&gt;Style Me Up&lt;/h2&gt;

&lt;p&gt;Already, its looking pretty awesome!&lt;/p&gt;

&lt;p&gt;On the left, we can see the &lt;a href=&quot;https://www.mapbox.com/tilemill/docs/crashcourse/styling/&quot;&gt;CartoCSS&lt;/a&gt; that is used to make the map look the way it does. There are multiple style files, each one focusing on styling different portions of the map. The files provided with this style are &lt;em&gt;style&lt;/em&gt; for general map features, &lt;em&gt;road&lt;/em&gt; for styling roads at different zoom levels, and &lt;em&gt;labels&lt;/em&gt; for (you guessed it) labels.&lt;/p&gt;

&lt;p&gt;Real quick, let’s switch to our region of choice - Kansas City, using the nifty built in search feature.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/search.gif&quot; alt=&quot;new project&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;No panning and dragging necessary!&lt;/p&gt;

&lt;p&gt;Ok, now lets start styling.&lt;/p&gt;

&lt;p&gt;First, we can ditch the &lt;em&gt;labels&lt;/em&gt; style file, as we don’t want any labels at all. Click on the &lt;em&gt;labels&lt;/em&gt; tab and then the little minus sign next to it. After confirming to remove, the style file is gone - but the labels remain. What?&lt;/p&gt;

&lt;p&gt;Turns out we have to save to get the update to show up (as was the case with TileMill).&lt;/p&gt;

&lt;p&gt;Clicking on the “Save As” button allows you to find a place to save the style project. After saving, we can now see the labels are gone.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/06_no_labels.png&quot; alt=&quot;new project&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Now we want to style some roads. The plan is to copy most of the style from my &lt;a href=&quot;https://gist.github.com/vlandham/2312647#file_style.css&quot;&gt;previous streets style&lt;/a&gt; . This means I’ll end up deleting most of the built in &lt;em&gt;roads&lt;/em&gt; styles too - but I wanted to keep it around to get a feel for how to work with this new data source.&lt;/p&gt;

&lt;p&gt;Looking at the styles in &lt;em&gt;roads&lt;/em&gt;, we can see that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#road&lt;/code&gt; entries have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; associated with their &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Key:highway&quot;&gt;OpenStreetMap tags&lt;/a&gt; . Here is a sample:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/vlandham/35adbfc0ac5876544bcc.js?file=old_roads.css&quot;&gt;
&lt;/script&gt;

&lt;p&gt;To confirm that these classes are in the data, we can switch to the &lt;em&gt;data explore&lt;/em&gt; view to see the metadata behind all these little lines on our map.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/07_menu_anno.png&quot; alt=&quot;menu&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;On the top bar, click the little “layers with magnifying glass” to switch views. Now you can view an x-ray of the data on the map. Click around a bit to see some of what is available.&lt;/p&gt;

&lt;p&gt;Pretty darn impressive, if you ask me.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/08_xray.png&quot; alt=&quot;menu&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;We can see that indeed each road has a property called &lt;em&gt;class&lt;/em&gt; which seem to match the OSM names. So, I need to modify my original stylings to use these classes.&lt;/p&gt;

&lt;p&gt;(Also, the class names are listed in the description section of the roads layer data)&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/roads_description.png&quot; alt=&quot;menu&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;I deleted the &lt;em&gt;roads&lt;/em&gt; stylesheet now (even though it was really cool and useful to learn from), and augmented my old CartoCSS a bit. Here is the styling I came up with.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/vlandham/35adbfc0ac5876544bcc.js?file=style.css&quot;&gt;
&lt;/script&gt;

&lt;p&gt;I’m sure I’m missing out on a ton of cool CartoCSS features, but I just wanted to get something out quick.&lt;/p&gt;

&lt;p&gt;It looks like you have to zoom in to see all the road types (not sure how to override these default zoom levels for all roads).&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/09_zoom.png&quot; alt=&quot;menu&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;h2 id=&quot;extract-me-out&quot;&gt;Extract Me Out&lt;/h2&gt;

&lt;p&gt;So now we have a basic road map, we want to get it out of Mapbox Studio to print.&lt;/p&gt;

&lt;p&gt;Unfortunately, unlike TileMill, Studio doesn’t (yet?) have the ability to export to SVG or another vector format (which seems a bit odd since the input data is vector now…).&lt;/p&gt;

&lt;p&gt;However, you can export high resolution pngs, so let’s try that out.&lt;/p&gt;

&lt;p&gt;Currently, there are two great tutorials from Mapbox about printing from Mapbox Studio:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.mapbox.com/blog/high-res-prints-from-mapbox-studio/&quot;&gt;High resolution prints&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.mapbox.com/blog/web-to-canvas-print/&quot;&gt;Web to canvas prints&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both might be more useful then my own ramblings, so refer to them if I’m not doing it for you.&lt;/p&gt;

&lt;p&gt;First, we should go into settings and switch to 24-bit png to maintain top quality.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/10_change_png.png&quot; alt=&quot;change png&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Next, we open the “Export Image” tool, which is located in the upper-right hand corner of the window.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/11_export_anno.png&quot; alt=&quot;change png&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Exporting still sounds a little tricky.&lt;/p&gt;

&lt;p&gt;First, you draw a bounding box around the portion of the map you would like to export.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/12_bounding_box.png&quot; alt=&quot;change png&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Then, you need to zoom in until you are at the desired zoom (which determines the size of the image) you want to create. In this test, I’ve zoomed to level 13.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/zoom_level.png&quot; alt=&quot;change png&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Make sure the output format is as you like. You want png as the image format, and I’m exporting to 300ppi.&lt;/p&gt;

&lt;p&gt;Then hit Download!&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/13_end.png&quot; alt=&quot;change png&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;According to the &lt;a href=&quot;https://www.mapbox.com/blog/web-to-canvas-print/&quot;&gt;web to canvas&lt;/a&gt; , if your bounding box is too big then you will need to export slices of the map and join them back together in the end.&lt;/p&gt;

&lt;p&gt;I expect some of that might be automated in the future.&lt;/p&gt;

&lt;p&gt;For 300ppi, at 13 zoom, I could download the entire KC export in one piece.&lt;/p&gt;

&lt;h3 id=&quot;put-me-up&quot;&gt;Put Me Up&lt;/h3&gt;

&lt;p&gt;The end result is a 40MB png file of Kansas City - ready for printing.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/kc.png&quot; alt=&quot;map&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Still fun to explore and find the little hints of the city that you remember.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map/airport.png&quot; alt=&quot;airport&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Linked Small Multiples (FlowingData)</title>
   <link href="http://vallandingham.me/linked_small_multiples.html"/>
   <updated>2014-10-15T00:00:00+00:00</updated>
   <id>http://vallandingham.me/linked_small_multiples</id>
   <content type="html">&lt;p&gt;This &lt;a href=&quot;http://flowingdata.com/2014/10/15/linked-small-multiples/&quot;&gt;primer and tutorial on FlowingData&lt;/a&gt; focuses on the use of interaction to link small multiples together to create a richer experience for the reader. We look at a number of examples before diving in to how to create your own sortable and scrubbable small multiples.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://flowingdata.com/2014/10/15/linked-small-multiples/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/flowingdata_linked_small_multiples.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Experiments!</title>
   <link href="http://vallandingham.me/experiments_repo.html"/>
   <updated>2014-03-18T00:00:00+00:00</updated>
   <id>http://vallandingham.me/experiments_repo</id>
   <content type="html">&lt;p&gt;Want some more data visualization attempts, studies, and undertakings? Check out my new &lt;a href=&quot;http://vallandingham.me/experiments/&quot;&gt;Experiments Section&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/experiments/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/experiments.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;Here you will find an ever growing list of half-baked projects and hair-brained ideas.&lt;/p&gt;

&lt;p&gt;As a bonus, I’ve whipped up a little tag-based navigational tool for finding what you are interested in, faster.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/experiments_tags.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/experiments&quot;&gt;Most of the code for these little projects is easily accessible&lt;/a&gt; - just in case anyone wants to explore an idea further.&lt;/p&gt;

&lt;p&gt;Check back often to discover what I have been experimenting with lately.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Let's Make a Bar Chart with Lyra</title>
   <link href="http://vallandingham.me/make_a_barchart_with_lyra.html"/>
   <updated>2014-02-28T00:00:00+00:00</updated>
   <id>http://vallandingham.me/make_a_barchart_with_lyra</id>
   <content type="html">&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; Lyra is labelled as &lt;em&gt;alpha&lt;/em&gt;. Its interface might have changed since this posting.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;A few days ago &lt;a href=&quot;https://twitter.com/arvindsatya1&quot;&gt;Arvind Satyanarayan&lt;/a&gt; from the &lt;a href=&quot;http://idl.cs.washington.edu/&quot;&gt;UW Interactive Data Lab&lt;/a&gt; released an alpha version of &lt;a href=&quot;http://idl.cs.washington.edu/projects/lyra/&quot;&gt;Lyra&lt;/a&gt; that promises to be a way to create complex data visualizations without code. Think of it like an open source Adobe Illustrator, for data visualizations. Sounds pretty awesome, right? But does it work?!&lt;/p&gt;

&lt;p&gt;Let’s find out.&lt;/p&gt;

&lt;p&gt;There are a number of very interesting examples to learn from on the Lyra main page. These examples recreate some well known complex visuals.&lt;/p&gt;

&lt;p&gt;I wanted to see what would be required to create a really basic bar chart - as a way to start to learn more about this interesting tool.&lt;/p&gt;

&lt;p&gt;Here’s the final product:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_final.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Pretty simple right? But &lt;a href=&quot;http://bost.ocks.org/mike/bar/&quot;&gt;sometimes simple ways are best&lt;/a&gt; . So follow along with me for a bit of Lyra fun!&lt;/p&gt;

&lt;h2 id=&quot;your-visualization-development-environment&quot;&gt;Your Visualization Development Environment&lt;/h2&gt;

&lt;p&gt;Here’s what it looks like when you first &lt;a href=&quot;http://idl.cs.washington.edu/projects/lyra/app/&quot;&gt;open Lyra&lt;/a&gt; :&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_01_small.png&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;I’ve annotated the app with my own terminology to provide a bit of orientation.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_01_2_small.png&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;The far &lt;strong&gt;left panel&lt;/strong&gt; provides capabilities to add data to the visualization and manipulate this data.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;top bar&lt;/strong&gt; allows you to drag new visual components or &lt;a href=&quot;https://github.com/trifacta/vega/wiki/Tutorial#wiki-marks&quot;&gt;marks&lt;/a&gt; into the visualization.&lt;/p&gt;

&lt;p&gt;These marks are organized into layers (just like Illustrator!). Properties of the marks in a visualization can be manipulated in the far &lt;strong&gt;right panel&lt;/strong&gt;. This panel is also used to modify the size of the visual, its axes, etc.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;middle&lt;/strong&gt; gives you a preview of the visualization. You can also move around and resize the layers of your work here.&lt;/p&gt;

&lt;p&gt;We will start with the data input and manipulation panel first. Far left.&lt;/p&gt;

&lt;h2 id=&quot;a-simple-data-pipeline&quot;&gt;A Simple Data Pipeline&lt;/h2&gt;

&lt;p&gt;Let’s pull in some data. Adding and manipulating data in Lyra is called a &lt;strong&gt;Data Pipeline&lt;/strong&gt;. To avoid complications, I used &lt;em&gt;medals&lt;/em&gt;, one of the sample data sets provided by Lyra. This set gives data about who won what at the Olympics (I’m guessing it is the 2014 Winter Olympics, but I don’t really know. I don’t really know much Olympics).&lt;/p&gt;

&lt;p&gt;Click on the &lt;em&gt;From Source&lt;/em&gt; drop down and select &lt;em&gt;medals&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_02_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;The original data includes gold, silver, and bronze medal winnings. Let’s just go for gold!&lt;/p&gt;

&lt;h3 id=&quot;filter-transform&quot;&gt;Filter Transform&lt;/h3&gt;

&lt;p&gt;To get this done inside Lyra, we can use the &lt;strong&gt;Transforms&lt;/strong&gt; feature to modify the input data.&lt;/p&gt;

&lt;p&gt;Click on the &lt;em&gt;New Transform&lt;/em&gt; button.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_03_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Then click on the &lt;em&gt;Filter&lt;/em&gt; button&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_04_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;We get a little Filter input field. We are going to perform our first data binding in Lyra now. This involves dragging column names from the Data section to a little circle &lt;em&gt;data binding&lt;/em&gt; visual.&lt;/p&gt;

&lt;p&gt;In this instance we are going to drag the column &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Medal_Type&lt;/code&gt; over to the Filter section.&lt;/p&gt;

&lt;p&gt;Here is a little animated gif of the whole process:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/bind.gif&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;I’ll break it down step-by-step for the anti-gif folks out there. Here’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Medal_Type&lt;/code&gt; move.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_06_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Once you do that, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Medal_Type&lt;/code&gt; should show up in your filter input.&lt;/p&gt;

&lt;p&gt;Now we are going to complete the filter by checking this column against the string &lt;em&gt;“Gold”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This appears to be JavaScript, so you are going to want to use the double equals: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Medal_Type == &quot;Gold&quot;&lt;/code&gt;. In fact, a single equals sign in that filter seems to modify your data on the fly… which could be useful in other circumstances.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_07.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Once you have the filter setup, click &lt;em&gt;Add to Pipeline&lt;/em&gt;. This will add the filter step to your pipeline (as you might guess by the name of the button).&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_08.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;If you look at the values shown in the Data panel, you should see that only those with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Medal_Type&lt;/code&gt; as &lt;em&gt;Gold&lt;/em&gt; are shown. Pretty cool right?&lt;/p&gt;

&lt;h3 id=&quot;sort-those-medals&quot;&gt;Sort those Medals&lt;/h3&gt;

&lt;p&gt;Now I want to sort the data in order of medal counts, so the countries with the most medals appear at the top. You might have guessed it by now, but we are going to use the sort Transform.&lt;/p&gt;

&lt;p&gt;Click on the &lt;em&gt;New Transform&lt;/em&gt; button again, but this time select &lt;em&gt;Sort&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_04_2.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Now we need to pull &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Count&lt;/code&gt; down to the &lt;em&gt;Sort By&lt;/em&gt; field:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_09_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Then select &lt;em&gt;Descending&lt;/em&gt; for the &lt;em&gt;Order&lt;/em&gt;. Once you add this to the pipeline, we should have all our data transformations done, and be ready for some visualizing.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_10.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;h2 id=&quot;the-visualization&quot;&gt;The Visualization&lt;/h2&gt;

&lt;p&gt;Now let’s move our attention over to the far right panel.&lt;/p&gt;

&lt;p&gt;We see &lt;em&gt;Visualization&lt;/em&gt; at the top, and &lt;em&gt;Layer 1&lt;/em&gt; which is clickable to show more options.&lt;/p&gt;

&lt;h3 id=&quot;give-yourself-some-room&quot;&gt;Give Yourself Some Room&lt;/h3&gt;

&lt;p&gt;One thing that took me a while to find was how to change the width and height of the entire visualization. The width and height of a layer (even the first layer) isn’t the same as the width and height of the entire visual.&lt;/p&gt;

&lt;p&gt;To change the visualizations size, click on the &lt;em&gt;Visualization&lt;/em&gt; header. You should see &lt;em&gt;Dimensions&lt;/em&gt; and &lt;em&gt;Padding&lt;/em&gt; options.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_11_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;As you can see in the image above, I gave my visualization some space by changing the &lt;em&gt;Width&lt;/em&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;700&lt;/code&gt; and &lt;em&gt;Height&lt;/em&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;500&lt;/code&gt;. I am assuming this is in pixels. For now, let’s leave the &lt;em&gt;Padding&lt;/em&gt; setting alone.&lt;/p&gt;

&lt;h3 id=&quot;your-first-mark&quot;&gt;Your First Mark&lt;/h3&gt;

&lt;p&gt;Now is the moment we’ve all been waiting for: the start of the actual visualization.&lt;/p&gt;

&lt;p&gt;Visual elements, like rectangles, lines, and even text are known as &lt;strong&gt;marks&lt;/strong&gt;. We are going to add a rectangle mark for our bar chart.&lt;/p&gt;

&lt;p&gt;To do this, drag the &lt;em&gt;rectangle&lt;/em&gt; mark from Marks Menu on top down to the visualization preview section:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_12_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;And release. You’ll be left with a little blue rectangle in your visualization preview.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_13.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Animated gif version:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/rect.gif&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;The visualization panel should reflect this addition as well. You should see a &lt;em&gt;Rect 1&lt;/em&gt; mark under &lt;em&gt;Layer 1&lt;/em&gt;. This is where we are going to associate data elements with the attributes of the rectangle.&lt;/p&gt;

&lt;h3 id=&quot;binding-the-data&quot;&gt;Binding the Data&lt;/h3&gt;

&lt;p&gt;Ok, so far this just looks like a drawing app. That square is nice and all, but isn’t what you would call a “data visualization”. Let’s really start making the vis happen by binding some data to the visual properties of the rectangle mark.&lt;/p&gt;

&lt;p&gt;The process is similar to how we used data elements in our data transforms. It works by drag-and-drop.&lt;/p&gt;

&lt;p&gt;Because we are making a vertical bar chart, I want to associate the width of one or more rectangles with the count of Olympic medals for a country. You should see &lt;em&gt;Width&lt;/em&gt; listed as a property of &lt;em&gt;Rect 1&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_15_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Right now it is set to a constant number. We are going to drag over the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Count&lt;/code&gt; data element from our data pipeline and connect it to the little circle visual next to &lt;em&gt;Width&lt;/em&gt;. You really have to drop it right on the circle to make it count.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_16_1_small.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Once you release the data element, you should see your visualization preview change to show a bunch of rectangles on top of one another - instead of what looked like just one.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_17.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Not a bad start, but a bit crowded. Let’s move them off one another. I think you could do this a number of ways, but try binding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Country_Code&lt;/code&gt; data element to the mark’s &lt;em&gt;Y Position&lt;/em&gt; property. Since the country code is unique for each bar (as we have already filtered to only include gold medals), this make each bar move to a unique position. Try it. Drag the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Country_Code&lt;/code&gt; data element to &lt;em&gt;Y Position&lt;/em&gt; and release.&lt;/p&gt;

&lt;p&gt;My Lyra looks something like this:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_18_small.png&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;We can start to see a little bar chart starting to form. Exciting!&lt;/p&gt;

&lt;h3 id=&quot;getting-the-look&quot;&gt;Getting the Look&lt;/h3&gt;

&lt;p&gt;Now that we have bars, let’s make them a bit more attractive. First, modify the &lt;em&gt;Height&lt;/em&gt; property to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;15&lt;/code&gt; - so they aren’t sitting on top of one another.&lt;/p&gt;

&lt;p&gt;Also, set the &lt;em&gt;X Position&lt;/em&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;. We will move it around in a second.&lt;/p&gt;

&lt;p&gt;Now we can gild our blue bars. Modify the &lt;em&gt;Fill color&lt;/em&gt; property. You can type in a specific hex or other &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value&quot;&gt;css color name&lt;/a&gt;. Feel free to pick one less terrible than mine. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#e68b02&lt;/code&gt; was as gold as I wanted to get.&lt;/p&gt;

&lt;p&gt;Now I’m going to make room for my title and bar annotations by moving the layer over a bit. You could do this in the right panel by clicking on &lt;em&gt;Layer 1&lt;/em&gt; and setting the x/y position as well as the width and height. But, you can also do this in a more visual manner by moving the layer around in the Visualization Preview panel.&lt;/p&gt;

&lt;p&gt;If you move your mouse inside the Visualization Preview, you should see the layer parameter highlighted with a little dotted line. Click inside that dotted line (but not on a bar) to select &lt;em&gt;Layer 1&lt;/em&gt;. The little rectangles around the parameter should indicate it is selected.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_19.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Now click on these parameter rectangles and resize each side of the layer until its in the location you want. This will take some jostling - and can always be modified in the future.&lt;/p&gt;

&lt;p&gt;You can check the settings in the &lt;em&gt;Layer 1&lt;/em&gt; properties. I ended up with the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;X Start&lt;/em&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;105&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Width&lt;/em&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;580&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Y Start&lt;/em&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;50&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Height&lt;/em&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;400&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_20_small.png&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;I don’t know if the visual manipulation is easier or more work than just trying out different values in the input boxes, but its nice to have options.&lt;/p&gt;

&lt;p&gt;Again, the general idea is that I know I want to make room for a title and some labels on the side.&lt;/p&gt;

&lt;h3 id=&quot;label-those-bars&quot;&gt;Label Those Bars&lt;/h3&gt;

&lt;p&gt;Ok, we make room for them, now let’s add some labels. As you might suspect, we are going to use the &lt;em&gt;Text&lt;/em&gt; mark. Drag one of them down to your visualization preview - just like we did with the rectangle.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_21_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;You should see a little blue text that reads “text”. Cute, but useless.&lt;/p&gt;

&lt;p&gt;To get the country names on the screen, bind the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Country_Name&lt;/code&gt; data element to the &lt;em&gt;Text&lt;/em&gt; property of the text mark. This is the same drag-and-drop as before.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_22_1_small.png&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Now you have a big jumble of little blue text.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_23.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Bind the &lt;em&gt;Y Position&lt;/em&gt; property to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Country_Code&lt;/code&gt;, like you did for the rectangles. For some reason, I was having some problems with this drag-and-drop. Make sure the right circle changes color before you let go with your mouse.&lt;/p&gt;

&lt;p&gt;Now the labels are starting to look like labels. To clean them up a bit, I set their &lt;em&gt;Align Horizontal&lt;/em&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Right Align&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_24.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Next, I played around with the x/y position and offset. I ended up with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-7&lt;/code&gt; &lt;em&gt;X Position&lt;/em&gt; and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10&lt;/code&gt; &lt;em&gt;Y Offset&lt;/em&gt;. Also, I changed the color to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#777777&lt;/code&gt;. Ta Da!&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_25_small.png&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;h3 id=&quot;always-add-an-axis&quot;&gt;Always Add an Axis&lt;/h3&gt;

&lt;p&gt;Things are coming along now!&lt;/p&gt;

&lt;p&gt;But we need to give our visual some perspective. What numbers are these bars actually representing? 50? 500? Let’s add an axis to find out.&lt;/p&gt;

&lt;p&gt;In Lyra, it looks like Axes are associated with a particular layer. If you scroll back to the top of the right panel, you should see a little &lt;em&gt;Axes&lt;/em&gt; section with a plus button to add a new axis. Click that button now.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_26_1.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;You should see a little new axis panel appear:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_27.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;For &lt;em&gt;Type&lt;/em&gt; we are going to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X&lt;/code&gt;. For orient, we are going to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bottom&lt;/code&gt;. Now we need to associate a Scale with the axis. In the bottom left-hand corner of the screen, you should see your &lt;em&gt;Scales&lt;/em&gt; menu. Drag up your &lt;em&gt;X Scale&lt;/em&gt; and drop it in the Axis &lt;em&gt;Scale&lt;/em&gt; property.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_28_1_small.png&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Once its dropped in, you should see your scale appear at the bottom of the preview panel. Pretty slick!&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/scale.gif&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;I changed all the colors of each element of the axis to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#777777&lt;/code&gt;. I did try messing with the other properties of the axis mark and ended up screwing everything up. This will probably not be an issue in the future - but be advised - right now it seems a little picky.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_29.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;h3 id=&quot;finish-with-a-title&quot;&gt;Finish with a Title&lt;/h3&gt;

&lt;p&gt;Ok, my fingers are cramping up. We need to end this tutorial quick, so let’s add a title.&lt;/p&gt;

&lt;p&gt;To do this, drop another Text mark into your visualization preview. Instead of associating its text with a data element, we will just type out a title. I choose “Gold Medals by Country”. You can use that too, if you want. A better title would be “Olympic Gold Medals by Country”. An even better title would include a date.&lt;/p&gt;

&lt;p&gt;Next position and style. This should all be familiar, as we just did it with the labels. To mix things up a bit, I switched the &lt;em&gt;Font Family&lt;/em&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Georgia&lt;/code&gt;, and set the color to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#595959&lt;/code&gt;. &lt;em&gt;Font Size&lt;/em&gt; is 24.&lt;/p&gt;

&lt;p&gt;Right now this text mark is part of the same layer as everything else. This might be the wrong way to do things - but it works at least in this simple example. A consequence of this association is that the &lt;em&gt;Y Position&lt;/em&gt; will need to be negative to move the title above the chart. I set the &lt;em&gt;Y Position&lt;/em&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-24&lt;/code&gt; and the &lt;em&gt;X Position&lt;/em&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;130&lt;/code&gt; to get my particular styling. You can do better.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_30_small.png&quot; alt=&quot;&quot; style=&quot;border:0px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;h3 id=&quot;save-and-share&quot;&gt;Save and Share!&lt;/h3&gt;

&lt;p&gt;Down at the bottom of the screen are a few utility buttons:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_31.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;You can export your work of art as SVG or PNG for static showing. You can also export as a &lt;a href=&quot;http://trifacta.github.io/vega/&quot;&gt;Vega spec&lt;/a&gt; to allow for more interactive end goals. I haven’t done much with Vega yet, but this is a particularly exciting possibility that will require future exploring.&lt;/p&gt;

&lt;p&gt;You should also be able to save the Lyra settings in your browser history and load up old ones from this button bar.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/lyra/lyra_final.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;h3 id=&quot;your-homework&quot;&gt;Your Homework&lt;/h3&gt;

&lt;p&gt;Hopefully you enjoyed this little introduction to Lyra. I think it might turn out to be a very useful tool in the future for creating data visualizations in a systematic, but non-programmatic way.&lt;/p&gt;

&lt;p&gt;If you want to build on this example, what about filtering out countries with 0 gold medals?&lt;/p&gt;

&lt;p&gt;Right now India, Armenia, etc are shown, but their bar values are really 0. Try filtering out these countries and re-situating the visual elements to take up this extra space.&lt;/p&gt;

&lt;p&gt;For the more adventurous, try getting a visual display for all 3 types of medals. This might involve using the &lt;em&gt;Group By&lt;/em&gt; Transform to add some hierarchy to the data.&lt;/p&gt;

&lt;p&gt;And that is a simple introduction to Lyra. Hopefully starting with the basics will encourage us all to start making more advanced graphics with these tools and allow us to better understand the more complex starting points created by the author.&lt;/p&gt;

&lt;p&gt;My first thoughts on Lyra is that it is certainly rough around the edges, but could provide real value to the visualization community.&lt;/p&gt;

&lt;p&gt;It has some overlap with Design Density’s wonderful &lt;a href=&quot;http://app.raw.densitydesign.org/#/&quot;&gt;RAW&lt;/a&gt; app. While RAW is more polished, I think Lyra might ultimately provide a more powerful feature set for those interested in learning the tool.&lt;/p&gt;

&lt;p&gt;Lyra’s binding capabilities allow for comparisons to some of what is featured in Bret Victor’s &lt;a href=&quot;http://worrydream.com/#!/DrawingDynamicVisualizationsTalk&quot;&gt;Drawing Dynamic Visualizations&lt;/a&gt; tool. If his tool is released, it will be interesting to compare further.&lt;/p&gt;

&lt;p&gt;D3’s success in the data visualization world has been in part because of its &lt;a href=&quot;https://groups.google.com/forum/#!forum/d3-js&quot;&gt;large thriving community&lt;/a&gt; . And this large community was built up quickly in part because of the many &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Gallery&quot;&gt;examples&lt;/a&gt; provided by the authors as well as other individuals.&lt;/p&gt;

&lt;p&gt;Let’s hope Lyra, if it proves useful to others, is also able to foster an active community - capable of taking it to the next level.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Visualizing Bird Songs with Web Audio</title>
   <link href="http://vallandingham.me/visualizing_bird_songs.html"/>
   <updated>2014-01-27T00:00:00+00:00</updated>
   <id>http://vallandingham.me/visualizing_bird_songs</id>
   <content type="html">&lt;script src=&quot;//d3js.org/d3.v3.min.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;vis/js/spectrogram.js&quot;&gt;&lt;/script&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/spectrogram.png&quot; alt=&quot;Spectrogram&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;UPDATE (07/04/2018):&lt;/strong&gt; The amazingly talented &lt;a href=&quot;https://github.com/eren-ck&quot;&gt;Eren Cakmak&lt;/a&gt; has contributed a significantly updated version of &lt;a href=&quot;https://github.com/vlandham/spectrogramJS&quot;&gt;spectrogramJS&lt;/a&gt;. This new version uses D3v5, has zoom capabilities, and allows you to specify a color scheme for your spectrogram. Thanks so much to Eren for these contributions!&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;bird-based-visualizations&quot;&gt;Bird-based Visualizations&lt;/h2&gt;

&lt;p&gt;Recently, I rediscovered a wonderful book on my shelf, which ended up sparking a bit of visualization exploration.&lt;/p&gt;

&lt;p&gt;The book was a 1966 copy of &lt;a href=&quot;http://www.amazon.com/Birds-North-America-Identification-Golden/dp/1582380902&quot;&gt;Birds of North America&lt;/a&gt; . I must of borrowed, bought, or stolen it at some point in life, only to forget of its existence.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/birds_book_front.jpg&quot; alt=&quot;bird book&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Get yourself a copy, if you get the chance. Even &lt;a href=&quot;http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0000M4&quot;&gt;Tufte agrees&lt;/a&gt; : its good. (In fact, I have started casually collecting as many &lt;a href=&quot;http://en.wikipedia.org/wiki/Golden_Guide&quot;&gt;Golden Guide&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Golden_Field_Guide&quot;&gt;Golden Field Guide&lt;/a&gt; books as I can find. They are all amazing.)&lt;/p&gt;

&lt;p&gt;Laced throughout the pages of this great resource, I discovered an interesting visual approach to depicting bird calls and songs on paper. Labelled a “sonagram” in the book, this method is now known as a &lt;a href=&quot;http://en.wikipedia.org/wiki/Spectrogram&quot;&gt;spectrogram&lt;/a&gt; (probably to reduce confusion with modern day baby detecting and depicting technologies).&lt;/p&gt;

&lt;p&gt;You can see them below, right above the range maps for each species.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/book_spectrograms.jpg&quot; alt=&quot;bird spectrograms&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;From the notes in the front of the book, this is the first time this type of visual representation was used on the general public. And I think it works pretty darn well.&lt;/p&gt;

&lt;p&gt;Its not a complex format. Really, a sort of specialized scatter plot. Time is on the x axis, frequency on the y. As you might guess, low notes have lower frequencies and high notes have higher frequencies. Cells within the graph are shaded by the intensity or loudness of a particular frequency at a particular time.&lt;/p&gt;

&lt;p&gt;This simplistic framework allows for the complexity of natural sounds to be revealed.&lt;/p&gt;

&lt;p&gt;Sounds from bird calls to cat calls show patterns that span the spectrum. Once you are able to pair a sound with its spectrogram, you can start hearing all the little complexities that are present in the visual. Furthermore, you can develop an intuition about what something will sound like - just from the spectrogram itself.&lt;/p&gt;

&lt;p&gt;Of course, when I saw how beautiful this visualization was, I wanted to create some of my own. So I made a little tool to do just that!&lt;/p&gt;

&lt;p&gt;Its called &lt;a href=&quot;https://github.com/vlandham/spectrogramJS&quot;&gt;SpectrogramJS&lt;/a&gt; and you can try it out here and use it in your own projects!&lt;/p&gt;

&lt;div id=&quot;bird_vis&quot; class=&quot;spectrogram&quot;&gt;
&lt;/div&gt;

&lt;script&gt;
var sample = new Spectrogram('vis/data/bird\_short.ogg', &quot;\#bird\_vis&quot;, {width:600, height:200});
&lt;/script&gt;

&lt;p&gt;Click &lt;em&gt;analyze&lt;/em&gt; to begin processing the provided sound. Once done, you can hit &lt;em&gt;play&lt;/em&gt; again to follow along with the spectrogram as the sound plays.&lt;/p&gt;

&lt;p&gt;Simple, but I think pretty true to the original - while being more useful then a static image.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/vlandham/spectrogramJS&quot;&gt;SpectrogramJS github&lt;/a&gt; to start visualizing your own bird calls today.&lt;/p&gt;

&lt;p&gt;More on how SpectrogramJS was built below.&lt;/p&gt;

&lt;h2 id=&quot;reinventing-the-wheel&quot;&gt;Reinventing the Wheel&lt;/h2&gt;

&lt;p&gt;It turns out others before me have heard the spectrogram’s siren call, and have developed software to generate similar charts. &lt;a href=&quot;http://audacity.sourceforge.net/&quot;&gt;Audacity&lt;/a&gt; appears to have a &lt;a href=&quot;http://www.youtube.com/watch?v=7WYw3qoTdU4&quot;&gt;spectrogram view&lt;/a&gt; . In fact, the &lt;a href=&quot;http://www.birds.cornell.edu/brp/Raven/RavenOverview.html&quot;&gt;Raven&lt;/a&gt; product suite, which includes the free &lt;em&gt;Raven Lite&lt;/em&gt;, looks to be a powerful tool specifically for the purposes of analyzing bird songs and other animal calls using spectrograms.&lt;/p&gt;

&lt;p&gt;Ok, so the spectrogram ground is pretty well covered. Implementing my own version wouldn’t necessarily be practical - or even useful - in light of these other much more robust systems. Or at least, these were my initial thoughts.&lt;/p&gt;

&lt;p&gt;However, these tools are heavyweights in their field. And with all that power and bulk can be limiting in their own way.&lt;/p&gt;

&lt;p&gt;What about a lightweight tool for quick and dirty spectrogram creations? One that could provide interactive capabilities outside of traditional applications and instead provide a web-based experience.&lt;/p&gt;

&lt;h2 id=&quot;html5-web-audio-api-to-the-rescue&quot;&gt;HTML5 Web Audio API to the Rescue!&lt;/h2&gt;

&lt;p&gt;So, I turned to the still developing &lt;a href=&quot;https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html&quot;&gt;Web Audio API&lt;/a&gt; to see if such a web-based experience could be had. It turns out that this API has audio analysis capabilities that make it suited for &lt;a href=&quot;https://github.com/michaelbromley/soundcloud-visualizer&quot;&gt;all sorts&lt;/a&gt; of audio visualizations.&lt;/p&gt;

&lt;p&gt;In fact, cool spectrogram projects have already been implemented using this API. Google created a &lt;a href=&quot;http://www.creativeapplications.net/javascript-2/web-audio-javascript-sound/&quot;&gt;3d sonogram&lt;/a&gt; to demo the use of the Web Audio API. Jos Dirksen also has a great &lt;a href=&quot;http://www.smartjava.org/content/exploring-html5-web-audio-visualizing-sound&quot;&gt;moving spectrogram&lt;/a&gt; as part of his tutorial on web audio.&lt;/p&gt;

&lt;p&gt;So, for my project, I focus on just replicating the look and feel of my original inspiration - the bird book. Clean and simple, providing insight and context.&lt;/p&gt;

&lt;p&gt;I am just dipping my toes in the Audio API stream right now, but most of my knowledge comes from the wonderful &lt;a href=&quot;http://chimera.labs.oreilly.com/books/1234000001552&quot;&gt;Web Audio API&lt;/a&gt; book by &lt;a href=&quot;http://twitter.com/borismus&quot;&gt;Boris Smus&lt;/a&gt; (which is currently free to read on O’Reilly). Some of this content is also in the &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/webaudio/intro/&quot;&gt;tutorials on HTML5 Rocks&lt;/a&gt; - which is also a great starting point.&lt;/p&gt;

&lt;p&gt;From what I understand, the Web Audio API is used by creating and connecting nodes together in a directed graph, called the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/AudioContext&quot;&gt;audio context&lt;/a&gt; . These nodes can be audio sources, audio outputs, or nodes to analyze and manipulate.&lt;/p&gt;

&lt;p&gt;It is these &lt;em&gt;analyzing&lt;/em&gt; nodes that we take advantage of to allow for the analysis of the temporal and frequency aspects of a sound. My audio context looks pretty simple for this visualization:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/audio_nodes.png&quot; alt=&quot;node connections&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;

&lt;p&gt;Specifically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createAnalyser()&lt;/code&gt; will create an instance of a Web Audio Analyzer that can provide frequency data through a &lt;a href=&quot;http://en.wikipedia.org/wiki/Fourier_transform&quot;&gt;Fourier transform&lt;/a&gt; . Its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getByteFrequencyData()&lt;/code&gt; function dumps an array of frequency values for the portion of the audio stream currently being analyzed.&lt;/p&gt;

&lt;p&gt;To sample frequency data throughout the sound clip, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createScriptProcessor()&lt;/code&gt; is used to create a JavaScript processing node that will execute a callback at a particular sample rate.&lt;/p&gt;

&lt;p&gt;The sampling callback is pretty simple. After some setup, it really just appends frequency data to an array of hashes - one for each sample point:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;curTime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sampleRate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sampleRate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;analyser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getByteFrequencyData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;freqs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;curTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;freqs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once the entire audio input has been analyzed, this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; array forms the basis of the visualization. &lt;a href=&quot;http://d3js.org/&quot;&gt;D3&lt;/a&gt; is used to display this data. Due to the density of the dataset, I opted to use canvas to handle the main display, with SVG used for the axes and other visuals.&lt;/p&gt;

&lt;p&gt;So, if nothing else, this visualization might be a good example of &lt;strong&gt;combining SVG and canvas&lt;/strong&gt; for a nice one-two punch!&lt;/p&gt;

&lt;p&gt;The visualization code is pretty simple. After some cleanup, the data array is drawn in the canvas using a loop:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;Spectrogram&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;svg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.x.axis&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xAxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;svg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.y.axis&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;yAxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;visContext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.vis_canvas&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;2d&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// clear canvas to prepare for new draw&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;visContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clearRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;yScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getBinFrequency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;// draw to canvas&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;visContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fillStyle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;visContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fillRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dotWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dotHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As shown in the previous code snippet, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d.key&lt;/code&gt; is the time point being sampled. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d.values&lt;/code&gt; is the actual frequency data. Each value in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d.values&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt; is plotted on the graph - its numerical value dictating its fill color.&lt;/p&gt;

&lt;p&gt;For a 4 second audio clip (with a sample rate of 44.1 kHz), processing each 512 frames, you get around 358,000 data points to visualize. You can bump the processing down to every 256 frames to get 716,800 if you want - but things get a bit lethargic when updating the visualization. Still, that’s a lot of points to look at!&lt;/p&gt;

&lt;h2 id=&quot;future-work&quot;&gt;Future Work&lt;/h2&gt;

&lt;p&gt;Right now SpectrogramJS is a bit of a proof of concept. A lot more could go into making it more interactive, add features, and clean up the horrendous code.&lt;/p&gt;

&lt;p&gt;If you think you might want to try using SpectrogramJS out - and have suggestions or need improvements, &lt;a href=&quot;https://github.com/vlandham/spectrogramJS/issues&quot;&gt;let me know!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So get out there and start visualizing sounds in your browser today!&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/sparrow.png&quot; alt=&quot;Sparrow&quot; style=&quot;&quot; /&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Mapping Seattle - Streets</title>
   <link href="http://vallandingham.me/mapping_seattle_streets.html"/>
   <updated>2013-10-18T00:00:00+00:00</updated>
   <id>http://vallandingham.me/mapping_seattle_streets</id>
   <content type="html">&lt;p&gt;Recently, I’ve up-rooted my family and transplanted from Kansas City, MO to Seattle, WA. This represents the first major venture out of the Midwest for my wife, dauther, and myself. Its exciting and scary and fun and difficult.&lt;/p&gt;

&lt;p&gt;To begin to learn the city, I’ve started making basic maps - with the attempt to highlight different aspects or views of how things are arranged and where things are.&lt;/p&gt;

&lt;p&gt;My first set attempts to take a very zoomed-out look at the streets.&lt;/p&gt;

&lt;p&gt;Here are the streets of Seattle.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/seattle/small/seattle_roads_small.png&quot; alt=&quot;Seattle Streets&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Not too exciting, but this provides a base line for those unacquainted with the lands up here.&lt;/p&gt;

&lt;p&gt;Now on to my actual maps!&lt;/p&gt;

&lt;p&gt;First, we have all the bus routes and other public transportation.&lt;/p&gt;

&lt;p&gt;Click on the image to get to a super-big &lt;em&gt;png&lt;/em&gt; version. I’ll try to work on vector-based versions as well, but my machine was having problems with that.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/images/seattle/seattle_public_transportation_big.png&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/seattle/small/seattle_public_transport_small.png&quot; alt=&quot;Seattle Public Transportation&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;From this, we can guess at where the downtown is located - the dense ball of paths there near the sound. We can also see that the routes tend to emanate from this downtown hub and move North and South from the city. The little loops at the ends of the routes indicate where the bus turns around - the edges of the transportation network.&lt;/p&gt;

&lt;p&gt;As a bonus, we get to see some of the ferry routes that arc away from the city’s center over to the islands of the Olympic Peninsula.&lt;/p&gt;

&lt;p&gt;The rest of these maps focus on interesting features of how streets are named here. First, as you drive around, you notice almost all the streets have a direction as part of their name. The direction is in front of the name for streets that run East / West ( &lt;em&gt;West Thurman Street&lt;/em&gt; ) and at the end of the name for Streets that run North / South ( &lt;em&gt;13th Avenue West&lt;/em&gt; ).&lt;/p&gt;

&lt;p&gt;I wanted to find out where the boundaries of these directions were. Are all the West streets in one location, or scattered around? What section(s) of Seattle are ‘North’ or ‘Northwest’? These are some of the questions I had. So, (instead of researching this question) I decided to make a map! Here, the color of the streets based on their direction.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/images/seattle/seattle_directional_big.png&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/seattle/small/seattle_directional_small.png&quot; alt=&quot;Seattle Public Transportation&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;I am still pondering the color choices, but right now I am trying to use the color wheel to mirror the compass. Red for North, blue for south, and so on.&lt;/p&gt;

&lt;p&gt;In any case, you can see that the directional streets of Seattle are highly compartmentalized. There are hard cut-offs that look to be fairly well maintained. Also, all of downtown is exempt from this directional practice (gray means no direction on the name).&lt;/p&gt;

&lt;p&gt;The other odd thing about Seattle streets (at least odd for me - in my limited exposure to the world) is that there are numbered streets that run both North / South as well as East / West. This is one reason why that front / back direction is important.&lt;/p&gt;

&lt;p&gt;What wasn’t clear to me was where the numbered streets start and in what direction they increase. So, here are some maps that try to answer these questions.&lt;/p&gt;

&lt;p&gt;First, East/West streets. The gray streets are numbered streets with a direction in their name. Lower numbered streets are less dark. Higher numbered streets are more dark. Orange streets are those East/West streets that have a direction, but are not number streets.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/images/seattle/seattle_east_west_big.png&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/seattle/small/seattle_east_west_small.png&quot; alt=&quot;Seattle East West&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;The image itself needs a legend, but hopefully the pattern is clear from the explanation above. First, the numbers don’t start till you are fairly far away from the city center (only orange in the middle). And, the first numbers up North start at 50 or so - and not 1.&lt;/p&gt;

&lt;p&gt;Secondly, numbers increment in both directions. Strange indeed!&lt;/p&gt;

&lt;p&gt;Here is the same for North/South streets.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/images/seattle/seattle_north_south_big.png&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/seattle/small/seattle_north_south_small.png&quot; alt=&quot;Seattle North South&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;Same pattern. They increase in both directions.&lt;/p&gt;

&lt;p&gt;With these maps, I’m at least getting an overall picture of how streets are arranged in my new town. Hopefully they might be interesting to you too!&lt;/p&gt;

&lt;p&gt;Bonus: parks and greenspaces of Seattle&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/images/seattle/seattle_parks_big.png&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/seattle/small/seattle_parks_small.png&quot; alt=&quot;Seattle Parks&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;Apparently, all those boxes on the upper Western coast are Discovery Park &lt;a href=&quot;http://en.wikipedia.org/wiki/Tidelands&quot;&gt;tidelands&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Maps were created using the ever wonderful &lt;a href=&quot;https://www.mapbox.com/tilemill/&quot;&gt;TileMill&lt;/a&gt; . I was exporting super large png files, so the street widths were jacked way up, which makes some areas look a little messy. Data comes from the infinitely useful &lt;a href=&quot;http://metro.teczno.com/&quot;&gt;Metro Extracts&lt;/a&gt; . Park data comes from the city of Seattle.&lt;/p&gt;

&lt;p&gt;Some &lt;a href=&quot;https://gist.github.com/vlandham/7051466&quot;&gt;very basic processing&lt;/a&gt; of the road shapefiles was done using python with &lt;a href=&quot;https://pypi.python.org/pypi/Fiona&quot;&gt;Fiona&lt;/a&gt; to help with the parsing. I definitely want to take advantage of &lt;a href=&quot;http://macwright.org/2012/10/31/gis-with-python-shapely-fiona.html&quot;&gt;shapely&lt;/a&gt; in the near future.&lt;/p&gt;

&lt;p&gt;I also want to start layering data from other sources onto these base road maps. Foursquare and Yelp data are on my radar - as well as &lt;a href=&quot;http://flowingdata.com/2013/09/12/working-with-line-maps-the-google-places-api-and-r/&quot;&gt;Google Places&lt;/a&gt; .&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Abusing The Force Talk</title>
   <link href="http://vallandingham.me/abusing_the_force.html"/>
   <updated>2013-06-07T00:00:00+00:00</updated>
   <id>http://vallandingham.me/abusing_the_force</id>
   <content type="html">&lt;p&gt;I was very fortunate to be able to speak at the first &lt;a href=&quot;http://openvisconf.com/&quot;&gt;OpenVis Conf&lt;/a&gt; in Boston in April 2013.&lt;/p&gt;

&lt;p&gt;The speakers were wonderful. The &lt;a href=&quot;http://bocoup.com/&quot;&gt;organizers&lt;/a&gt; were graceful. The venue was delightful.&lt;/p&gt;

&lt;h2 id=&quot;video&quot;&gt;Video&lt;/h2&gt;

&lt;p&gt;The talk was recorded, and can be found on &lt;a href=&quot;https://www.youtube.com/watch?v=Mucmb33711A&quot;&gt;Youtube&lt;/a&gt;:&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/Mucmb33711A&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;or &lt;a href=&quot;https://openvisconf.com/2013/&quot;&gt;the archived OpenVis 2013 Site&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;slides&quot;&gt;Slides&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/force_talk/#0&quot;&gt;Here are my slides for Abusing the Force&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the arrow keys on your keyboard to navigate. Each slide is its own html page. The &lt;a href=&quot;https://github.com/vlandham/force_talk&quot;&gt;source is all on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also put the slides on speaker deck for easy viewing:&lt;/p&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;e9bb8300a1ec013092ef0af45ce6d40d&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;
&lt;/script&gt;

&lt;p&gt;It was a great time, and again, I feel very honored and humbled to have been part of OpenVis Conf.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Abstract Maps Talk at CityCampKC 2013</title>
   <link href="http://vallandingham.me/city_camp_abstract_maps_notes.html"/>
   <updated>2013-04-21T00:00:00+00:00</updated>
   <id>http://vallandingham.me/city_camp_abstract_maps_notes</id>
   <content type="html">&lt;p&gt;I was fortunate to be part of the 2013 &lt;a href=&quot;http://citycampkc.org/&quot;&gt;CityCampKC&lt;/a&gt; conference that occured 4/20 at the lovely &lt;a href=&quot;http://www.kauffman.org/about-foundation/the-kauffman-conference-center.aspx&quot;&gt;Kauffman Foundation Conference Center&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This one day &lt;em&gt;unconference&lt;/em&gt; focuses on bringing together people from all walks of life under the banner of local community and government improvement. While a majority of the attendees appeared to be connected to the tech and startup scenes in Kansas City, I also got a chance to meet government officials, librarians, and artists from the community. The variety of people was great, with the caveat that trying to create a talk for this kind of group was difficult.&lt;/p&gt;

&lt;p&gt;I wanted to include a bit of visualization into the mix, so decided to give a talk in the afternoon sessions. The title of my talk was “Abstract Maps for a Powerful Impact”. The premise of this talk is that while maps are an extremely potent way to tell a story with data, the ubiquitous use of Google Maps, what I would call the ‘default presets’ of online mapping, can dilute your data driven story.&lt;/p&gt;

&lt;p&gt;So, I attempt to provide an overview of some alternatives to Google Maps, and to traditional maps in general, with applications to local data. I cover &lt;a href=&quot;http://vallandingham.me/kansas_city_streets_map_with_tilemill.html&quot;&gt;reductionist&lt;/a&gt; data/art techniques, &lt;a href=&quot;http://maps.stamen.com&quot;&gt;Stamen Maps&lt;/a&gt;, cartograms, time-scale maps, and my own &lt;a href=&quot;http://vallandingham.me/racial_divide/&quot;&gt;racial divide&lt;/a&gt; map.&lt;/p&gt;

&lt;p&gt;I tried to show &lt;em&gt;remixable&lt;/em&gt; examples of what could be used at a local level, as well as some iterations on failure. For example, my failed attempts to use &lt;a href=&quot;http://bl.ocks.org/mbostock/4055892&quot;&gt;dorling cartograms&lt;/a&gt; to display census tract data.&lt;/p&gt;

&lt;p&gt;You can find the original talk here:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/abstract_map_talk/#0&quot;&gt;Abstract Maps for Powerful Impact&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And I put it on SpeakerDeck - just for the fun of it:&lt;/p&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;a8dd33008ca00130b2101231381d4b42&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;
&lt;/script&gt;

&lt;p&gt;It was a great chance to meet some new people. And fun to attempt to create some material around a topic that I really enjoy: Maps! I felt I went a little too &lt;em&gt;lecturey&lt;/em&gt;, not quite hitting the right &lt;a href=&quot;http://www.hilarymason.com/speaking/speaking-entertain-dont-teach/&quot;&gt;entertain/educate&lt;/a&gt; ratio. But you might enjoy!&lt;/p&gt;

&lt;p&gt;Thanks to the CityCampKC organizers, &lt;a href=&quot;http://neighbor.ly/&quot;&gt;Neighbor.ly&lt;/a&gt;, &lt;a href=&quot;http://www.singlewingcreative.com/&quot;&gt;SingleWing&lt;/a&gt;, and everyone else involved in this great event.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>VisKC for KC based Visualizations</title>
   <link href="http://vallandingham.me/introducing_viskc.html"/>
   <updated>2013-04-10T00:00:00+00:00</updated>
   <id>http://vallandingham.me/introducing_viskc</id>
   <content type="html">&lt;p&gt;As I have been busy &lt;a href=&quot;http://flowingdata.com/2012/08/02/how-to-make-an-interactive-network-visualization/&quot;&gt;creating&lt;/a&gt; &lt;a href=&quot;http://flowingdata.com/2013/01/17/how-to-animate-transitions-between-multiple-charts/&quot;&gt;tutorials&lt;/a&gt; for FlowingData, I haven’t updated this site in a while.&lt;/p&gt;

&lt;p&gt;I wanted to point out a new fledgling project I’ve started: &lt;a href=&quot;http://viskc.com/&quot;&gt;VisKC.com&lt;/a&gt; - an aggregation site for Kansas City centric data visualizations.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://viskc.com/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/viskc.png&quot; alt=&quot;visKC logo&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;With this site I’d like to highlight interesting maps, visualizations, as well as data that focus on the Kansas City Metro area. Right now its mostly maps (as expected) and some data. I hope to update about once a week.&lt;/p&gt;

&lt;p&gt;In the future, I’d like to use it as a way to showcase some of my own KC based visualizations.&lt;/p&gt;

&lt;p&gt;So, if you get a hankering for some local Data Vis, come on down to &lt;a href=&quot;http://viskc.com/&quot;&gt;VisKC.com&lt;/a&gt; !&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Animate Transitions Between Charts (FlowingData)</title>
   <link href="http://vallandingham.me/transitions_between_multiple_charts.html"/>
   <updated>2013-01-17T00:00:00+00:00</updated>
   <id>http://vallandingham.me/transitions_between_multiple_charts</id>
   <content type="html">&lt;p&gt;Check out my &lt;a href=&quot;http://flowingdata.com/2013/01/17/how-to-animate-transitions-between-multiple-charts/&quot;&gt;tutorial on FlowingData&lt;/a&gt; and learn how you can use D3.js to transition between different chart types with nifty cool animations!&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://flowingdata.com/2013/01/17/how-to-animate-transitions-between-multiple-charts/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/flowingdata_animated_chart.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Small Multiples with Details on Demand</title>
   <link href="http://vallandingham.me/small_multiples_with_details.html"/>
   <updated>2012-12-17T00:00:00+00:00</updated>
   <id>http://vallandingham.me/small_multiples_with_details</id>
   <content type="html">&lt;p&gt;Small multiples are a great way to show changes in data. By lining up multiple visualizations, they effectively allow for direct comparisons to be made with little effort. This is in contrast to potential alternatives such as video or animation, which force the observer to remember previous shots of the visualization to perform the same comparisons.&lt;/p&gt;

&lt;p&gt;But some times the &lt;em&gt;small&lt;/em&gt; in small multiples can be limiting. It can be difficult to cram in relevant annotations, scales or other data that should be in your data visualization to help explain your point. You want to use small multiples because Tufte says they’re &lt;a href=&quot;http://www.marquis-kyle.com.au/mt/000034.htm&quot;&gt;the best&lt;/a&gt; , but you also don’t want your visualization to end up on &lt;a href=&quot;http://junkcharts.typepad.com/&quot;&gt;Junk Charts&lt;/a&gt; because you splattered clutter everywhere. Is there any hope?&lt;/p&gt;

&lt;h2 id=&quot;a-manifest-solution&quot;&gt;A Manifest Solution&lt;/h2&gt;

&lt;p&gt;Recently, &lt;a href=&quot;https://twitter.com/poezn&quot;&gt;Michael Porath&lt;/a&gt; provided an interesting graphic that I think includes an elegant solution to address the needs of the small but detailed visualization. I’ll call this method: &lt;strong&gt;Small Multiples with Details on Demand&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;http://michaelporath.com/projects/manifest-destiny/#overview&quot;&gt;Manifest Destiny&lt;/a&gt; , we see the story of how the United States came to be in a series of small multiples. Its a great piece, and the feature that I wanted to learn more about was the smooth looking transitions that occur when a user clicks on a map. You get a nice zoom effect that lets you know where the map came from, then details and more exploration in this single map. Returning back to the small multiples provides, again, a nice zoom to re-orient the user and allow them to continue to explore.&lt;/p&gt;

&lt;p&gt;In this blog post we will look at a way to implement this effect using &lt;a href=&quot;http://d3js.org/&quot;&gt;D3.js&lt;/a&gt; and jQuery.&lt;/p&gt;

&lt;h2 id=&quot;c02-emitted-over-the-years&quot;&gt;C02 Emitted Over the Years&lt;/h2&gt;

&lt;p&gt;To isolate and explain this functionality, I’ve created a small multiple visualization of CO2 emissions that incorporates much of this functionality. &lt;a href=&quot;http://vallandingham.me/co2_small_multiple/&quot;&gt;Check it out&lt;/a&gt; by clicking the image below.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/co2_small_multiple/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/co2_preview.png&quot; alt=&quot;small multiples demo&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/vlandham/co2_small_multiple&quot;&gt;code is available on github&lt;/a&gt; for downloading and remixing - so you can start on your own awesome interactive small multiple today!&lt;/p&gt;

&lt;p&gt;C02 emissions for the current leading CO2 producers are displayed for each year between 1961 and 2008. But the top polluters now weren’t always the top polluters back then. We see the steady increase in emissions in China. We see Japan struggle to maintain lower emissions in the 80’s and 90’s. We see the decadent United States, boldly and consistently dioxiding the world - especially when compared to all of the European Union.&lt;/p&gt;

&lt;p&gt;The details on demand element of the visualization is demonstrated when you click on a plot. Each bar chart gets a zoomed in &lt;em&gt;detail view&lt;/em&gt;, providing more details about that year. In the example, the detail view is pretty simple, but the idea is that more complex annotations and interactions can occur here to provide more insights into the data without compromising the small multiples view.&lt;/p&gt;

&lt;p&gt;Ready to learn how to create one on your own? Let’s get started!&lt;/p&gt;

&lt;h2 id=&quot;above-the-smog-an-overview-of-the-implementation&quot;&gt;Above the Smog: An Overview of the Implementation&lt;/h2&gt;

&lt;p&gt;The general idea for implementing this method isn’t too tricky:&lt;/p&gt;

&lt;p&gt;Each chart in the small multiples view is contained &lt;strong&gt;in its own&lt;/strong&gt; div and its own SVG element. 48 years means 48 SVGs on the page.&lt;/p&gt;

&lt;p&gt;The detail view is created in a &lt;strong&gt;separate SVG element&lt;/strong&gt; that spans the entire display area. The elements making up the detail view start out hidden.&lt;/p&gt;

&lt;p&gt;When a chart is clicked, the small multiple version is drawn in the detail view so that it &lt;strong&gt;covers up&lt;/strong&gt; the original below it. Additional annotations are then added to the detail view version of the graphic.&lt;/p&gt;

&lt;p&gt;Finally, D3 transitions are used to zoom the detailed chart front and center while CSS transitions are used to obscure the small multiples in the background. Clicking on the detail view essentially undos the process: a transition pulls the detailed chart back to its origin ending with the detail view being re-hidden.&lt;/p&gt;

&lt;p&gt;Now that we have the stratospheric perspective, let’s hit a few of the more tricky details. We’ll start with some details on the underlying html and CSS - but don’t worry! We will take a hard look at the visualization implementation too.&lt;/p&gt;

&lt;h2 id=&quot;building-our-smog-factory-proper-positioning-of-dom-elements&quot;&gt;Building our Smog Factory: Proper Positioning of DOM Elements&lt;/h2&gt;

&lt;p&gt;To make this look good, it is important to get all the elements on the page positioned correctly. We have a few things to worry about: the positioning of the small multiple graphs, the detail view overlay covering the current viewing area, and a clean transition between small multiple and detail view.&lt;/p&gt;

&lt;p&gt;Here is the overall structure of the html that will hold both the small multiple SVGs as well as the detail view:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vis&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;previews&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;detail&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;detail_panel&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;svg&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;800&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;800&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;g&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;detail_view&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/g&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- end #detail_panel --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- end #detail --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- end #vis --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- end #main --&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#previews&lt;/code&gt; div is where each of the charts in the small multiple view will be created. It is currently empty as will generate these divs dynamically using D3.&lt;/p&gt;

&lt;p&gt;The detail view is a bit more complicated. The top &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#detail&lt;/code&gt; div will serve to overlay the entire view. It starts hidden so the entire detail view is not visible initially.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#detail_panel&lt;/code&gt; div will be used to center the detail view SVG so that it sits on top of the small multiples view.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#detail_panel&lt;/code&gt; we prepare a svg element with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#detail_view&lt;/code&gt; group. This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt; node is where the detail view visualization will be drawn.&lt;/p&gt;

&lt;p&gt;On the CSS side, there are two topics I want to hit. First, we need to get the position of the detail view figured out.&lt;/p&gt;

&lt;p&gt;In our example, as in the original visualization, the header and footer are &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/CSS/position#Fixed_positioning&quot;&gt;fixed&lt;/a&gt; so that they stay visible on screen as the rest of the page is scrolled. This means we also want our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#detail&lt;/code&gt; fixed and set below our header. Here’s the CSS for the most-outer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#detail&lt;/code&gt; div:&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;#detail&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fixed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;128px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see I’m also using &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/CSS/color_value#rgba()&quot;&gt;rgba&lt;/a&gt; CSS3 to make the background semi-transparent.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;&quot;&gt;rest of the stylesheet&lt;/a&gt; for details on positioning of other components.&lt;/p&gt;

&lt;p&gt;Now, let’s look at the nice CSS transition used to transition between the two views.&lt;/p&gt;

&lt;p&gt;The MDN has a nice &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_transitions&quot;&gt;tutorial on CSS transistions&lt;/a&gt; - so I won’t go into too much detail, but I wanted to look at the how this technology is used for the subtle background effects here.&lt;/p&gt;

&lt;p&gt;The transition is controlled by two classes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.hidden&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.visible&lt;/code&gt;. Here’s what they look like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.hidden&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;500ms&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;-webkit-transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;500ms&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;-moz-transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;500ms&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.visible&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;500ms&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;-webkit-transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;500ms&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;-moz-transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;500ms&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We will apply the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.hidden&lt;/code&gt; class to the small multiple view when the detail view comes up. Instead of immediately disappearing, the CSS transition allows us to apply our opacity over time. When this class is applied to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;, it will gradually disappear over half a second.&lt;/p&gt;

&lt;p&gt;Likewise, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.visible&lt;/code&gt; class will make the elements reappear gradually over time. A nice subtle effect with just a bit of CSS.&lt;/p&gt;

&lt;h2 id=&quot;year-by-year-building-the-small-multiple-view&quot;&gt;Year by Year: Building the Small Multiple View&lt;/h2&gt;

&lt;p&gt;Ok, enough with the layout, let’s get to the visualization! The &lt;a href=&quot;https://github.com/vlandham/co2_small_multiple/blob/gh-pages/coffee/vis.coffee&quot;&gt;full coffeescript code is here&lt;/a&gt; - and below we will walk through some of the important parts.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Coffeescript Implementation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This visualization is written in &lt;a href=&quot;http://coffeescript.org/&quot;&gt;CoffeeScript&lt;/a&gt; . I just enjoy it so much more than Javascript, I couldn’t bear to change. I invite you to take a 20 minute look at CoffeeScript - if you aren’t already familiar. It is a really simple language and really allows us to focus on the implementation details - rather then syntax.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;First up, we need to create a separate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; and SVG element for each of the charts in the small multiple. We will do this by using D3’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; method to bind the data to an &lt;a href=&quot;http://bost.ocks.org/mike/join/&quot;&gt;empty selection&lt;/a&gt; and then appending the needed elements.&lt;/p&gt;

&lt;p&gt;To better understand what the code is doing, here is what the data looks like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;year&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1961&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;values&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;China&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;552066.85&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;percent_world&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.059&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;USA&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;year&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1962&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So data is an array of objects. Each object represents a single year’s data. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;values&lt;/code&gt; array of the object stores the CO2 values for each country for that year.&lt;/p&gt;

&lt;p&gt;And here’s the code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt; &lt;span class=&quot;c1&quot;&gt;# bind data to svg elements so there will be a svg for # each year&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;pre&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#previews&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.preview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# create the svg elements&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;pre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;preview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;svgs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;svg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# create a group for displaying the bar chart in&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;previews&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;svgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;g&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are &lt;strong&gt;no&lt;/strong&gt; div’s with class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.preview&lt;/code&gt; initially, so when we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enter()&lt;/code&gt; this will create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; for each year. Inside each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;, we append a SVG element. Both elements share the same width and height. We will use the position information of the preview div’s to figure out where to start the detail view transition. Inside the SVG, we create a group element to draw the chart in.&lt;/p&gt;

&lt;p&gt;Next let’s draw the actual charts. I wanted to use the same code to draw the basic chart in both the small multiples view and the detail view. To make this happen, I encapsulated the code in a function called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawChart()&lt;/code&gt; and then execute this function to draw all the small multiple charts by calling it through D3’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;each()&lt;/code&gt; function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt; &lt;span class=&quot;c1&quot;&gt;# draw the graphs for each data element.&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;previews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;drawChart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;each()&lt;/code&gt; function will execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawChart()&lt;/code&gt; for &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Selections#wiki-each&quot;&gt;each of the SVG elements&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;This drawing function will be passed to arguments: the data associated with the element, and its index in the data array. Additionally, inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawChart()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; will be the current DOM element - meaning for us the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt; inside each SVG element that we want to draw the chart in.&lt;/p&gt;

&lt;p&gt;So what does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawChart()&lt;/code&gt; look like?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;drawChart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# the 'this' element is the group # element which the bar chart will # live in&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;graphWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;graphHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;background&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# create the bars&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;g&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;graphHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yPadding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;rangeBand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;  &lt;span class=&quot;nx&quot;&gt;yScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fill&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;colorScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mouseover&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showAnnotation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mouseout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hideAnnotation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# add the year title&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text-anchor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;middle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;graphWidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.3em&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is pretty standard D3 for chart creation, based on &lt;a href=&quot;http://bl.ocks.org/3885304&quot;&gt;existing bar chart examples&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Again, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt; to draw in, so we select it first and then append elements to this element.&lt;/p&gt;

&lt;p&gt;Our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; input argument is the data bound to this element - meaning the object containing data from a particular year. For each year, we want to create a bar for each Object in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;values&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;As described &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Selections#wiki-data&quot;&gt;in the documentation&lt;/a&gt; , we can pass a function into data to return an array inside the parent data. This is why we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.data((d) -&amp;gt; d.values)&lt;/code&gt; when creating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bar&lt;/code&gt; rects - to bind a new rectangle for each of the country objects in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;values&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As part of the bar creation, we also assign &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseover&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseout&lt;/code&gt; functions. But if you &lt;a href=&quot;http://vallandingham.me/co2_small_multiple/&quot;&gt;interact with the demo&lt;/a&gt; , you will see that nothing happens when you mouse over bars while you are in the small multiples view.&lt;/p&gt;

&lt;p&gt;So what’s going on?&lt;/p&gt;

&lt;p&gt;After executing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawChart()&lt;/code&gt;, we perform &lt;em&gt;one more step&lt;/em&gt; with our small multiple bar charts:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;previews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;graphWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;graphHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;mouse_preview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This overlays a transparent rectangle on top of each small multiple. When this rect is clicked, it will execute the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;showDetail&lt;/code&gt; function. It also prevents mouse interactions from reaching the bars underneath.&lt;/p&gt;

&lt;p&gt;With relatively little code, we can make a nice small multiples display without duplicating code.&lt;/p&gt;

&lt;h2 id=&quot;the-dirty-details-building-the-detail-view&quot;&gt;The Dirty Details: Building the Detail View&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;But we’re not done yet!&lt;/strong&gt; Let’s investigate what happens when a small multiple is clicked - by looking at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;showDetail()&lt;/code&gt;. First, the creation and drawing code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;showDetail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# switch the css on which divs are hidden&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;toggleHidden&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;detailView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#detail_view&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;detailView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'.main'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# bind the single element to be detailed to the&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# detail view's group&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;detailG&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;detailView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'g'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# create a new group to display the graph in&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;detailG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;g&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# draw graph just like in the initial creation&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# of the small multiples&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;drawChart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# add details specific to the detail view&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;drawDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toggleHidden(true)&lt;/code&gt; swaps the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.hidden&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.visible&lt;/code&gt; CSS classes we looked at earlier, starting the transition to fade out the background and fade in the detail view.&lt;/p&gt;

&lt;p&gt;Then we create a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt; element inside our detail view’s SVG with the class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.main&lt;/code&gt;. We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data([d])&lt;/code&gt; to bind the data as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; in this function refers to a single year’s data object. We want to use all the D3 functions - even when dealing with a single object - so binding to an array containing just this element is a good way to do that.&lt;/p&gt;

&lt;p&gt;We use the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawChart()&lt;/code&gt; function to create a bar chart in the detail view SVG. This chart will be initially identical to one of the charts in the small multiple view. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawDetails()&lt;/code&gt; function adds annotations to the detail view chart to make it, well… more &lt;em&gt;detailed&lt;/em&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;drawDetails&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# like in 'drawChart', 'this' # is the group element to draw # the details in&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# add names under bars&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text-anchor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;middle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;graphHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yPadding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.3em&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;rangeBand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;font-size&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# add values above bars&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;No Data&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;shortenNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text-anchor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;middle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;graphHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yPadding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-0.3em&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.1em&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;rangeBand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;font-size&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can see that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; variables all behave the same as in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawChart()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here we add text for displaying the country name and values associated with each bar.&lt;/p&gt;

&lt;p&gt;In this simple example, we are able to re-use most of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawChart()&lt;/code&gt; code and simply append more details with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawDetails()&lt;/code&gt;. If you were making a more extreme detail view, you might not be able create it in such an elegant manner.&lt;/p&gt;

&lt;p&gt;An important thing to remember is that initially the detail view is the same small size as the bar charts in the small multiples.&lt;/p&gt;

&lt;p&gt;But now its time for the &lt;strong&gt;big finish&lt;/strong&gt; - like a beautify butterfly the detail view will be &lt;strong&gt;transformed&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;I’ve left most of my comments in the code snippet - even though it takes away some of the suspense.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt; &lt;span class=&quot;c1&quot;&gt;# getPosition is a helper function to # return the relative location of the graph # to be viewed in the detail view&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getPosition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# scrollTop returns the number of pixels&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# hidden on the top of the window because of&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# the window being scrolled down&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;scrollTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# first we move our (small) detail chart to be positioned over&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# its preview version&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'transform'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;translate(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# then we use a transition to center the detailed graph and scale it&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# up to be bigger&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'transform'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;translate(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;) scale(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scaleFactor&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First we figure out where the small multiple that was clicked is currently in the browser’s window. Then we transition the detail view’s chart to this location immediately.&lt;/p&gt;

&lt;p&gt;Finally, we &lt;a href=&quot;http://blog.visual.ly/creating-animations-and-transitions-with-d3-js/&quot;&gt;transition&lt;/a&gt; the entire SVG group to create the zoom effect.&lt;/p&gt;

&lt;p&gt;We provide both a translation position and a scaling factor. D3 does all the rest of the work. It is able to recognize numbers inside strings and automatically tween between the starting location and the final destination.&lt;/p&gt;

&lt;p&gt;The effect is simple, but I think very effective. The intuitive and meaningful nature of the animation maintain &lt;a href=&quot;http://bost.ocks.org/mike/constancy/#when-constancy-matter&quot;&gt;constancy&lt;/a&gt; and look good to boot.&lt;/p&gt;

&lt;p&gt;Again, the &lt;a href=&quot;https://github.com/vlandham/co2_small_multiple&quot;&gt;code is available on github&lt;/a&gt; . Please let me know what small multiples and/or details on demand you create!&lt;/p&gt;

&lt;p&gt;And thanks again to &lt;a href=&quot;https://twitter.com/poezn&quot;&gt;Michael Porath&lt;/a&gt; for the great and inspiring Manifest Destiny visualization.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Building a Bubble Cloud</title>
   <link href="http://vallandingham.me/building_a_bubble_cloud.html"/>
   <updated>2012-09-10T00:00:00+00:00</updated>
   <id>http://vallandingham.me/building_a_bubble_cloud</id>
   <content type="html">&lt;div class=&quot;alert alert-danger&quot;&gt;
  &lt;p&gt;This post is very old and no longer represents the current state of how to use D3 properly. You should check out my updated &lt;a href=&quot;http://vallandingham.me/bubble_charts_with_d3v4.html&quot;&gt;Creating Bubble Charts with D3v4&lt;/a&gt; instead!&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;For the 2012 Republican and Democratic national conventions, &lt;a href=&quot;http://bost.ocks.org/mike/&quot;&gt;Mike Bostock&lt;/a&gt; , &lt;a href=&quot;http://shancarter.com/&quot;&gt;Shan Carter&lt;/a&gt; , and &lt;a href=&quot;http://www.ericson.net/content/&quot;&gt;Matthew Ericson&lt;/a&gt; have created a series of visualizations highlighting the words being used in the speeches of both gatherings. These word-cloud-like word bubble clouds (what I’ll call &lt;em&gt;bubble clouds&lt;/em&gt;, unless you can think of a better name) serve as a great interface for looking at the differences in the two conventions and for browsing through quotes from the talks.&lt;/p&gt;

&lt;p&gt;Check them out here:&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;one-third column&quot;&gt;
    &lt;a href=&quot;http://www.nytimes.com/interactive/2012/08/28/us/politics/convention-word-counts.html&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/rep.png&quot; alt=&quot;republican image&quot; style=&quot;border:1px dotted #cccccc; padding-right:10px; float:left;&quot; /&gt;&lt;/a&gt;
  &lt;/div&gt;
  &lt;div class=&quot;one-third column&quot;&gt;
  &lt;a href=&quot;http://www.nytimes.com/interactive/2012/09/04/us/politics/democratic-convention-words.html&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/dem.png&quot; alt=&quot;democratic image&quot; style=&quot;border:1px dotted #cccccc; padding-right:10px; float:left;&quot; /&gt;&lt;/a&gt;
  &lt;/div&gt;
  &lt;div class=&quot;one-third column&quot;&gt;
  &lt;a href=&quot;http://www.nytimes.com/interactive/2012/09/06/us/politics/convention-word-counts.html&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/combo.png&quot; alt=&quot;combo image&quot; style=&quot;border:1px dotted #cccccc; float:left; clear:right;&quot; /&gt;&lt;/a&gt;
  &lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;While there is a lot that could be discussed about all the little things that contribute to the quality and polish of these visualizations, in this tutorial we will look at some of the implementation details that make them &lt;em&gt;tick&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;bubble-cloud-demo&quot;&gt;Bubble Cloud Demo&lt;/h2&gt;

&lt;p&gt;I’ve created a basic bubble cloud visualization that tries to replicate some of the functionality of the NYT version. Click on the &lt;a href=&quot;http://vallandingham.me/bubble_cloud/&quot;&gt;image below to see the demo&lt;/a&gt; .&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/bubble_cloud/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/bubble_cloud_preview.png&quot; alt=&quot;word bubble cloud demo&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;div class=&quot;clearfix&quot;&gt;
&lt;/div&gt;
&lt;p&gt;Try clicking on the bubbles, then try dragging them around. Change the source text with the drop down in the upper-left corner.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/vlandham/bubble_cloud&quot;&gt;source code is available for download&lt;/a&gt; and use in your own projects.&lt;/p&gt;

&lt;p&gt;This visualization uses D3’s force-directed layout, so if you aren’t familiar with that, you might check out my &lt;a href=&quot;http://vallandingham.me/bubble_charts_in_d3.html&quot;&gt;post on creating animated bubble charts&lt;/a&gt; , or the &lt;a href=&quot;http://flowingdata.com/2012/08/02/how-to-make-an-interactive-network-visualization/&quot;&gt;designing interactive network visualizations&lt;/a&gt; tutorial on Flowing Data.&lt;/p&gt;

&lt;p&gt;While I won’t be going over the basics of the force layout, hopefully there is still enough in this implementation to keep things interesting. The main topics I want to cover here are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The use of SVG and plain html components in the same visualization&lt;/li&gt;
  &lt;li&gt;Saving the state of the visualization using links&lt;/li&gt;
  &lt;li&gt;Creating a custom gravity effect&lt;/li&gt;
  &lt;li&gt;Creating a custom collision detection mechanism&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/bubble_cloud/blob/gh-pages/coffee/vis.coffee&quot;&gt;Here is all the CoffeeScript that makes this visualization&lt;/a&gt; in case you want to follow along in the actual code. Sorry in advanced to the CoffeeScript haters.&lt;/p&gt;

&lt;p&gt;Ready to get started? Let’s go!&lt;/p&gt;

&lt;h2 id=&quot;you-got-html-in-my-svg&quot;&gt;You got HTML in my SVG!&lt;/h2&gt;

&lt;p&gt;Typically when using &lt;a href=&quot;http://d3js.org/&quot;&gt;D3&lt;/a&gt; , the more advanced visualizations are made with SVG. In a previous tutorial, we &lt;a href=&quot;http://vallandingham.me/d3_without_svg.html&quot;&gt;dabbled in a SVG-less D3 world&lt;/a&gt; , but the trade-offs were steep.&lt;/p&gt;

&lt;p&gt;These bubble cloud visualizations actually combine SVG and Html elements elegantly! Specifically, the bubble elements themselves are circle’s inside of a SVG element, but the text on top of them is actually maintained in regular &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; ’s. As a bonus, both sets of visual elements are backed by the data, so there is very little code duplication or overhead using this structure.&lt;/p&gt;

&lt;p&gt;Why would you want this duality? My initial thought when I looked at the implementation was that this was for increased browser compatibility. I figured that in IE8 users might just see the html elements, but miss out on the bubble backgrounds.&lt;/p&gt;

&lt;p&gt;This turned out &lt;strong&gt;not to be the case&lt;/strong&gt;. Navigating to the site with an old browser just gets you a static picture. The interactive versions still require browsers with SVG support.&lt;/p&gt;

&lt;p&gt;My current guess for why this implementation route was chosen is because of how &lt;strong&gt;SVG deals with text wrapping&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Surprisingly, the 1.1 version of the SVG specification &lt;a href=&quot;http://stackoverflow.com/questions/4991171/auto-line-wrapping-in-svg-text&quot;&gt;does not deal with word wrapping&lt;/a&gt; . There are &lt;a href=&quot;http://stackoverflow.com/questions/3142007/how-to-either-determine-svg-text-box-width-or-force-line-breaks-after-x-chara&quot;&gt;some proposed&lt;/a&gt; &lt;a href=&quot;http://stackoverflow.com/questions/475804/svg-word-wrap-show-stopper&quot;&gt;workarounds&lt;/a&gt; , and the 1.2 spec includes the &lt;a href=&quot;http://www.w3.org/TR/SVGTiny12/text.html#TextAreaElement&quot;&gt;textArea&lt;/a&gt; element, which is supposed to solve this deficiency. But none of the solutions look particularly clean, dynamic, or without speed costs.&lt;/p&gt;

&lt;p&gt;So the words and phrases the visualizations that will be showing might be on multiple lines. SVG doesn’t support this natively, and it looks like there are some trade-offs with the SVG only workarounds. What should we do?&lt;/p&gt;

&lt;p&gt;Why not just implement this part in &lt;strong&gt;HTML&lt;/strong&gt;? This looks to be the path Mike et al. at the New York Times took.&lt;/p&gt;

&lt;p&gt;And this combo plater actually works out pretty well. To get started, here’s how we setup the elements that will hold the nodes and labels:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;      &lt;span class=&quot;c1&quot;&gt;# node will be used to group the bubbles&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;svgEnter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;g&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bubble-nodes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;transform&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;translate(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# label is the container div for all the labels that sit on top of&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# the bubbles&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# - remember that we are keeping the labels in plain html and&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;#  the bubbles in svg&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#bubble-labels&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bubble-labels&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; refers to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#vis&lt;/code&gt; div. For the labels, we add a container &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#bubble-labels&lt;/code&gt;. Adding the circles that make up the nodes for the visualization is stuff we have seen before, so lets focus on the labels. First we bind the same data we use to build up the nodes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bubble-label&lt;/code&gt; elements in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;label&lt;/code&gt; selection:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# updateLabels is more involved as we need to deal with getting the sizing&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# to work well with the font size&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;updateLabels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# as in updateNodes, we use idValue to define what the unique id for each data&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# point is&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.bubble-label&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;idValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So we can still use data bindings, just like in any other D3 visualization!&lt;/p&gt;

&lt;p&gt;Now we build up our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bubble-label&lt;/code&gt; ’s by entering our (currently empty) selection and appending an anchor and some divs:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;c1&quot;&gt;# labels are anchors with div's inside them&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# labelEnter holds our enter selection so it&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# is easier to append multiple elements to this selection&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;labelEnter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bubble-label&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;href&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;#&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;encodeURIComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;idValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;drag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;connectEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;labelEnter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bubble-label-name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;textValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;labelEnter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bubble-label-value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we can see that each label is an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; with two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; elements inside it. One to hold the word/phrase name, the other to hold the count. We will look at how these anchors work in the next section.&lt;/p&gt;

&lt;p&gt;The last thing we need to do when creating these labels is determine the size of the elements holding this text. We want the text to be able to spill out a bit on either size of the bubble, but also to wrap around if it gets too long. Let’s look at one way this can be done. Here’s the code used to style and position the text:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;c1&quot;&gt;# first set the font-size and cap the maximum width to enable word wrapping&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;font-size&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;px&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;px&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# now we need to adjust if the width set is too big for the text&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# do this using a temporary span&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;span&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;textValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBoundingClientRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# reset the width of the label to the actual width&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;px&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# compute 'dy' - the value to shift the text from the top&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBoundingClientRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s analyze this in more detail. As the comments say, we set our font size based on the same scale we are using to scale the bubbles. Good. Bigger bubbles will have bigger text. We also get &lt;strong&gt;word wrapping&lt;/strong&gt; for free by setting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width&lt;/code&gt; to an appropriate value.&lt;/p&gt;

&lt;p&gt;But if the text is actually too small for the bubble, it will skew to the left. The width will pad it out and make it not line up correctly with the bubble. So we need to find out if the bubble or the word-wrapped text is bigger.&lt;/p&gt;

&lt;p&gt;We can do this by adding the text to a temporary span element and grabbing its actual width using &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/DOM/element.getBoundingClientRect&quot;&gt;getBoundingClientRect&lt;/a&gt; . &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;each&lt;/code&gt; is used here so we can also set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dx&lt;/code&gt; property of our labels, which will be used when positioning them.&lt;/p&gt;

&lt;p&gt;With this corrected width known, we can reset our label’s width to account for smaller words.&lt;/p&gt;

&lt;p&gt;Finally, we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getBoundingClientRect&lt;/code&gt; again to get the amount to shift the label down.&lt;/p&gt;

&lt;p&gt;Its a bit confusing, but I think its a great solution to this issue - and now that its been worked out, we can all use it.&lt;/p&gt;

&lt;p&gt;To close off this label issue, here is how the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dx&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dy&lt;/code&gt; properties are used in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; function to position the labels:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;c1&quot;&gt;# As the labels are created in raw html and not svg, we need&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# to ensure we specify the 'px' for moving based on pixels&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;left&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;px&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;top&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;px&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And there you have it. A nice way to use SVG and Html together, keeping with the D3 paradigm of binding data and using the same data backend for both.&lt;/p&gt;

&lt;h2 id=&quot;a-way-to-save-state&quot;&gt;A Way to Save State&lt;/h2&gt;

&lt;p&gt;By &lt;em&gt;saving state&lt;/em&gt;, I mean being able to return to or share a particular view of a visualization. The way to do this in web-based interactive visualizations is by modifying the url so as to encode the current state of the visualization in the url itself.&lt;/p&gt;

&lt;p&gt;It’s an important detail, and one that is commonly missing from even professionally created visualizations. I liked Bryan Conner’s remark on this subject when discussing the &lt;a href=&quot;http://thewhyaxis.info/moneyball/&quot;&gt;Money Ball WSJ political donor visualization&lt;/a&gt; :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Having the ability to share a specific view as a link on Twitter or Facebook is definitely important and, as far as I’m concerned, should be standard for almost any contemporary visualization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With this bubble cloud implementation, we really only have to keep track of two variables: the text being viewed and the current word selected. I’ll focus on the word selected tracking, which we try to manage in a simple and elegant manner.&lt;/p&gt;

&lt;p&gt;Clicking a bubble causes an immediate change to the url. And it is this url change that serves as a signal to update the visualization. This keeps the code &lt;a href=&quot;http://www.youtube.com/watch?v=cLsaIXIob_I&quot;&gt;clean and neat&lt;/a&gt; . Let’s see how it works.&lt;/p&gt;

&lt;p&gt;The functionality depends on modifying the url’s &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/DOM/window.location&quot;&gt;hash section&lt;/a&gt; which is the text that follows the hash symbol (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt;). Here is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;click&lt;/code&gt; callback function, which is executed each time a bubble is clicked:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# changes clicked bubble by modifying url&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;click&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;encodeURIComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;idValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location.replace&lt;/code&gt; to kill the previous selection (if anything was selected before) and switch to the newly highlighted bubble. The use of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;replace&lt;/code&gt; function also means the history won’t be polluted with a bunch of versions of the same visualization.&lt;/p&gt;

&lt;p&gt;The hash component of the url is accessible via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location.hash&lt;/code&gt;. What’s more, we can register to be notified when this component of the url changes by using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange&quot;&gt;hashchange&lt;/a&gt; event. Combining these insights, the bubble cloud first hooks into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hashchange&lt;/code&gt; in the visualizations initialization function:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;      &lt;span class=&quot;c1&quot;&gt;# automatically call hashchange when the url has changed&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hashchange&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hashchange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then uses this event to trigger a change in the active bubble.&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# called when url after the # changes&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;hashchange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;decodeURIComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;updateActive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# activates new node&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;updateActive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;classed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bubble-selected&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;idValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# if no node is selected, id will be empty&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;h3&amp;gt;The word &amp;lt;span class=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;/span&amp;gt; is now active&amp;lt;/h3&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;h3&amp;gt;No word is active&amp;lt;/h3&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This decouples the event handling implementation from the visualization and would allow us to add more callbacks for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hashchange&lt;/code&gt; to modify other parts of the page if we wanted to. Here, we are just modifying a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;, but think of the possibilities!&lt;/p&gt;

&lt;p&gt;Of course you can use your own custom event to perform the same decoupling, but I think it is nice having state saving via url modification and user interaction changes wrapped up in this nice little package.&lt;/p&gt;

&lt;h2 id=&quot;spreading-gravity-thin&quot;&gt;Spreading Gravity Thin&lt;/h2&gt;

&lt;p&gt;In D3, the &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout#wiki-gravity&quot;&gt;gravity&lt;/a&gt; component of a force actually draws nodes towards the center of the force layout. It is useful to ensure your nodes don’t fly off the screen. But the default gravity implementation is symmetrical, meaning it pulls on a node’s vertical and horizontal positions equally.&lt;/p&gt;

&lt;p&gt;But what if you want a &lt;strong&gt;non-symmetrical gravity&lt;/strong&gt;? Say your visualization is wider then it is tall (like in this example) and you want nodes to spread out along the x axis a bit more? Well, then you can implement your own ‘gravity’ function to push your nodes around how you like!&lt;/p&gt;

&lt;p&gt;To get your own forces working on the nodes, we will call them each iteration of the force simulation by binding the force’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; event to a callback function:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;# The force variable is the force layout controlling the bubbles&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# here we disable gravity and charge as we implement custom versions&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# of gravity and collisions for this visualization&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;gravity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tick&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Every time the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; event is triggered, it will call our function, which happens to be called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt;. We also remove the built in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; forces by setting them to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;. We will implement both of these forces ourselves.&lt;/p&gt;

&lt;p&gt;Here is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# tick callback function will be executed for every&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# iteration of the force simulation&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# - moves force nodes towards their destinations&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# - deals with collisions of force nodes&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# - updates visual bubbles to reflect new force node locations&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;tick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;dampenedAlpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Most of the work is done by the gravity and collide&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# functions.&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;node&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gravity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dampenedAlpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;collide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jitter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;transform&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;translate(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# As the labels are created in raw html and not svg, we need&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# to ensure we specify the 'px' for moving based on pixels&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;left&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;px&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;top&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;px&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see for each node we are calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collide&lt;/code&gt; which perform all the work on our nodes. After which we update our node and label positions to their new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; coordinates. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collide&lt;/code&gt; will be in the next section, so let’s focus on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; now:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# custom gravity to skew the bubble placement&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;gravity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# start with the center of the display&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# use alpha to affect how much to push&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# towards the horizontal or vertical&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ay&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# return a function that will modify the&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# node's x and y values&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ax&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ay&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see how the only thing we really tweak is how much alpha affects the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; components of the gravitational pull.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; parameter comes from D3’s force layout and is the &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout#wiki-start&quot;&gt;cooling temperature for the layout simulation&lt;/a&gt; . &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; starts at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.1&lt;/code&gt; and decreases as the force simulation continues, getting to around &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.005&lt;/code&gt; before stopping.&lt;/p&gt;

&lt;p&gt;Here we are reducing the alpha value to be applied to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; movement by 8. When we multiple the movement towards the center by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ax&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ay&lt;/code&gt;, this makes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; movement stronger. Thus, while the nodes should remain centered vertically, they will be allowed to drift along the x axis.&lt;/p&gt;

&lt;p&gt;Redistributing nodes like this allows more content below it to be ‘above the fold’ without running the risk of cutting off the bottom of the bubbles.&lt;/p&gt;

&lt;h2 id=&quot;dont-burst-your-bubbles&quot;&gt;Don’t Burst Your Bubbles&lt;/h2&gt;

&lt;p&gt;As we saw in the &lt;a href=&quot;http://vallandingham.me/bubble_charts_in_d3.html&quot;&gt;bubble chart tutorial&lt;/a&gt; , a form of collision avoidance can be implemented in D3 by making the charge associated with each node a function of the size of the node. This provides a visually interesting, &lt;em&gt;organic&lt;/em&gt;, experience, where bubbles push on one another in an particle-like way.&lt;/p&gt;

&lt;p&gt;The bubbles in these word visualizations act in a subtly but significantly different manner. Here the nodes bounce off one another, maintaining a rigid parameter space around themselves. So how is this affect achieved in D3? By implementing a custom collision detection and avoidance algorithm!&lt;/p&gt;

&lt;p&gt;Its actually not as complicated as it might sound. Here is the code:&lt;/p&gt;

&lt;div class=&quot;language-coffeescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# custom collision function to prevent&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# nodes from touching.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;collide&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jitter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# return a function that modifies&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# the x and y of a node&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forEach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# check that we aren't comparing a node&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# with itself&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d2&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# use distance formula to find distance&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# between two nodes&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# find current minimum space between two nodes&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# using the forceR that was set to match the&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# visible radius of the nodes&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;minDistance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forceR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forceR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;collisionPadding&lt;/span&gt;

          &lt;span class=&quot;c1&quot;&gt;# if the current distance is less then the minimum&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;# allowed then we need to push both nodes away from one another&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;minDistance&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# scale the distance based on the jitter variable&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;minDistance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jitter&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# move our two nodes&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;moveX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;moveY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moveX&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moveY&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;d2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moveX&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;d2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;moveY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We compute the distance between each node pair and see if it is less then the minimum distance allowed by our visualization. If so, then we move the nodes away from one another. The fact that D3 stores the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; position of each node as part of the data associated with that node makes it easy to get the values required to perform these calculations.&lt;/p&gt;

&lt;p&gt;Notice the input variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jitter&lt;/code&gt;. What’s it do? We use it to help scale the distance that will be used to move the colliding nodes. Higher values will make this distance larger, smaller values will reduce it.&lt;/p&gt;

&lt;p&gt;I’ve connected the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jitter&lt;/code&gt; to a range control underneath the visualization. This lets you explore what the collisions look like when the nodes really start pushing each other hard. The default value, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.5&lt;/code&gt; visually seems to make the interactions look natural.&lt;/p&gt;

&lt;h3 id=&quot;the-quad-connection&quot;&gt;The Quad Connection&lt;/h3&gt;

&lt;p&gt;The implementation as shown above is a &lt;strong&gt;brute-force strategy&lt;/strong&gt;. All nodes are compared with all other nodes, regardless of how close they are in the visualization. While this works decently for a small number of nodes, it will start bogging down as the node count increases.&lt;/p&gt;

&lt;p&gt;If we had some rough-grained insight as to which nodes were nearest one another, we might be able to speed things up significantly by only performing these calculations for these nearby nodes.&lt;/p&gt;

&lt;p&gt;This is actually how the NYT version of the collision algorithm is implemented. How do they know which nodes are nearby? By using a &lt;a href=&quot;http://en.wikipedia.org/wiki/Quadtree&quot;&gt;Quadtree&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;A Quadtree is a tree-like data structure in which each internal node has four children (hence the name). You can use a Quadtree to partition up a two-dimensional space such that areas with more nodes will have more partitions. You can then visit the nodes in an efficient manner and stopped traversing once you have made it out of the quadrants that could affect the node in question.&lt;/p&gt;

&lt;p&gt;D3 has a sparsely documented &lt;a href=&quot;https://github.com/mbostock/d3/blob/master/src/geom/quadtree.js&quot;&gt;Quadtree&lt;/a&gt; implementation which is used in the force layout in this manner to make it fast. While this Quadtree implementation is a great option to have, and should be considered for collisions between many nodes, I think the brute-force version provides the same basic idea, without more technical overhead.&lt;/p&gt;

&lt;h2 id=&quot;your-own-bubble-cloud-in-the-sky&quot;&gt;Your Own Bubble Cloud in the Sky&lt;/h2&gt;

&lt;p&gt;That does it for this tutorial. Hopefully this provides a bit more insight into these great pieces from the New York Times (and hopefully they don’t mind me continuing to exploit their great pieces).&lt;/p&gt;

&lt;p&gt;Again, the &lt;a href=&quot;https://github.com/vlandham/bubble_cloud&quot;&gt;code is on github&lt;/a&gt; , so grab it and let your bubble clouds accumulate!&lt;/p&gt;

&lt;p&gt;Taking this to the next level would involve splitting the bubbles based on some variable, like the &lt;a href=&quot;http://www.nytimes.com/interactive/2012/09/06/us/politics/convention-word-counts.html&quot;&gt;dual convention version&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;For that, check out Mike’s great demonstration of &lt;a href=&quot;http://bl.ocks.org/3422480&quot;&gt;how they split the bubbles&lt;/a&gt; to get a sense of how to add this kind of visualization.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Interactive Networks Visualizations (FlowingData)</title>
   <link href="http://vallandingham.me/interactive_networks.html"/>
   <updated>2012-08-02T00:00:00+00:00</updated>
   <id>http://vallandingham.me/interactive_networks</id>
   <content type="html">&lt;p&gt;Check out my &lt;a href=&quot;http://flowingdata.com/2012/08/02/how-to-make-an-interactive-network-visualization/&quot;&gt;tutorial on FlowingData&lt;/a&gt; and learn how you can use D3.js to make some awesome interactive networks.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://flowingdata.com/2012/08/02/how-to-make-an-interactive-network-visualization/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/flowingdata_network.png&quot; alt=&quot;&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Steps for Building a Stepper Visualization</title>
   <link href="http://vallandingham.me/stepper_steps.html"/>
   <updated>2012-06-27T00:00:00+00:00</updated>
   <id>http://vallandingham.me/stepper_steps</id>
   <content type="html">&lt;p&gt;As the NYT’s Amanda Cox has said &lt;a href=&quot;http://blog.visual.ly/10-things-you-can-learn-from-the-new-york-times-data-visualizations/&quot;&gt;in some of her talks&lt;/a&gt; , annotating a visualization is one of the most important, but also one of the hardest things to do. In this post, we won’t tackle the ‘what’ to annotate, but an example of the ‘how’ to implement an annotation layer that needs to change as a user progresses through a visualization. &lt;a href=&quot;http://vallandingham.me/stepper_example/final/&quot;&gt;Here’s what we will be building&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/stepper_example/final/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/stepper.png&quot; alt=&quot;stepper image&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/vlandham/stepper_example&quot;&gt;code for this example is on github&lt;/a&gt; . Each build of this process is broken up into its own folder.&lt;/p&gt;

&lt;p&gt;We will look at implementing this using jQuery, and then as a bonus, a &lt;a href=&quot;http://d3js.org/&quot;&gt;D3.js&lt;/a&gt; only implementation.&lt;/p&gt;

&lt;p&gt;According to Amanda’s &lt;a href=&quot;http://eyeofestival.com/&quot;&gt;Eyeo 2012 talk&lt;/a&gt; (which I saw streaming, but don’t know if it’ll be up anywhere), the New York Times graphics department calls this type of interactive element a &lt;strong&gt;Stepper&lt;/strong&gt;. A great example of a stepper can be found in the &lt;a href=&quot;http://vallandingham.me/bubble_charts_in_d3.html&quot;&gt;previously discussed&lt;/a&gt; &lt;a href=&quot;http://www.nytimes.com/interactive/2012/02/13/us/politics/2013-budget-proposal-graphic.html&quot;&gt;Obama 2013 Budget Proposal&lt;/a&gt; visualization.&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/obama_stepper.png&quot; alt=&quot;obama stepper image&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;As the user clicks on each step of the stepper, the visualization changes - along with its annotations. This allows the visualization to focus on different points of the data presented at each step, and bring the viewer through the entire “story” of the data.&lt;/p&gt;

&lt;p&gt;Before we get started, let me say that everything presented in this demo is pretty basic html and javascript. I just wanted to have a concise example of one way to implement a stepper for web-based. That being said, if you aren’t too bored already, then let’s get started!&lt;/p&gt;

&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;

&lt;p&gt;The method I will present here is largely based on the implementation shown in the Obama Budget visualization. There are dozens of ways this kind of stepper could be implemented. Here are some pros to this process:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keeps the annotations as html&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This allows for easier editing and styling via css.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uses jQuery to switch between annotation steps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Odds are you have some familiarity with this framework.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pretty simple implementation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nothing too crazy going on, just a few commonly used html/javascript features.&lt;/p&gt;

&lt;p&gt;So the basic steps we will follow will be to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create the step annotations in html&lt;/li&gt;
  &lt;li&gt;Style them using css&lt;/li&gt;
  &lt;li&gt;Transition between them using jQuery&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;the-annotation-html&quot;&gt;The Annotation Html&lt;/h2&gt;

&lt;p&gt;Each step will have its own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;, with a unique &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;, and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; identifying it as a step &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;. Inside this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;, each chunk of annotation text can be separated in its own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; for positioning.&lt;/p&gt;

&lt;p&gt;Importantly, all the step divs should be wrapped in a container &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;. The reason we will see in a minute.&lt;/p&gt;

&lt;p&gt;The stepper nav links can be built out of an unsorted list, like any other navigation control.&lt;/p&gt;

&lt;p&gt;A simple example would look something like this:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/github/vlandham/stepper_example/raw/gh-pages/build1/stepper.html&quot;&gt;
&lt;/script&gt;

&lt;p&gt;Our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vis-container&lt;/code&gt; div wraps the entire visualization. The annotation sets for each step are contained in their own div with an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.annotation-step&lt;/code&gt; class, and all annotation steps are children of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#annotation-steps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#vis-canvas&lt;/code&gt; div would be where the actual visualization would be created.&lt;/p&gt;

&lt;p&gt;If we were to stop now, &lt;a href=&quot;http://vallandingham.me/stepper_example/build1/&quot;&gt;here is what it would look like&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-css&quot;&gt;The CSS&lt;/h2&gt;

&lt;p&gt;So far our annotation layer isn’t very impressive. The text for all the steps are visible at the same time, and they go down the page instead of being stacked on top of one another. Let’s look at the minium amount of css that is required to get our annotation layer looking right.&lt;/p&gt;

&lt;p&gt;The main trick used to get positioning how we want it is &lt;a href=&quot;http://css-tricks.com/absolute-positioning-inside-relative-positioning/&quot;&gt;absolute positioning inside a relative div&lt;/a&gt; . Like the link states, when absolute-positioned &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;divs&lt;/code&gt; are inside a relative-positioned &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;, we can specify the exact location of these absolute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;divs&lt;/code&gt; within their parent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;. Meaning, we don’t have to worry about positioning our annotations relative to the entire body of the page (which would get pretty annoying every time a little change was made).&lt;/p&gt;

&lt;p&gt;For our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.annotation-step&lt;/code&gt; divs, we want them all to stack on top of one another. Thus, using just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position: absolute;&lt;/code&gt; should do the trick. It will absolutely position the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; at the top of its relative parent.&lt;/p&gt;

&lt;p&gt;For our specific blocks of text within the annotation, we can use absolute positioning, along with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;left&lt;/code&gt;/@top@ styles to define exactly where each should go inside its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;annotation-step&lt;/code&gt;. You wouldn’t want to write an entire site using absolute positioning, but this method provides the kind of precision you want for where your annotation goes. Also, if you have better ways to position elements like this, let me know!&lt;/p&gt;

&lt;p&gt;We finish off with some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z-index&lt;/code&gt; to ensure the annotation layer and stepper controls are on top of the visualization.&lt;/p&gt;

&lt;p&gt;Our basic stylings now look like this:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/github/vlandham/stepper_example/raw/gh-pages/build2/stepper.css&quot;&gt;
&lt;/script&gt;

&lt;p&gt;The comments in the code should let you follow what is going on.&lt;/p&gt;

&lt;p&gt;Note that we have hidden all the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.annotation-step&lt;/code&gt; divs, but we would like to start by showing the annotations for the first step. This can be done by adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;style=&quot;display:block;&quot;&lt;/code&gt; to the html of the first step’s div. This overrides the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;display:none;&lt;/code&gt; in our css file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;annotation-step&quot; id=&quot;step1-annotation&quot; style=&quot;display:block;&quot;&gt;
&amp;lt;/code&amp;gt;

While we are at it, lets make the stepper look half-way decent. The Obama Budget visualization uses a nice looking multipart button, complete with fancy rounded corners and shadows. You can find a close approximation to this style from [Twitter Bootstrap’s Button Group](http://twitter.github.com/bootstrap/components.html#buttonGroups) . Twitter Bootstrap makes it easy to make your UI elements look good. For this demo, however, I didn’t want to pull in their css and add any complexity. So instead, we will just style them as simple boxes:

&lt;script src=&quot;http://gist-it.appspot.com/github/vlandham/stepper_example/raw/gh-pages/build2/nav.css&quot;&gt;
&lt;/script&gt;

As an aside, I &lt;strong&gt;am&lt;/strong&gt; using a [reset css file](https://github.com/vlandham/stepper_example/blob/gh-pages/final/css/reset.css) in addition to the css above. This is from the [HTML5 Boilerplate template](http://html5boilerplate.com/) .

## The Javascript

Our javascript needs to switch the annotations to a new step when a step link is pressed, and look classy doing it. To do this, we will rely on the consistent naming of the id’s of the `.step-link` anchors and the id’s of the `annotation-step` divs. First, lets hook up a click callback function for the step links:

&lt;script src=&quot;http://gist-it.appspot.com/github/vlandham/stepper_example/raw/gh-pages/build3/stepper.js&quot;&gt;
&lt;/script&gt;

This code is using [jQuery 1.7.2](http://jquery.com/) , but shouldn’t really be too version specific.

Basically, we just need to get the new step’s id somehow (this uses jQuery’s `attr` method), and use it to switch to the next step.

I’ve broken up the switching of the step into two functions: `switchStep` changes which step is active in the stepper links. `switchAnnotations` will change which `.step-annotation` is being displayed.

Here is the entire js for this demo:

&lt;script src=&quot;http://gist-it.appspot.com/github/vlandham/stepper_example/raw/gh-pages/final/js/stepper.js&quot;&gt;
&lt;/script&gt;

So in `switchStep`, we use jQuery’s `.toggleClass` method to de-activate all steps and then activate the new step.

In `switchAnnotation`, we do much the same thing with the annotation step divs. First we hide all the annotation steps, then use the `newStep` to find the step that should be turned on. To make things a little special, we use the `fadeIn` method to have the annotation appear after a bit of a delay. Fancy!

## Bonus: D3 Only Version

Since as of late, I’ve been excited to use [D3.js](http://d3js.org/) , I was interested in how difficult it would be do implement this functionality just D3 instead of jQuery. It turns out, its not too hard at all.

Here’s the [example just using D3](http://vallandingham.me/stepper_example/final_d3/) .

The javascript code is below:

&lt;script src=&quot;http://gist-it.appspot.com/github/vlandham/stepper_example/raw/gh-pages/final_d3/js/stepper.js&quot;&gt;
&lt;/script&gt;

You can see it might be a bit more verbose, but it gets the job done. A few things to point out with this D3 example:

##### Be mindful of when to use `.select` or `.selectAll`

With D3, you need to use the `.select` method when accessing a single element on the page (like when we activate one of the stepper nav links), and `.selectAll` when you are going to be modifying the attributes of multiple elements (like hiding all the stepper annotations).

##### Difference between `.attr` and `.style`

I always start using `.attr` to attempt to change CSS styles of an element when I need to use `.style`. Don’t be like me.

Also, its important to remember that `.attr` (and `.style`) are accessors as well as setters. This feature of `.attr` is used to get the `id` of the stepper nav link clicked.

##### Implementing your own fade in

D3 doesn’t have short-cuts for fancy transitions. Instead, you implement your own using the `d3.transition()` selection.

This usually isn’t too hard - and means you can make very complicated transitions very quickly. In this example, I set all the `.annotation-step` div’s opacities to 0, then transition to an opacity of 1. `.delay` and `.duration` ensure that it looks the same as our jQuery example.

##### Move js code inclusion to end of html file.

To simulate the functionality of `$(document).ready()`, I’ve found [recommendations](http://stackoverflow.com/questions/7169370/d3-js-and-document-onready) that say putting the javascript code at the end of your html file simulates the desired behavior of waiting for the document to load.

This is what I did for the [index.html of this D3 example](https://github.com/vlandham/stepper_example/blob/gh-pages/final_d3/index.html) .

Again, all this [code is on github](https://github.com/vlandham/stepper_example) as a separate project, so have fun building some steppers!
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>D3 Without SVG</title>
   <link href="http://vallandingham.me/d3_without_svg.html"/>
   <updated>2012-05-09T00:00:00+00:00</updated>
   <id>http://vallandingham.me/d3_without_svg</id>
   <content type="html">&lt;script src=&quot;https://code.jquery.com/jquery-1.12.1.min.js&quot;&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;vis/js/libs/es5-shim.min.js&quot;&gt;
&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;vis/js/libs/d3.v2.js&quot;&gt;
&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;vis/js/d3_no_svg.js&quot;&gt;
&lt;/script&gt;

&lt;p&gt;Typically, when creating interactive visualizations with d3.js, you are building your graphics up in SVG. While much of the &lt;a href=&quot;http://d3js.org/&quot;&gt;D3 library&lt;/a&gt; is platform-independent, and there is even a &lt;a href=&quot;http://mbostock.github.com/d3/tutorial/bar-1.html&quot;&gt;small example using just html&lt;/a&gt; in the D3 tutorials, SVG is the typically used for all but the simplest D3 experiments.&lt;/p&gt;

&lt;p&gt;Recently, the New York Times published an interactive visualization on the &lt;a href=&quot;http://elections.nytimes.com/2012/electoral-map&quot;&gt;electorial map&lt;/a&gt; for the up-coming American presidential election. It features a &lt;a href=&quot;http://vallandingham.me/bubble_charts_in_d3.html&quot;&gt;bubble chart&lt;/a&gt; inspired interactive ‘game’ in which users can make their own predictions about which way undecided states will swing to see how the election might turn out.&lt;/p&gt;

&lt;p&gt;I think its a great piece. One detail that isn’t immediately apparent until you start looking at the code is that the entire visualization is built with &lt;strong&gt;no SVG&lt;/strong&gt;. This means that the entire visualization works great in both modern browsers and old ones that don’t support SVG like &lt;strong&gt;IE8&lt;/strong&gt; (I tested it and its just a little less smooth then in Chrome, but otherwise fine).&lt;/p&gt;

&lt;p&gt;Here I’d like to look at just this one facet of how this visualization was made: how they use D3 without SVG.&lt;/p&gt;

&lt;h2 id=&quot;svg-less-d3-demo&quot;&gt;SVG-less D3 Demo&lt;/h2&gt;

&lt;p&gt;To explore how the NYT group created their visualization, I’ve created a small demo using the same methods they did. The result is below:&lt;/p&gt;

&lt;div id=&quot;canvas&quot;&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
&lt;a href=&quot;#&quot; id=&quot;move&quot;&gt;&lt;strong&gt;Move&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/vlandham.github.com/blob/master/vis/js/d3_no_svg.js&quot;&gt;Here is the code for this visualization on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/vlandham.github.com/blob/master/css/pages/d3_no_svg.css&quot;&gt;And the corresponding CSS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before looking at the implementation details, let’s get a high-level overview of how this works:&lt;/p&gt;

&lt;p&gt;First we create a &lt;em&gt;class&lt;/em&gt; that represents a bubble in the vis. This class is called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt;. It stores the data as well as the visual representation for that data. Here, the visual component is a series of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;divs&lt;/code&gt; that are styled using css.&lt;/p&gt;

&lt;p&gt;By &lt;em&gt;class&lt;/em&gt; I really mean that it is a constructor function with additional methods added to it’s &lt;a href=&quot;https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/prototype&quot;&gt;prototype object&lt;/a&gt; . In javascript, there are no classes, but an object inherits properties from it’s prototype object. And functions in javascript are &lt;a href=&quot;https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function&quot;&gt;really Function objects&lt;/a&gt; . So a function has a prototype object to inherit functionality from. By defining ‘methods’ at the prototype level, we can instantiate instances of the function object (in this case, the bubbles in the graph), and they retain these methods. There are lots of posts online that explain javascript prototypes more. &lt;a href=&quot;http://mckoss.com/jscript/object.htm&quot;&gt;Here is one about OO in JS&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Next we create a class that represents the entire visualization. This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleVis&lt;/code&gt; class is handed the data we want to visualize, and the name of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOM&lt;/code&gt; element to build the visualization at. It then instantiates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; objects to store and visualize this data. The D3 &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout&quot;&gt;force layout&lt;/a&gt; is used to position/move the bubbles and is kept at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleVis&lt;/code&gt; level.&lt;/p&gt;

&lt;p&gt;Sound good? Ok, lets look at the nitty-gritty of how this works.&lt;/p&gt;

&lt;h2 id=&quot;useful-jquery-methods&quot;&gt;Useful jQuery Methods&lt;/h2&gt;

&lt;p&gt;This visualization depends a lot on jQuery to make things easier. Before we look at the demo code, it might be useful to explain the jQuery methods used.&lt;/p&gt;

&lt;h3 id=&quot;jqueryproxy&quot;&gt;&lt;a href=&quot;http://api.jquery.com/jQuery.proxy/&quot;&gt;jQuery.proxy()&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy&lt;/code&gt; method wraps a function in a particular &lt;a href=&quot;https://developer.mozilla.org/en/JavaScript/Reference/Operators/this&quot;&gt;context&lt;/a&gt; . This is very similar to the fat arrow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&amp;gt;&lt;/code&gt; in &lt;a href=&quot;http://coffeescript.org/#fat_arrow&quot;&gt;coffeescript&lt;/a&gt; . In fact, the class-based approach used in this demo would make it a good candidate for implementation in coffeescript. However, the NYT visualization used the prototype approach, so I wanted to try it out as well, for this demo.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy&lt;/code&gt; used in the demo and the original visualization to keep a consistent context inside of mouse-related callback functions. This allows us to get access to the location and data of the specific &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; that is being moused over to display in the tooltip.&lt;/p&gt;

&lt;h3 id=&quot;jqueryappend&quot;&gt;&lt;a href=&quot;http://api.jquery.com/append/&quot;&gt;jQuery.append()&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;append&lt;/code&gt; is used to combine the various &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;divs&lt;/code&gt; used to make up the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; visual representation. It is similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.append&lt;/code&gt;, but works on jQuery objects. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;append&lt;/code&gt; is also used to add the bubbles to the main visualization &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;jqueryremove&quot;&gt;&lt;a href=&quot;http://api.jquery.com/remove/&quot;&gt;jQuery.remove()&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;The compliment to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;append&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remove&lt;/code&gt; removes an element from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOM&lt;/code&gt;. We use it here as a way to get rid of the tooltip box. Probably not the most efficient method, but it works.&lt;/p&gt;

&lt;p&gt;Now that the jQuery introduction is over, lets look in more detail at the two &lt;em&gt;classes&lt;/em&gt; that make up this demo, starting with our data container/view class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;simplebubble&quot;&gt;SimpleBubble&lt;/h2&gt;

&lt;p&gt;As mentioned above, instances of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; store the data and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOM&lt;/code&gt; elements used to represent a bubble. Below is its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; function which gets called in the constructor when we say something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var b = new SimpleBubble(data, id, canvas);&lt;/code&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;SimpleBubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;sr&quot;&gt;/_ Elements that make up the bubbles display_/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;lt;div class='bubble' id='bubble-&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;'&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elFill&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;lt;div class='bubbleFill'&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elFill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;sr&quot;&gt;/_ Attach mouse interaction to root element _/&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Note&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;proxy&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;maintain&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;mouseover&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showToolTip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;mouseout&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hideToolTip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;sr&quot;&gt;/_ Set CSS of Elements _/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;radius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boxSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elFill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boxSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boxSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boxSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boxSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So first we create some free standing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;divs&lt;/code&gt; that will make up the visual representation of the bubble. We store them as part of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; instance. the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jQuery.append()&lt;/code&gt; method is used to attach the sub-elements to the root &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.el&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;This demo only uses one sub-element, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.elFill&lt;/code&gt;. The NYT Visualization uses a number of child elements to hold text, background images, etc.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jQuery.proxy()&lt;/code&gt; method is used to allow us to use tooltip functions defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; to show and hide the tooltip when mousing.&lt;/p&gt;

&lt;p&gt;Finally, CSS is applied using the jQuery object’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css&lt;/code&gt; method for the child &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elFill&lt;/code&gt; element. This is done to position it correctly inside the parent element.&lt;/p&gt;

&lt;p&gt;Getting the positioning correct requires just the right css position incantations. While this all could be specified in the javascript, I decided to put them in a stand-alone CSS file, since they are not dependent on any data associated with the bubble. Here is the CSS applied to the bubble elements:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.bubble&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;absolute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.bubbleFill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;absolute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;-webkit-border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;70px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;-moz-border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;70px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;70px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can see that the main &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bubble&lt;/code&gt; elements and their &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bubbleFill&lt;/code&gt; child elements have their positions set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;absolute&lt;/code&gt;. This means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bubble&lt;/code&gt; element’s position is based on its parent element (the main visualization div) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bubbleFill&lt;/code&gt; element’s position is based on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bubble&lt;/code&gt;. So modifying the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;left&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;top&lt;/code&gt; stylings of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bubble&lt;/code&gt; will be done relative to the main visualization element (and not the entire page) and will in turn modify its child element’s positions.&lt;/p&gt;

&lt;p&gt;The other thing to note is that we use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt; property to make the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;divs&lt;/code&gt; into &lt;strong&gt;circles&lt;/strong&gt;. This leads to a complication with IE, as will be talked about more later.&lt;/p&gt;

&lt;p&gt;Speaking of moving the bubbles, let’s look really quickly at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move&lt;/code&gt; method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;SimpleBubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pretty simple. The bubble’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; are expected to be modified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleVis&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move&lt;/code&gt; function just modifies the css of the bubble to shift its position. This isn’t the most abstracted way to implement this functionality, but it works.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; given to the bubble instance in this demo is a simple integer used to determine its size. In a real visualization, you would probably use a javascript object to pass more information to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; for it to store.&lt;/p&gt;

&lt;p&gt;The tooltip labels are lazily done, because I got lazy, so lets not focus on those, ok?&lt;/p&gt;

&lt;h2 id=&quot;simplevis&quot;&gt;SimpleVis&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleVis&lt;/code&gt; stores the force layout, creates new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; instances for each data point, and moves these bubbles based on the force layout. Most of this functionality is in it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; method, so lets look at that:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;SimpleVis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;sr&quot;&gt;/_ Store reference to original this _/&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;sr&quot;&gt;/_ Initialize root visualization element _/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;#eee&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;relative&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;sr&quot;&gt;/_ Create Bubbles _/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SimpleBubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;sr&quot;&gt;/_ Define Starting locations _/&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boxSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boxSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bubbles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;sr&quot;&gt;/_ Add root bubble element to visualization _/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;sr&quot;&gt;/_ Setup force layout _/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bubbles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gravity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bubbleCharge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;friction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.87&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bubbles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setBubbleLocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;centers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ok, so first we setup the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; that will be holding our visualization. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.canvas&lt;/code&gt; is a jQuery object wrapped around a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; present in the page. This div gets passed into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleVis&lt;/code&gt; constructor, as we will see. Here the position is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;relative&lt;/code&gt; using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css&lt;/code&gt; method instead of in a static style-sheet. This is just to show another way it could be done.&lt;/p&gt;

&lt;p&gt;Then we iterate over our data and add create new bubbles for each data point. Initial positions are just a guess on my part. They could be set to anything - depending on how you wanted the initial state of your visualization to look.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.layout.force&lt;/code&gt; is initialized. This process is very similar to how &lt;a href=&quot;http://vallandingham.me/bubble_charts_in_d3.html&quot;&gt;my previous bubble chart example&lt;/a&gt; worked. Note that a method in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleVis&lt;/code&gt; determines the next location for each bubble on each &lt;strong&gt;tick&lt;/strong&gt;. And then each bubble is moved to that location.&lt;/p&gt;

&lt;p&gt;We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;me&lt;/code&gt; so that we can refer to the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleVis&lt;/code&gt; inside of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; callback function.&lt;/p&gt;

&lt;p&gt;The force’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; parameter is defined by a function that will be passed each node. Lets look at this function really quickly:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bubbleCharge&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So, just like before, it uses the node’s radius to determine a relative charge to push away other nodes with. Quick and easy collision ‘detection’.&lt;/p&gt;

&lt;p&gt;Lastly, lets checkout the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setBubbleLocation&lt;/code&gt; method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;SimpleVis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setBubbleLocation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;centers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;centers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)];&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.115&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bubble&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.115&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can see that we get a center location based on the bubble’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;, then modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; variables to move the bubble closer to that position. This movement is tempered by the force’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt;, which will decay as time goes on.&lt;/p&gt;

&lt;h2 id=&quot;caveats-and-trade-offs&quot;&gt;Caveats and Trade Offs&lt;/h2&gt;

&lt;h3 id=&quot;the-binding-question&quot;&gt;The Binding Question&lt;/h3&gt;

&lt;p&gt;So just because we &lt;strong&gt;can&lt;/strong&gt; use D3 without SVG doesn’t mean its always a great solution. We’ve gained access to D3’s great force directed layout. Using some shims (described below), we can also use D3’s scales and some of its array manipulation features.&lt;/p&gt;

&lt;p&gt;We didn’t use one of D3’s most powerful constructs - &lt;strong&gt;binding&lt;/strong&gt; data to the data’s representation using the built in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectAll&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; functions. While we certainly can use D3 to bind data to any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOM&lt;/code&gt; element, the choice to use a class-based approach to encapsulate the data and representation in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleBubble&lt;/code&gt; replaced this D3 binding functionality.&lt;/p&gt;

&lt;p&gt;More investigation might bring out a way to cleanly use D3’s binding capabilities with more complicated object based representations.&lt;/p&gt;

&lt;h3 id=&quot;it-works-in-ie&quot;&gt;It Works in IE?&lt;/h3&gt;

&lt;p&gt;The original NYT graphic works great in IE8. This demo has some problems.&lt;/p&gt;

&lt;p&gt;Specifically, the round appearance of the bubbles is created using the CSS &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt; property - but &lt;strong&gt;IE8 doesn’t support this&lt;/strong&gt;! So how does the NYT graphic still look good? If the browser is found not to support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt;, then a static circular image is used instead.&lt;/p&gt;

&lt;p&gt;Generating a bunch of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gif&lt;/code&gt; images for this demo isn’t something I’m prepared to do, so I’ll have to be satisfied with boxes in IE. But otherwise it is impressive how cross-platform the NYT visualization is. They include a number of tweaks to optimize the experience for the iPad as well. Something that I might look at more later.&lt;/p&gt;

&lt;h2 id=&quot;other-tips&quot;&gt;Other Tips&lt;/h2&gt;

&lt;h3 id=&quot;es5-shim&quot;&gt;es5-shim&lt;/h3&gt;

&lt;p&gt;This demo also uses &lt;a href=&quot;https://github.com/kriskowal/es5-shim&quot;&gt;es5-shim&lt;/a&gt; to add missing functionality to Arrays in IE. The NYT visualization doesn’t use this particular library, but d3 uses some of these functions in places like scales, so its useful to have.&lt;/p&gt;

&lt;h3 id=&quot;html5&quot;&gt;html5&lt;/h3&gt;

&lt;p&gt;As &lt;a href=&quot;https://github.com/mbostock/d3/issues/599&quot;&gt;this bug report&lt;/a&gt; points out, loading d3 in IE won’t work unless the page is html5. So keep this in mind.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/vlandham.github.com/blob/master/vis/js/d3_no_svg.js&quot;&gt;Here is a link&lt;/a&gt; to the code again. Thanks to the NYT group for creating this great graphic to learn from. In a future post, we may explore the drag and drop capabilities that make this visualization so interactive.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kansas City Streets Visualized</title>
   <link href="http://vallandingham.me/kansas_city_streets_map_with_tilemill.html"/>
   <updated>2012-04-05T00:00:00+00:00</updated>
   <id>http://vallandingham.me/kansas_city_streets_map_with_tilemill</id>
   <content type="html">&lt;h3 id=&quot;using-tilemill-and-openstreetmaps-for-printable-map-art&quot;&gt;Using Tilemill and OpenStreetMaps for Printable Map-Art&lt;/h3&gt;

&lt;p&gt;Awhile ago, Gregor Aisch, creator of the awesome up-and-coming &lt;a href=&quot;http://kartograph.org/&quot;&gt;Kartograph&lt;/a&gt; posted his &lt;a href=&quot;http://vis4.net/blog/posts/berlin-streets/&quot;&gt;Berlin Streets Visualized&lt;/a&gt; , a map of just Berlin streets inspired by Ben Fry’s &lt;a href=&quot;http://fathom.info/allstreets/&quot;&gt;All Streets Map&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;When I saw how nice and simple it was to create, I wanted to make one for myself, of my hometown - Kansas City. Here’s a scaled down version of the end result:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;a href=&quot;http://vallandingham.me/images/vis/kc_map_medium.jpg&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/kc_map_small.png&quot; alt=&quot;kc map&quot; style=&quot;border:1px dotted #cccccc;&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;p&gt;Gregor used street data in Adobe Illustrator form from the wonderful &lt;a href=&quot;http://downloads.cloudmade.com/&quot;&gt;Cloudmade OSM downloads&lt;/a&gt; . Alas, Cloudemade’s downloads don’t include city level exports for North American cities (at least I didn’t see it anywhere).&lt;/p&gt;

&lt;p&gt;So I decided to try a slight variation on the theme: use Shapefiles from OSM and style them using &lt;a href=&quot;http://mapbox.com/tilemill/&quot;&gt;TileMill&lt;/a&gt; . Here I’ll spell out some of the specifics on how this works.&lt;/p&gt;

&lt;h2 id=&quot;metro-extracts&quot;&gt;Metro Extracts&lt;/h2&gt;

&lt;p&gt;While it would be possible to use &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Osmosis&quot;&gt;Osmosis&lt;/a&gt; to extract my local cities OSM data, fortunately for me, this was not necessary.&lt;/p&gt;

&lt;p&gt;The wonderful &lt;a href=&quot;http://metro.teczno.com/&quot;&gt;Metro Extracts&lt;/a&gt; provided as a service by &lt;a href=&quot;http://mike.teczno.com/notes/&quot;&gt;Michal Migurski&lt;/a&gt; (who’s blog you should subscribe to right now) gives you nice OSM extracts for a large list of metro areas world-wide.&lt;/p&gt;

&lt;p&gt;The one gotcha with this service is that, unlike Cloudemade’s downloads, these extracts have not been converted to Illustrator format. I’m sure that getting it in that format wouldn’t be too hard, but honestly I’m pretty aweful at Illustrator, so wanted to try out a different way to style this data.&lt;/p&gt;

&lt;p&gt;To this end, I grabbed the &lt;em&gt;imposm shapefiles&lt;/em&gt; to work with in TileMill.&lt;/p&gt;

&lt;h2 id=&quot;tilemill&quot;&gt;TileMill&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://mapbox.com/tilemill/&quot;&gt;TileMill&lt;/a&gt; is a great tool from the MapBox team. Its really meant create and style map tiles to be hosted on a service like their &lt;a href=&quot;http://mapbox.com/plans/&quot;&gt;map publishing platform&lt;/a&gt; . They have some great looking &lt;a href=&quot;http://mapbox.com/maps/&quot;&gt;map styles&lt;/a&gt; and you can upload your own custom tiles or data, like the NYPL Lab’s &lt;a href=&quot;https://tiles.mapbox.com/nypllabs/map/nyc1940-16&quot;&gt;1940s Census Tiles&lt;/a&gt; used on their &lt;a href=&quot;http://directme.nypl.org/&quot;&gt;Direct Me NYC&lt;/a&gt; site.&lt;/p&gt;

&lt;p&gt;In addition to all this map tile stying, since version 0.6 TileMill has had the ability to export to SVG. This means we can style our map with TileMill, and get it in a vector format suitable for printing!&lt;/p&gt;

&lt;p&gt;Here’s the basic process I used to import, style and export my street data:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extract the shapefile archive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now you have a folder with lots of shapefile files inside.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open TileMill, create a new Project called “KC Print Map”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I included the ‘Default data’, but then hid it in my final map styling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open your new Project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should see a nice view of the world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Select the Layers tab and load your shapefile&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img src=&quot;http://vallandingham.me/images/vis/tilemill_layers.png&quot; alt=&quot;tilemill layers tab&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;With the layers tab open, select &lt;strong&gt;Add layer&lt;/strong&gt;. Navigate to where you extracted your shapefiles. Select the &lt;em&gt;kansas-city-lawrence-topeka.osm-roads.shp&lt;/em&gt; file for your Datasource and use &lt;strong&gt;roads&lt;/strong&gt; for your ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Some of the road types have their own shapefiles, so you could import these layers separately and style them separately. This is the approach I started with, but ran into issues with missing road types and layering. So lets import all the roads, style the types separately (as we will see below).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Select “Style &amp;amp; Save” and then zoom in to your road data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should have a nice view of all the roads in KC (or whatever metro you choose).&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/tilemill_roads.png&quot; alt=&quot;tilemill roads overview&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;Now lets style these roads!&lt;/p&gt;

&lt;h2 id=&quot;carto&quot;&gt;Carto&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://mapbox.com/tilemill/docs/manual/carto/&quot;&gt;Carto&lt;/a&gt; is the styling syntax used by TileMill. It looks a lot like CSS, but is based on &lt;a href=&quot;http://lesscss.org/&quot;&gt;less&lt;/a&gt; so has support for variables and conditional effects, which we will make use of here.&lt;/p&gt;

&lt;h3 id=&quot;road-styles&quot;&gt;Road Styles&lt;/h3&gt;

&lt;p&gt;The full &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;style.mss&lt;/code&gt; file used to style the map can be &lt;a href=&quot;https://gist.github.com/2312647#file_style.css&quot;&gt;found in this gist&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, I’ll provide a shortened version of the code, to talk about:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2312647.js?file=short.css&quot;&gt;
&lt;/script&gt;

&lt;p&gt;Lets go over the details.&lt;/p&gt;

&lt;p&gt;First we create two variables, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@minor_color&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@major_color&lt;/code&gt;, to store the two colors used to style the different road types.&lt;/p&gt;

&lt;p&gt;The first style, for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#roads&lt;/code&gt; sets the basis of what all the roads will look like. It makes all the roads skinny and sets them to the minor road color.&lt;/p&gt;

&lt;p&gt;The stylings after that override this default setting for certain types of roads. We use conditional styles, (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[key='value']&lt;/code&gt; component) to select which road type we are talking about.&lt;/p&gt;

&lt;p&gt;First we hide a number of types that aren’t roads. The above example hides railways. I used QGIS to find all the different types of roads in the shapefile, but there are probably lots of ways to do that.&lt;/p&gt;

&lt;p&gt;Then, for major roads and highways, we increase the line width and use the darker &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@major_color&lt;/code&gt;. These major road stylings use the &lt;em&gt;New symbolizer&lt;/em&gt; syntax (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::newsymbol&lt;/code&gt;) which creates a ordering of overlays. A poor-mans version of separate layers. This works because we start with small roads and overlay larger ones. So the &lt;strong&gt;order&lt;/strong&gt; of the stylings &lt;strong&gt;matter&lt;/strong&gt;. Something to keep in mind.&lt;/p&gt;

&lt;p&gt;The nice thing about this approach is that we can try out all sorts of different stylings really easily. Want to make major roads green and highways really fat? No problem. A two line change and you have:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/tilemill_roads_detail_1.png&quot; alt=&quot;tilemill roads detail&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;TileMill makes it really easy to explore different combinations of styles.&lt;/p&gt;

&lt;h2 id=&quot;export&quot;&gt;Export&lt;/h2&gt;

&lt;p&gt;Once you have something you like, its time to get it into a format suitable for printing.&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Export&lt;/strong&gt; at the top-right of the screen. Then select &lt;strong&gt;SVG&lt;/strong&gt;. You might need to zoom into your region of interest again and crop using &lt;em&gt;shift-drag&lt;/em&gt; as necessary. When you have the cropping how you want it, select &lt;strong&gt;Export&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This will generate a file in your TileMill’s &lt;em&gt;export directory&lt;/em&gt;. I believe, by default, it is in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Documents/MapBox/export&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;finishing-touches&quot;&gt;Finishing Touches&lt;/h2&gt;

&lt;p&gt;Ok, so I would be misleading if I didn’t mention that I finished up by importing the SVG into Illustrator to add a white border and to resize it to be 20x24in. Theoretically, you could do this part in any editor capable of handling SVGs. However, none of the actual styling of the map was done in Illustrator.&lt;/p&gt;

&lt;p&gt;I enjoy how interesting landmarks jump out at you, even when presented with just the streets of a city you are familiar with. For example, here is our lowly airport:&lt;/p&gt;

&lt;div class=&quot;center&quot;&gt;
&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/tilemill_airport.png&quot; alt=&quot;tilemill airport detail&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;So go out and create some interesting map art with TileMill and Open Street Map data!&lt;/p&gt;

&lt;p&gt;And thanks to &lt;a href=&quot;http://vis4.net/blog/&quot;&gt;Gregor&lt;/a&gt; for the nice tutorial to copy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Creating Animated Bubble Charts in D3</title>
   <link href="http://vallandingham.me/bubble_charts_in_d3.html"/>
   <updated>2012-02-21T00:00:00+00:00</updated>
   <id>http://vallandingham.me/bubble_charts_in_d3</id>
   <content type="html">&lt;div class=&quot;left&quot;&gt;
&lt;img src=&quot;http://vallandingham.me/images/vis/nyt_thumb.png&quot; alt=&quot;nyt bubble chart&quot; /&gt;
&lt;/div&gt;

&lt;div class=&quot;alert alert-danger&quot;&gt;
  &lt;p&gt;This post is very old and no longer represents the current state of how to use D3 properly. You should check out my updated &lt;a href=&quot;http://vallandingham.me/bubble_charts_with_d3v4.html&quot;&gt;Creating Bubble Charts with D3v4&lt;/a&gt; instead!&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I moved the code to &lt;a href=&quot;https://github.com/vlandham/gates_bubbles&quot;&gt;its own github repo&lt;/a&gt; - to make it easier to consume and maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update #2&lt;/strong&gt; I’ve rewritten this tutorial &lt;a href=&quot;http://vallandingham.me/bubble_charts_in_js.html&quot;&gt;in straight JavaScript&lt;/a&gt;. So if you aren’t that in to CoffeeScript, check the new one out!&lt;/p&gt;

&lt;p&gt;Recently, the New York Times featured a &lt;a href=&quot;http://www.nytimes.com/interactive/2012/02/13/us/politics/2013-budget-proposal-graphic.html&quot;&gt;bubble chart of the proposed budget for 2013&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/#!/shancarter&quot;&gt;Shan Carter&lt;/a&gt; . It features some nice, organic, animations, and smooth transitions that add a lot of visual appeal to the graphic. This was all done using &lt;a href=&quot;http://mbostock.github.com/d3/&quot;&gt;D3.js&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;As &lt;a href=&quot;http://flowingdata.com/2012/02/15/slicing-obamas-2013-budget-proposal-four-ways/&quot;&gt;FlowingData commenters point out&lt;/a&gt; , the use of bubbles may or may not be the best way to display this dataset. Still, the way this visualization draws you in and gets you to interact makes it a nice piece and one that makes you wonder how they did it.&lt;/p&gt;

&lt;p&gt;In this post, we attempt to tease out some of the details of how this graphic works.&lt;/p&gt;

&lt;h2 id=&quot;simple-animated-bubble-chart&quot;&gt;Simple Animated Bubble Chart&lt;/h2&gt;

&lt;p&gt;In order to better understand the budget visualization, I’ve created a similar bubble chart that displays information about what education-based donations the Gates Foundation has made.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/gates_bubbles/&quot;&gt;&lt;img class=&quot;center&quot; src=&quot;http://vallandingham.me/images/vis/bubble_chart.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/gates_bubbles/&quot;&gt;You can see the full visualization here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the &lt;a href=&quot;https://github.com/vlandham/gates_bubbles&quot;&gt;visualization code is on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bubbles are color coded based on grant amount (I know the double encoding using size and color isn’t very helpful - but this data set didn’t have any quick and easy categorical fields besides year).&lt;/p&gt;

&lt;div class=&quot;box&quot;&gt;
**Warning Coffeescript**

The example is written in [CoffeeScript](http://coffeescript.org/) as I find it much easier to read and write than javascript. Everything is packaged up in a nice `BubbleChart` class. Hopefully this does not get in the way of you understanding what is going on. The original NYT visualization is in javascript. Let me know if something is confusing.

&lt;/div&gt;
&lt;p&gt;The data for this visualization comes from the &lt;a href=&quot;http://www.washingtonpost.com/wp-srv/metro/data/gates-grants.html&quot;&gt;Washington Posts DataPost&lt;/a&gt; . I’ve added a categorization to the amount for each grant (low, medium, high) and pulled out the start year, but otherwise have left the data alone.&lt;/p&gt;

&lt;p&gt;The rest of this tutorial will walk through the functionality behind this Gates Foundation visualization. This visualization is just a sketch of the functionality in the New York Times graphic - so we can see the relevant parts clearly.&lt;/p&gt;

&lt;h2 id=&quot;d3s-force-layout&quot;&gt;D3’s Force Layout&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout&quot;&gt;Force Layout&lt;/a&gt; component of D3.js is used to great effect to provide most of the functionality behind the transitions, animations, and collisions in the visualization.&lt;/p&gt;

&lt;p&gt;This layout essentially starts up a little physics simulation in your visualization. Components push and pull at one another, eventually settling in to their final positions. Typically, this layout is used for &lt;a href=&quot;http://mbostock.github.com/d3/ex/force.html&quot;&gt;graph visualization&lt;/a&gt; . Here, however, we forgo the use of edges and instead use it just to move around the nodes of a graph.&lt;/p&gt;

&lt;p&gt;This means we don’t really need to know much about graph theory to understand how this graphic works. However, we do need to know the components that make up a force layout, and how to use them.&lt;/p&gt;

&lt;h3 id=&quot;force-layout-quick-reference&quot;&gt;Force Layout Quick Reference&lt;/h3&gt;

&lt;p&gt;Here are some of the concepts this visualization will use.&lt;/p&gt;

&lt;h4 id=&quot;nodes&quot;&gt;nodes&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nodes&lt;/code&gt; is an array of objects that will be used as the nodes (i.e. bubbles in this graph) in the layout. Each node in the array needs a few attributes like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this visualization, we set some of the required attributes manually - so we are in full control of them. The rest we let D3 set and handle internally.&lt;/p&gt;

&lt;h4 id=&quot;gravity&quot;&gt;gravity&lt;/h4&gt;

&lt;p&gt;In D3’s force layout, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; isn’t really a force pushing downwards. Rather, it is a force that can push nodes towards the center of the layout.&lt;/p&gt;

&lt;p&gt;The closer to the center a node is, the less of an impact the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; parameter has on it.&lt;/p&gt;

&lt;p&gt;Setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; to 0 disables it. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; can also be negative. This gives the nodes a push away from the center.&lt;/p&gt;

&lt;h4 id=&quot;friction&quot;&gt;friction&lt;/h4&gt;

&lt;p&gt;As &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout#wiki-friction&quot;&gt;the documentation states&lt;/a&gt; , perhaps a more accurate term for this force attribute would be &lt;strong&gt;velocity decay&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At each step of the physics simulation (or &lt;strong&gt;tick&lt;/strong&gt; as it is called in D3), node movement is scaled by this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;friction&lt;/code&gt;. The recommended range of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;friction&lt;/code&gt; is 0 to 1, with 0 being no movement and 1 being no friction.&lt;/p&gt;

&lt;h4 id=&quot;charge&quot;&gt;charge&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; in a force layout refers to how nodes in the environment push away from one another or attract one another. Kind of like magnets, nodes have a charge that can be positive (attraction force) or negative (repelling force).&lt;/p&gt;

&lt;h4 id=&quot;alpha&quot;&gt;alpha&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; is the layout is described as the simulation’s &lt;em&gt;cooling factor&lt;/em&gt; . I don’t know if that makes sense to me or not.&lt;/p&gt;

&lt;p&gt;What I do know is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; starts at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.1&lt;/code&gt;. After a few hundred ticks, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; is decreased some amount. This continues until &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; is really small (for example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.005&lt;/code&gt;), and then the simulation ends.&lt;/p&gt;

&lt;p&gt;What this means is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; can be used to scale the movement of nodes in the simulation. So at the start, nodes will move relatively quickly. When the simulation is almost over, the nodes will just barely be tweaking their positions.&lt;/p&gt;

&lt;p&gt;This allows you to damper the effects of the forces in your visualization over time. Without taking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; into account, things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; would exert a consistent force on your nodes and pull them all into a clump.&lt;/p&gt;

&lt;h2 id=&quot;how-this-bubble-chart-works&quot;&gt;How This Bubble Chart Works&lt;/h2&gt;

&lt;p&gt;Ok, we didn’t cover everything in the force layout, but we got through all the relevant bits for this visualization. Let me know if I messed anything up.&lt;/p&gt;

&lt;p&gt;Now on to the interesting part!&lt;/p&gt;

&lt;p&gt;There are two features of this bubble chart I want to talk about in more detail: collision detection and transitions.&lt;/p&gt;

&lt;h3 id=&quot;bubble-collision-detection&quot;&gt;Bubble Collision Detection&lt;/h3&gt;

&lt;p&gt;When I first saw the NYT chart, I was intrigued by how they could use different sized bubbles but not have them overlap or sit on top of one another.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; of a force layout specifies node-node repulsions, so it could be used to push nodes away from one another, creating this effect. But how can this work with different sizes if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; is just a single parameter?&lt;/p&gt;

&lt;p&gt;The trick is that along with a static value, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; can also take a &lt;strong&gt;function&lt;/strong&gt;, which is evaluated for each node in the layout, passing in that node’s data. Here is the charge function for this visualization:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;na&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pretty simple right? But, for me at least, it was unclear from the &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Force-Layout#wiki-charge&quot;&gt;charge documentation&lt;/a&gt; , that this function based approach was possible.&lt;/p&gt;

&lt;p&gt;Lets break it down. Again this is coffeescript, so what we are seeing is a method called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BubbleChart&lt;/code&gt; class. This method takes in an input parameter, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt;, which is the data associated with a node. The method returns the negative of the diameter of the node, divided by 8.&lt;/p&gt;

&lt;p&gt;The negative is for pushing away nodes. Dividing by 8 scales the repulsion to an appropriate scale for the size of the visualization.&lt;/p&gt;

&lt;p&gt;A couple of other factors are at work that also contribute to the nice looking placement of these nodes.&lt;/p&gt;

&lt;p&gt;Here is the code that is used to configure and startup the force directed simulation:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;na&quot;&gt;display_group_all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;gravity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;friction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;tick&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;circles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;move_towards_center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@force&lt;/code&gt; is an instance variable of BubbleChart holding the force layout for the visualization. You can see the use of the charge method for the layout’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; input. We set its gravity to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-0.01&lt;/code&gt; and its friction value to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.9&lt;/code&gt; (which is the default). This says that nodes should be ever so slightly pushed away from the center of the layout, but there should be just enough friction to prevent them from scattering away.&lt;/p&gt;

&lt;p&gt;We will get to the tick function in the next section.&lt;/p&gt;

&lt;p&gt;So, nodes push away from one another based on their diameter - providing nice looking collision detection. The gravity and friction settings work along with this pushing to ensure nodes are sucked together or pushed away too far. Its a nice combo.&lt;/p&gt;

&lt;h3 id=&quot;animation-and-transitions&quot;&gt;Animation and Transitions&lt;/h3&gt;

&lt;p&gt;The original graphic has some nice transitions between views of the data, where bubbles are pulled apart into separate groups. I’ve replicated this somewhat by having a view that divides up Gate’s grants by year.&lt;/p&gt;

&lt;p&gt;How is this done? Well, lets start with the all-together view first. The position of each node is determined by the function called for each &lt;em&gt;tick&lt;/em&gt; of the simulation. This function gets passed in the tick event, which includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; for this iteration of the simulation.&lt;/p&gt;

&lt;p&gt;We can see this function in the code segment above. I’ll highlight it again here:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;tick&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;circles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;move_towards_center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@circles&lt;/code&gt; instance variable holds the svg circles that represent each node. So what this code does is for every tick event, for each circle in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@circles&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move_towards_center&lt;/code&gt; method is called, with the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; value passed in. Then, The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cx&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cy&lt;/code&gt; of each circle is set based on it’s data’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; values.&lt;/p&gt;

&lt;p&gt;So, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move_towards_center&lt;/code&gt; &lt;strong&gt;must&lt;/strong&gt; be doing something with the data’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; values to get things to move. And indeed it is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;towards_center&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;damper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;damper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move_towards_center&lt;/code&gt; returns a function that is called for each circle, passing in its data. Inside this function, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; values of the data are pushed towards the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@center&lt;/code&gt; point (which is set to the center of the visualization). This push towards the center is dampened by a constant, 0.02 + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@damper&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; dampening allows the push towards the center to be reduced over the course of the simulation, giving other forces like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gravity&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charge&lt;/code&gt; the opportunity to push back.&lt;/p&gt;

&lt;p&gt;The variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@damper&lt;/code&gt; is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.1&lt;/code&gt;. This probably took some time to find a good value for.&lt;/p&gt;

&lt;p&gt;Ok, we’ve now seen how the nodes in the simulation move towards one point, what about multiple locations? The code is just about the same:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;na&quot;&gt;display_by_year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;gravity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;layout_gravity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;friction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;tick&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;circles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;move_towards_year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;towards_year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;year_centers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;damper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.1&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;damper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The switch to displaying by year is done by restarting the force simulation. This time the &lt;em&gt;tick&lt;/em&gt; function calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move_towards_year&lt;/code&gt;. Otherwise it’s about the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;display_group_all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move_towards_year&lt;/code&gt; is almost the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move_towards_center&lt;/code&gt;. The difference being that first the correct year point is extracted from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@year_centers&lt;/code&gt;. Here’s what that variable looks like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;year_centers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;2008&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/ 3, y: @height /&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;2009&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/ 2, y: @height /&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;2010&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/ 3, y: @height /&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can see this is just an associative array where each year has its own location to move towards.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move_towards_year&lt;/code&gt; also multiplies by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.1&lt;/code&gt; to speed up the transition a bit. Again, these numbers take some tweaking and experimentation to find. The code could be simplified a bit if you wanted to pass in the unique multipliers for each transition.&lt;/p&gt;

&lt;p&gt;So we’ve seen a general pattern for both of these views: setup the &lt;em&gt;tick&lt;/em&gt; method to iterate over all the nodes to change their locations. This was done using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;each&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;In fact you can chain multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;each&lt;/code&gt; methods that call different move functions. This would allow you to push and pull your nodes in various ways depending on their features. The NYT graphic uses at least two move functions for these transitions. One to move nodes towards a group point (like above), and one to move nodes towards their respective color band.&lt;/p&gt;

&lt;p&gt;Hope this tutorial shows you some interesting ways to use D3’s force layout. I thought the original NYT visualization was interesting enough to find out more about it. Again, the full visualization code &lt;a href=&quot;https://github.com/vlandham/gates_bubbles&quot;&gt;can be found on github&lt;/a&gt;. It is just over 200 lines of code - &lt;strong&gt;including&lt;/strong&gt; comments.&lt;/p&gt;

&lt;p&gt;Force layouts: they are not just for force-directed graphs anymore!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>iBook Widgets with D3.js</title>
   <link href="http://vallandingham.me/ibooks_and_d3.html"/>
   <updated>2012-02-16T00:00:00+00:00</updated>
   <id>http://vallandingham.me/ibooks_and_d3</id>
   <content type="html">&lt;h3 id=&quot;create-a-html-widget-for-ibooks-using-d3js-without-dashcode&quot;&gt;Create a HTML Widget for iBooks using d3.js without Dashcode&lt;/h3&gt;

&lt;div class=&quot;left&quot;&gt;
&lt;img src=&quot;http://vallandingham.me/images/ibooks/ibooks_author_icon.png&quot; alt=&quot;ibooks author icon&quot; /&gt;

&lt;/div&gt;
&lt;p&gt;With the release of &lt;a href=&quot;http://www.apple.com/ibooks-author/&quot;&gt;iBooks Author&lt;/a&gt; , the idea of using powerful javascript libraries inside using their &lt;a href=&quot;http://www.apple.com/ibooks-author/gallery.html&quot;&gt;HTML Module&lt;/a&gt; functionality probably came to a lot of people. I have certainly been thinking about the potential power of something like &lt;a href=&quot;http://mbostock.github.com/d3/&quot;&gt;d3.js&lt;/a&gt; or &lt;a href=&quot;https://leafletjs.com/&quot;&gt;leaflet.js&lt;/a&gt; embedded in an interactive text-book.&lt;/p&gt;

&lt;p&gt;When iBooks Author was announced, I spent 5 minutes entertaining this idea, but soon was frustrated with having to come up to speed with Dashcode and other Apple developer tools - when all I really wanted to do was make a fun, interactive visualization.&lt;/p&gt;

&lt;p&gt;Recently, I stumbled upon &lt;a href=&quot;http://ibooksauthor.es/&quot;&gt;ibooksauthor.es&lt;/a&gt; a blog by Miguel Sanchez Molina that &lt;a href=&quot;http://ibooksauthor.es/widgets-interactivos-html/&quot;&gt;describes how to create an interactive visualization using Raphael&lt;/a&gt; &lt;strong&gt;without&lt;/strong&gt; the need for Dashcode.&lt;/p&gt;

&lt;p&gt;Consider this write-up a slight spin on the same idea, but using d3.js, with a hint of automation.&lt;/p&gt;

&lt;h2 id=&quot;anatomy-of-a-dashcode-widget&quot;&gt;Anatomy of a Dashcode Widget&lt;/h2&gt;

&lt;div class=&quot;left&quot;&gt;
&lt;img src=&quot;http://vallandingham.me/images/ibooks/widgt_icon.png&quot; alt=&quot;dashcode widget icon&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;It turns out, a widget is really just a specially named folder with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.wdgt&lt;/code&gt; extension.&lt;/p&gt;

&lt;p&gt;You can right-click on a widget, select ‘Show Package Contents’ and see the HTML and javascript files that go into it.&lt;/p&gt;

&lt;p&gt;If I look at the default ‘Countdown’ widget from Dashcode, without any modifications, here are the files and directories it uses:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* attributes.js
* Default.png
* en.lproj
* iCal.js
* Icon.png
* Images/
* Info.plist
* main.css
* main.html
* main.js
* Parts/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Parts/&lt;/code&gt; directory stores Dashcode javascript libraries. The required components to a widget are just a subset of these files:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Info.plist - the plist file that tells a user of the widget how to run it.&lt;/li&gt;
  &lt;li&gt;Default.png - a preview image of the widget when it is not running.&lt;/li&gt;
  &lt;li&gt;main.html - or some html file to give it some functionality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And most likely you’ll want one or more javascript files - as we are trying to make an interactive visualization.&lt;/p&gt;

&lt;h2 id=&quot;creating-an-interactive-dashcode-widget&quot;&gt;Creating An Interactive Dashcode Widget&lt;/h2&gt;

&lt;p&gt;So again, our goal is to create an interactive widget using d3.js, without the need for using Dashcode directly.&lt;/p&gt;

&lt;p&gt;To this end, I’ve created a &lt;a href=&quot;https://github.com/vlandham/vis_widget&quot;&gt;vis widget starting point&lt;/a&gt; that includes the necessary files to kick start just such a project.&lt;/p&gt;

&lt;p&gt;Here’s what it’ll look like. Click for the actual interactive visualization. You can click and drag the circles around:&lt;/p&gt;

&lt;p&gt;You can see, its not much to look at - but its something to start with.&lt;/p&gt;

&lt;h3 id=&quot;vis-widget-template&quot;&gt;Vis Widget Template&lt;/h3&gt;

&lt;p&gt;This &lt;a href=&quot;https://github.com/vlandham/vis_widget&quot;&gt;vis_widget repo&lt;/a&gt; includes d3.js as well as &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Twitter bootstrap&lt;/a&gt; css, jQuery, and some other handy files. The html and file structure is based on &lt;a href=&quot;http://html5boilerplate.com/&quot;&gt;HTML5 Boilerplate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are familiar at all with Ruby and &lt;a href=&quot;http://gembundler.com/&quot;&gt;Bundler&lt;/a&gt; , you should be able to run:&lt;/p&gt;

&lt;pre&gt;
bundle install
thin start
&lt;/pre&gt;

&lt;p&gt;And then open up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://0.0.0.0:3000&lt;/code&gt; in your web browser to view the visualization. This lets you develop your interactive graphic in the comforts of your &lt;a href=&quot;https://www.google.com/chrome&quot;&gt;favorite web-browser&lt;/a&gt; and only move it to iBook Author once you are ready to publish.&lt;/p&gt;

&lt;p&gt;Looking at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js/vis.js&lt;/code&gt; code, you can see this is a pretty basic (i.e. useless) visualization. However it does prove out some important functionality:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Loading of a bundled data file using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.csv&lt;/code&gt; works without any issues.&lt;/li&gt;
  &lt;li&gt;D3’s &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Drag-Behavior&quot;&gt;drag behavior&lt;/a&gt; works well in this environment.&lt;/li&gt;
  &lt;li&gt;Custom css and javascript libraries are possible inside an iBook Widget.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;creating-your-own-vis-widget&quot;&gt;Creating Your Own Vis Widget&lt;/h3&gt;

&lt;p&gt;To create your own vis widget, simply fork or clone this repository, then modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.html&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js/vis.js&lt;/code&gt; to visualize what you want.&lt;/p&gt;

&lt;p&gt;When you have a visualization you like ready, follow these steps:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Create your own Default.png by taking a screen-shot, or otherwise exporting a preview image of your visualization.
** Make sure to get the dimensions right (see below).&lt;/li&gt;
  &lt;li&gt;Tweak your Info.plist as needed (see below).&lt;/li&gt;
  &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; in your vis_widget directory&lt;/li&gt;
  &lt;li&gt;Drag your newly created &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.wdgt&lt;/code&gt; file to iBooks Author&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile&lt;/code&gt; provided is super simple. It just copies the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vis_widget&lt;/code&gt; directory and moves it the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vis.wdgt&lt;/code&gt; without modifying it. It should create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.wdgt&lt;/code&gt; package suitable for transferring to iBooks Author.&lt;/p&gt;

&lt;p&gt;Once in iBooks Author, you can tweak the positioning and styling of the initial display of the widget - removing its title or description as necessary.&lt;/p&gt;

&lt;h3 id=&quot;infoplist&quot;&gt;Info.plist&lt;/h3&gt;

&lt;p&gt;The provided Info.plist will get you pretty far into developing a widget for iBooks, but there might be a few things you want to tweak:&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/vlandham/vis_widget/blob/master/Info.plist#L10&quot;&gt;CFBundleIdentifier&lt;/a&gt; you might want to modify to use your own name.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/vlandham/vis_widget/blob/master/Info.plist#L24&quot;&gt;Height&lt;/a&gt; and &lt;a href=&quot;https://github.com/vlandham/vis_widget/blob/master/Info.plist#L26&quot;&gt;Width&lt;/a&gt; integers might need to be modified if you don’t want use the same size visualization as me.&lt;/p&gt;

&lt;h3 id=&quot;size-issues&quot;&gt;Size Issues&lt;/h3&gt;

&lt;p&gt;When rendering the widget in an iBook, the sizing appears to be dependent on many factors. Not only does the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;height&lt;/code&gt; entries in Info.plist need to be correct, but the dimensions of your Default.png must match up with these dimensions.&lt;/p&gt;

&lt;p&gt;When determining what size to display your widget in, it appears the system uses the smallest dimensions of either the Info.plist or the Default.png. That’s why its important that these both match - and they really are the total size of the visualization you want to use.&lt;/p&gt;

&lt;h3 id=&quot;interactive-textbooks-with-d3&quot;&gt;Interactive Textbooks with D3&lt;/h3&gt;

&lt;p&gt;Hopefully this is enough to at least get you interested in the potential behind interactive visualizations in iBooks.&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;http://vallandingham.me/documents/d3_ibook_example.iba&quot;&gt;download a copy of my iBook file&lt;/a&gt; that includes this D3 visualization.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Installing Galaxy Tools</title>
   <link href="http://vallandingham.me/installing_galaxy_tools.html"/>
   <updated>2012-01-03T00:00:00+00:00</updated>
   <id>http://vallandingham.me/installing_galaxy_tools</id>
   <content type="html">&lt;p&gt;If you followed along with &lt;a href=&quot;http://vallandingham.me/galaxy_install.html&quot;&gt;my galaxy server install guide&lt;/a&gt; you should have a basic but functional Galaxy server on your machine.&lt;/p&gt;

&lt;p&gt;The next step is to get the tools that Galaxy depends on installed and working on this box. Galaxy’s wiki has an (incomplete) &lt;a href=&quot;http://wiki.g2.bx.psu.edu/Admin/Tools/Tool%20Dependencies?action=fullsearch&amp;amp;context=180&amp;amp;value=tool+dependency&amp;amp;titlesearch=Titles&quot;&gt;listing of tool dependencies&lt;/a&gt; . However, they don’t have a lot of information about exactly how Galaxy expects these dependencies to be installed / configured.&lt;/p&gt;

&lt;h2 id=&quot;galaxy-documentation-deficiencies&quot;&gt;Galaxy Documentation Deficiencies&lt;/h2&gt;

&lt;p&gt;From discussions on the mailing list, and poking around in the xml files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;galaxy-dist/tools&lt;/code&gt;, it looks like the most straight forward way to satisfy these requirements is to have executables accessible in your galaxy user’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, with tools that are packaged as jars (like &lt;a href=&quot;http://picard.sourceforge.net/&quot;&gt;picard&lt;/a&gt; ), the jar files must be present in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;galaxy-dist/tool-data/shared/jars&lt;/code&gt; (or a sub-directory of this directory - depending on the package). This caveat is not mentioned anywhere that I can find. It is discussed a bit on the &lt;a href=&quot;http://galaxy-development-list-archive.2308389.n4.nabble.com/How-and-where-to-install-tool-dependencies-td4179574.html&quot;&gt;Galaxy development forum&lt;/a&gt; , but it really is unclear to me how people installing Galaxy are supposed to find out about these critical but obscure details.&lt;/p&gt;

&lt;p&gt;Also, in the &lt;a href=&quot;http://wiki.g2.bx.psu.edu/News%20Briefs/2010_11_24?highlight=%28package%29%7C%28binary%29&quot;&gt;Galaxy news from November 2010&lt;/a&gt;, there is mention of using an external &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;tool_dependency_dir&amp;gt;&lt;/code&gt; to hold &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env.sh&lt;/code&gt; scripts that will be sourced prior to running the command. However, there no documentation as to the best way to take advantage of these sourced files.&lt;/p&gt;

&lt;p&gt;Because of the lack of documentation on how best to use this feature, I decided to take the simple route and get executables accessible from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt; and symlink jar’s into their required directories.&lt;/p&gt;

&lt;h2 id=&quot;biobrew&quot;&gt;Bio.brew&lt;/h2&gt;

&lt;p&gt;I think &lt;a href=&quot;https://github.com/vlandham/bio.brew&quot;&gt;my fork version of bio.brew&lt;/a&gt; is one of the best ways to get started with the installation of these tools.&lt;/p&gt;

&lt;p&gt;Bio.brew is a simple package manager, originally created by &lt;a href=&quot;https://github.com/drio/bio.brew&quot;&gt;David Rio Deiros&lt;/a&gt; with a focus on bioinformatic packages. It is similar to &lt;a href=&quot;https://github.com/mxcl/homebrew&quot;&gt;homebrew&lt;/a&gt; - but without many bells or whistles, and designed to work on both Mac and Linux.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/bio.brew&quot;&gt;My branch of bio.brew&lt;/a&gt; simplifies some of the recipe creation process, and adds additional commands that I found useful (like ‘fake’ to pretend to install a prerequisite package). It also moves towards the idea of maintaining multiple versions of a particular tool, though currently this functionality is pretty basic.&lt;/p&gt;

&lt;p&gt;So the idea is to get bio.brew setup, use it to install tools, and when necessary supplement the install with setup specific to Galaxy.&lt;/p&gt;

&lt;p&gt;In the future, it might be nice to add Galaxy specific functionality to bio.brew to simplify the process even more.&lt;/p&gt;

&lt;h2 id=&quot;biobrew-setup&quot;&gt;Bio.brew setup&lt;/h2&gt;

&lt;p&gt;I think the setup for bio.brew is pretty easy - largely due to it being just bash scripts. As the &lt;a href=&quot;https://github.com/vlandham/bio.brew&quot;&gt;readme&lt;/a&gt; states, simply clone bio.brew and add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BB_INSTALL&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BB_PATH&lt;/code&gt; variables to your environment and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Below are the commands I used to get bio.brew installed and configured. Tools will be installed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/galaxy/tools&lt;/code&gt; (along with bio.brew itself).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# as galaxy user&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /usr/local/galaxy
&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;tools
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;tools
git clone git://github.com/vlandham/bio.brew.git&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then edit your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt; file to include:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BB_INSTALL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/tools
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BB_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/tools/bio.brew
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$BB_INSTALL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$BB_PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;PATH&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;PATH&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This tells bio.brew to install packages into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/tools&lt;/code&gt; and adds the bin directory to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;biobrew-installing-an-executable&quot;&gt;Bio.brew installing an executable&lt;/h2&gt;

&lt;p&gt;So, lets try out installing a required tool. &lt;a href=&quot;http://samtools.sourceforge.net/&quot;&gt;samtools&lt;/a&gt; is required by many Galaxy tools - so it provides a good test case for the bio.brew installation process. With bio.brew, you should be able to install samtools with two commands:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;bb &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;samtools
bb activate samtools&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bb install&lt;/code&gt; pulls down samtools and compiles it, getting everything ready. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bb activate&lt;/code&gt; modifies the bio.brew symlinks used to point to the current version of a tool to point to this new version. The reason it is split up into two commands is to allow for testing of a tool prior to adding it to your path.&lt;/p&gt;

&lt;h2 id=&quot;biobrew-installing-jars&quot;&gt;Bio.brew installing jar’s&lt;/h2&gt;

&lt;p&gt;As mentioned above, we need to symlink jar files to a specific directory for Galaxy to know about them. Here we will install picard using bio.brew and add the .jar files to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;galaxy-dist/tool-data/shared/jars/picard&lt;/code&gt; so Galaxy knows about them. We will use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fake&lt;/code&gt; command to fake install java, as usually java is already installed on your machine and you don’t want to manage it through bio.brew.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;bb fake java
bb &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;picard
bb activate picard

&lt;span class=&quot;c&quot;&gt;# now create symlinks&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /usr/local/galaxy/galaxy-dist/tool-data/shared/jars
&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;picard
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;picard
&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/local/galaxy/tools/stage/picard/current/&lt;span class=&quot;se&quot;&gt;\*&lt;/span&gt;.jar ./&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;restart-galaxy-and-test&quot;&gt;Restart Galaxy and Test&lt;/h2&gt;

&lt;p&gt;Now its time to see if this actually worked. First restart Galaxy using the init script we setup before:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; /etc/init.d/galaxy restart&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now try out the NGS: Picard -&amp;gt; FASTQ to BAM tool in your local Galaxy server on a test fastq file. If all goes well, you should see green all through your history. Enjoy!&lt;/p&gt;

&lt;h2 id=&quot;limitations&quot;&gt;Limitations&lt;/h2&gt;

&lt;p&gt;bio.brew currently doesn’t have all the Galaxy prerequisites in it - but that is something that can be fixed easily. Simply create a new install recipe for the missing tool and contribute it back to bio.brew!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Galaxy Server Install and Setup</title>
   <link href="http://vallandingham.me/galaxy_install.html"/>
   <updated>2011-12-06T00:00:00+00:00</updated>
   <id>http://vallandingham.me/galaxy_install</id>
   <content type="html">&lt;h3 id=&quot;installing-galaxy-on-scientific-linux-6&quot;&gt;Installing Galaxy on Scientific Linux 6&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://main.g2.bx.psu.edu/&quot;&gt;Galaxy&lt;/a&gt; is a platform for managing, running, and sharing computational biology data and pipelines. Its a big idea, and a good idea, but a bit of a task to get working exactly how you might want it.&lt;/p&gt;

&lt;p&gt;What follows is a brain dump of the initial setup and configuration of this tool. Sorry about the length.&lt;/p&gt;

&lt;h2 id=&quot;goals-for-sever-configuration&quot;&gt;Goals for sever configuration&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Follow all recommended settings for production level Galaxy server&lt;/li&gt;
  &lt;li&gt;Use Nginx proxy front-end
    &lt;ul&gt;
      &lt;li&gt;Enable as much of proxy components as possible&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Use local postgreSQL server&lt;/li&gt;
  &lt;li&gt;Try to make these instructions as complete as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Future goals for follow up configuration include&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Enable and configure as many of the tools as possible&lt;/li&gt;
  &lt;li&gt;Provide easy access to local directories of sequencing data inside Galaxy&lt;/li&gt;
  &lt;li&gt;Experiment with with Galaxy Toolshed&lt;/li&gt;
  &lt;li&gt;Experiment with cluster configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;about-the-system&quot;&gt;About the System&lt;/h2&gt;

&lt;p&gt;Scientific Linux release 6.1 (Carbon)&lt;/p&gt;

&lt;p&gt;Will use separate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;galaxy&lt;/code&gt; user to run galaxy&lt;/p&gt;

&lt;p&gt;Galaxy user’s home directory will be located:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/galaxy&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;p&gt;Most information comes from &lt;a href=&quot;http://www.agapow.net/science/bioinformatics/galaxy/installing-galaxy&quot;&gt;apapow.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And &lt;a href=&quot;http://wiki.g2.bx.psu.edu/Admin/Config/Performance/Production%20Server&quot;&gt;the galaxy wikis Production Server page&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;check-base-install&quot;&gt;Check base install&lt;/h2&gt;

&lt;h3 id=&quot;ensure-python-is-installed-and-at-26&quot;&gt;Ensure python is installed and at 2.6&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;which python

&lt;span class=&quot;c&quot;&gt;# /usr/bin/python&lt;/span&gt;

python &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Python 2.6.6&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;ensure-postgresql-is-installed&quot;&gt;Ensure PostgreSQL is installed&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;postgresql postgresql-server&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;modify-postgresql-config-file&quot;&gt;Modify PostgreSQL config file&lt;/h2&gt;

&lt;p&gt;Tricky part to getting postgreSQL working is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pg_hba.conf&lt;/code&gt; file. Edit it to allow local connections.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /var/lib/pgsql/data/pg_hba.conf&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;http://www.depesz.com/index.php/2007/10/04/ident/&quot;&gt;A blog post explaining the syntax of this file&lt;/a&gt; . It should look something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
host all all 0.0.0.0/0 md5&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;startup-postgresql&quot;&gt;Startup PostgreSQL&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;service postgresql initdb
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;chkconfig postgresql on
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;service postgresql start&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;add-galaxy-user&quot;&gt;Add galaxy user&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;galaxy&lt;/code&gt; user created here is not capable of using sudo. Every time sudo is used in this document, it is done from a sudo capable user.&lt;/p&gt;

&lt;p&gt;Galaxy user’s home directory is at:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/galaxy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This was done because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home&lt;/code&gt; is a remotely mounted disk.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; /usr/sbin/useradd galaxy &lt;span class=&quot;nt&quot;&gt;--home&lt;/span&gt; /usr/local/galaxy
passwd galaxy&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;install-dependency-packages&quot;&gt;Install dependency packages&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# install git just to have&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;git

&lt;span class=&quot;c&quot;&gt;# install mercurial to download galaxy&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;mercurial&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;install-galaxy&quot;&gt;Install Galaxy&lt;/h2&gt;

&lt;h3 id=&quot;switch-to-galaxy-user&quot;&gt;Switch to galaxy user&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;su galaxy
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;download-galaxy&quot;&gt;Download galaxy&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;hg clone https://bitbucket.org/galaxy/galaxy-dist&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;download-virtualenv&quot;&gt;Download virtualenv&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;wget https://raw.github.com/pypa/virtualenv/master/virtualenv.py&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;create-sand-boxed-python-using-virtualenv&quot;&gt;Create sand-boxed Python using virtualenv&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;python ./virtualenv.py &lt;span class=&quot;nt&quot;&gt;--no-site-packages&lt;/span&gt; galaxy_env
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; ./galaxy_env/bin/activate
which python

&lt;span class=&quot;c&quot;&gt;# ~/galaxy_env/bin/python&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;configure-galaxy-user&quot;&gt;Configure galaxy user&lt;/h3&gt;

&lt;p&gt;Edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; to define &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TEMP&lt;/code&gt; and to add virtualenv source&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/galaxy_env/bin/activate

&lt;span class=&quot;nv&quot;&gt;TEMP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;HOME/galaxy-dist/database/tmp
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;TEMP&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ensure that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bash_profile&lt;/code&gt; sources &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# this should be in ~/.bash_profile&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.bashrc &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;setup-postgresql-database-for-galaxy&quot;&gt;Setup PostgreSQL database for Galaxy&lt;/h2&gt;

&lt;p&gt;Login as postgres user&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;su - postgres&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Use createdb to create new database for galaxy&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;createdb galaxy_prod&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Connect to database using psql&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;psql galaxy_prod&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Create galaxy user for PostgreSQL database&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;USER&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;galaxy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WITH&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PASSWORD&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'password'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;GRANT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIVILEGES&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DATABASE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;galaxy_prod&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;galaxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Test galaxy PostgreSQL user.&lt;/p&gt;

&lt;p&gt;Exit out of postgres user. Return to galaxy user and then attempt to connect to database.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Visualizing the Racial Divide</title>
   <link href="http://vallandingham.me/visualizing_the_racial_divide.html"/>
   <updated>2011-10-20T00:00:00+00:00</updated>
   <id>http://vallandingham.me/visualizing_the_racial_divide</id>
   <content type="html">&lt;h3 id=&quot;using-d3-and-force-directed-maps-to-see-the-impact-of-segregation-in-cities&quot;&gt;Using d3 and force-directed maps to see the impact of segregation in cities&lt;/h3&gt;

&lt;p&gt;I wanted to create a visualization to highlight the impact of the deep segregation that still exists in many US cities today. I think the Choropleth maps like those in &lt;a href=&quot;http://www.salon.com/2011/03/29/most_segregated_cities/slide_show&quot;&gt;Salon’s most segregated urban areas slide-show&lt;/a&gt; are great in terms of showing the reality of this problem. I wanted to come up with a more visual and perhaps more visceral way to show these racial divides and how they serve as real boundaries in and around communities.&lt;/p&gt;

&lt;h3 id=&quot;force-directed-maps&quot;&gt;Force-Directed Maps&lt;/h3&gt;

&lt;p&gt;Originally, I thought about using elevation to show these breaks, similar to &lt;a href=&quot;http://weburbanist.com/2010/09/17/criminal-contours-crime-rates-as-topographic-maps/&quot;&gt;these topographical crime rate maps&lt;/a&gt; . This still might be interesting to experiment with, but I decided to try to stick to a 2D method.&lt;/p&gt;

&lt;p&gt;Force-directed maps is a name you could give to a force-directed graph made up of neighboring components of a map. &lt;a href=&quot;http://twitter.com/#!/mbostock&quot;&gt;Mike Bostock&lt;/a&gt; has demonstrated them a few times using a map of the United States: both in his &lt;a href=&quot;http://mbostock.github.com/d3/talk/20110921/#18&quot;&gt;Trulia Talk&lt;/a&gt; and his &lt;a href=&quot;http://mbostock.github.com/d3/talk/20111018/#32&quot;&gt;SVG Open Keynote&lt;/a&gt; . Here’s his example:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://vallandingham.me/images/vis/force_directed_states.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I decided to use this concept to show how segregation in a city can ‘break it apart’. Here’s an example from Kansas City:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/vis/racial_divide.html&quot;&gt;&lt;img src=&quot;http://vallandingham.me/images/vis/kc_divide_before_after.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/vis/racial_divide.html&quot;&gt;See animated visualizations for a number of cities here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The visualization uses &lt;a href=&quot;http://mbostock.github.com/d3/&quot;&gt;d3.js&lt;/a&gt; and works best with Google Chrome.&lt;/p&gt;

&lt;p&gt;Cities were picked from the &lt;a href=&quot;http://www.censusscope.org/2010Census/FREY2010BLK100MetroSeg.xls&quot;&gt;list of most segregated cities&lt;/a&gt;, ordered from most to least.&lt;/p&gt;

&lt;h3 id=&quot;about-the-visualization&quot;&gt;About the Visualization&lt;/h3&gt;

&lt;p&gt;Data is from the 2010 Census, at the tract level. The links are hidden, but each tract is connected to each of its neighbors. The lengths of these connections encode the disparity between racial make-up between neighboring tracts. So, if a ‘mostly white’ tract is connected to another ‘mostly white’ tract, then the connection is short. If a city had uniform proportions of races in each tract, the map would not move much. However, longer connections occur where there is a sharp change in the proportions of white and black populations between neighboring tracts. These longer connections create rifts in the map and force areas apart, in some ways mimicking the real-world effects of these racial lines.&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts on these visualization style. Certainly it is not really meant to provide exact numbers. These maps only encode differences between white and black populations. It would be interesting to include other racial divides as well. The line length encoding also has some issues when there are few neighbors around with short connections. This can be seen in the smaller towns such as Wichita. Large cities like Chicago have too many tracts to keep the animation smooth.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Designing Data Visualizations Review</title>
   <link href="http://vallandingham.me/designing_data_visualizations_review.html"/>
   <updated>2011-10-07T00:00:00+00:00</updated>
   <id>http://vallandingham.me/designing_data_visualizations_review</id>
   <content type="html">&lt;p&gt;Having just finished reading &lt;a href=&quot;http://shop.oreilly.com/product/0636920022060.do&quot;&gt;Designing Data Visualization&lt;/a&gt; by &lt;a href=&quot;http://twitter.com/#!/noahi&quot;&gt;Noah Iliinsky&lt;/a&gt; and &lt;a href=&quot;http://twitter.com/#!/jsteeleeditor&quot;&gt;Julie Steele&lt;/a&gt;, I wanted to provide a short review of this book.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://vallandingham.me/images/ddv.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;ddvs-focus&quot;&gt;DDV’s Focus&lt;/h3&gt;

&lt;p&gt;DDV was made for people like me in mind: novices in the world of data visualization. From the preface, we read that the book’s purpose is to provide a high-level overview of the visualization landscape:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It will give you the general lay of the land. It is a set of steps and rules to follow that will get you 80% of the way to turning out great work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think this is a worthy goal - and one that this book is successful at.&lt;/p&gt;

&lt;p&gt;At first, I was surprised a bit by the physical size of the book. In the same Amazon purchase, I also had grabbed &lt;a href=&quot;http://www.amazon.com/Visualize-This-FlowingData-Visualization-Statistics/dp/0470944889/&quot;&gt;Visualize This&lt;/a&gt; and &lt;a href=&quot;http://www.amazon.com/Show-Me-Numbers-Designing-Enlighten/dp/0970601999/&quot;&gt;Show Me the Numbers&lt;/a&gt; . Compared to these two, Designing Data Visualizations is tiny: roughly 85 pages of content, with another 10 pages of appendix. However, given the goal of this work - I believe the size is appropriate. The appendix includes a checklist to go over when designing visualizations. Much of this book then serves to elaborate, explain, and justify this checklist as a way of creating solid visualizations. I think when attempting to explain an entire framework for how visualizations should be created, succinctness is important, less the reader gets lost in the details.&lt;/p&gt;

&lt;h3 id=&quot;ddvs-content&quot;&gt;DDV’s Content&lt;/h3&gt;

&lt;p&gt;Designing Data Visualizations is broken up into two parts. Part 1 is short, only two chapters, and serves to provide a vocabulary of visualization types and approaches to categorizing these types. The preface also includes a section entitled “What We Mean When We Say…” which is very reminiscent of the recent &lt;a href=&quot;http://flowingdata.com/2011/09/29/the-many-words-for-visualization/&quot;&gt;The Many Words for Visualization&lt;/a&gt; from &lt;a href=&quot;http://flowingdata.com/&quot;&gt;Flowing Data&lt;/a&gt; . I found these definitions to be very useful in defining this vocabulary, and though some definitions are repeated in chapters 1 and 2, I wish they had fleshed out this list as a third chapter. It would have provided a more comprehensive ‘language of visualization’. As it stands, its still a good list.&lt;/p&gt;

&lt;p&gt;Part 2 is where the meat of the book is, as stated in the Preface:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The goal is to help you think in a linear way about how to select and apply appropriate encodings for your data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The encoding of data dimensions into visual components is something I have been really looking for more info on - and where Designing Data Visualizations shines. DDV provides a clean, systematic way of understanding, prioritizing, and applying the myriad of the possible encodings available to visualization designers.&lt;/p&gt;

&lt;p&gt;Encoding of data is certainly a main topic of other data visualization books and papers. The &lt;a href=&quot;http://fellinlovewithdata.com/guides/7-classic-foundational-vis-papers&quot;&gt;Classic Paper Reading List&lt;/a&gt; from &lt;a href=&quot;http://fellinlovewithdata.com/&quot;&gt;Fell in Love with Data&lt;/a&gt; , for example, includes &lt;em&gt;Graphical Perception: Theory, Experimentation, and Application to the Development of Graphical Methods&lt;/em&gt;, which is mainly on encoding. And as Enrico summarizes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[V]isual encoding is hard stuff and you shouldn’t take it too lightly. And that visual primitives do have a ranking that you have to take into account if you want to design effective data visualizations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DDV takes these various encoding discussions, combines them, and presents them as part of a larger design framework. This framework for how to think and design visualizations is great and a process that can be immediately followed by beginners and customized or altered by more experienced data encoders. The framework encompasses a lot of topics. Some highlights include: using position as a primary encoding, the proper use of colors, and some pitfalls to avoid - especially when dealing with circle-based graphs.&lt;/p&gt;

&lt;p&gt;DDV doesn’t spend a lot of ink talking about the specifics of different types of graphs, like bar charts, steamgraphs, etc (although a nice organized list is given). I think this is a good thing. &lt;a href=&quot;http://flowingdata.com/2011/09/29/the-many-words-for-visualization/&quot;&gt;Visualize This&lt;/a&gt; as well as texts like &lt;a href=&quot;http://benfry.com/phd/&quot;&gt;Ben Fry’s PhD Thesis&lt;/a&gt; already provide through introductions to chart types. Duplication of this effort of “chart enumeration” in DDV would have made many readers of this book glaze over a bit.&lt;/p&gt;

&lt;h3 id=&quot;ddvs-weaknesses&quot;&gt;DDV’s Weaknesses&lt;/h3&gt;

&lt;p&gt;I have two small issues with the text. The first of which is the format that I purchased it in.&lt;/p&gt;

&lt;p&gt;This is one of the first books I’ve read in a physical form where I thought it would have been better experienced in the digital version instead. I like reading on paper still, underlining, making notes and what-not (perhaps I should finally buy a Kindle). This book is printed in gray-scale only, but many of the example charts and graphs discussed in it don’t really make a lot of sense unless you are looking at the color versions. This is mentioned explicitly at the end of the prefix, with a link providing access to the full-color versions. However, jumping back and forth between a book and a screen is distracting and sometimes not possible (another reason I like books is to get away from my computer screen for awhile). This is why I would recommend getting the ebook version of this text - or even better - get the bundled version and have the digital copy at the ready for viewing graphics.&lt;/p&gt;

&lt;p&gt;Secondly, I think they could have structured the reading list in the appendix a bit to provide more of a guided tour of where to go next in developing a strong data visualization design process. The goal of this book is to “start you down the path” of data visualization - which it does nicely. Now that you are on the path, however, what direction do you go at the crossroads?&lt;/p&gt;

&lt;p&gt;That said, the reading list is still very valuable - and includes many more texts I plan on picking up. I just wish they had ended it with a nice big sign that said “Now Go Here for another 10%”. Perhaps the authors are planning a sequel…&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;All in all, &lt;a href=&quot;http://shop.oreilly.com/product/0636920022060.do&quot;&gt;Designing Data Visualizations&lt;/a&gt; is a great resource for individuals just getting started in the visualization world, and I would guess it will be valuable for experienced designers as well, as a way to organize their processes in the context of data design framework. The book is relatively short and to the point. No words are extraneous. The ink is maximized for content. I would recommend getting the digital copy, if possible, for the smoothest reading experience.&lt;/p&gt;

&lt;p&gt;Thanks very much to Julie and Noah for this great resource!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>From Shapefile to GeoJSON</title>
   <link href="http://vallandingham.me/shapefile_to_geojson.html"/>
   <updated>2011-09-30T00:00:00+00:00</updated>
   <id>http://vallandingham.me/shapefile_to_geojson</id>
   <content type="html">&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;UPDATE - Feb 11, 2015&lt;/strong&gt;
This is an old post, and needed some love. I’ve updated it a bit with the following changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/vlandham/d3_geojson_example&quot;&gt;New github repo&lt;/a&gt; - for the D3 visualization part at the end&lt;/li&gt;
  &lt;li&gt;Automatically determines the projection’s scale and translation (from a &lt;a href=&quot;http://bl.ocks.org/mbostock/4707858&quot;&gt;Bostock Example&lt;/a&gt; ) - so this should work easier for any geojson file generated.&lt;/li&gt;
  &lt;li&gt;JavaScript as well as CoffeeScript implementations for the D3 part.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hope this helps keep the content relevant. Let me know if you see improvements that could be made!&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;a-method-for-editing-merging-simplifying-and-converting-shapefiles-to-geojson&quot;&gt;A method for editing, merging, simplifying, and converting Shapefiles to GeoJSON&lt;/h3&gt;

&lt;p&gt;FYI - You might also want to check out &lt;a href=&quot;http://bost.ocks.org/mike/map/&quot;&gt;Mike Bostock’s Let’s Make a Map&lt;/a&gt; post which covers a lot of the same ground.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mbostock.github.com/d3/&quot;&gt;D3.js&lt;/a&gt; supports cartographic visualizations by being able to display &lt;a href=&quot;https://github.com/mbostock/d3/wiki/Geo-Paths&quot;&gt;lines, polygons, and other geometry objects&lt;/a&gt; . It uses &lt;a href=&quot;http://geojson.org/&quot;&gt;GeoJSON&lt;/a&gt; as the storage format for this type of visualization.&lt;/p&gt;

&lt;p&gt;Likewise, map tiling libraries like &lt;a href=&quot;http://leafletjs.com/&quot;&gt;Leaflet&lt;/a&gt; can &lt;a href=&quot;http://leafletjs.com/examples/geojson.html&quot;&gt;use GeoJSON to create map layers&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;You can find some GeoJSON files around, like in &lt;a href=&quot;http://mbostock.github.com/d3/ex/choropleth.html&quot;&gt;D3’s choropleth example&lt;/a&gt; , but sooner or later you will want to visualize a more specific portion of the world.&lt;/p&gt;

&lt;p&gt;Specifically, I am interested in visualizing census data for my hometown: Kansas City. Kansas City is perhaps a bit unusual, from a census point of view, as it is actually two cities in two different states: &lt;a href=&quot;http://en.wikipedia.org/wiki/Kansas_City,_Kansas&quot;&gt;Kansas&lt;/a&gt; , and &lt;a href=&quot;http://en.wikipedia.org/wiki/Kansas_City,_Missouri&quot;&gt;Missouri&lt;/a&gt; . Also, I’m not really interested in the rest of these states - just the Kansas City metro area. So what I really want to do is merge multiple Shapefiles, cut out the interesting section, and convert this to GeoJSON. Making it as small as possible (in terms of filesize) in the process.&lt;/p&gt;

&lt;p&gt;Below is how I created a small GeoJSON file of just the KC metro from census shapefiles.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; I am not an expert in &lt;a href=&quot;http://en.wikipedia.org/wiki/Geographic_information_system&quot;&gt;GIS&lt;/a&gt; or cartography in general. This may not be the best way to get a custom GeoJSON. In fact, cutting up shapefiles into custom GeoJSON files might not even be a good idea in the first place. However, if you want to look at small piece of the world in D3 or other GeoJSON capable tools, this might be a way to start.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;

&lt;p&gt;I’m using a mix of different applications to perform this conversion:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.qgis.org/&quot;&gt;Quantum GIS&lt;/a&gt; is used to deal with shapefiles.
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; I ran into a few issues trying to get QGIS installed on my Mac - though a Mac version is available. So instead of fighting this, I just used the Windows version on an XP machine. This all &lt;strong&gt;should&lt;/strong&gt; be possible using just the Mac version, but the screenshots will be of Windows.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://mapshaper.org/&quot;&gt;MapShaper&lt;/a&gt; a free online tool is used to simplify the Shapefile and reduce its filesize.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.gdal.org/&quot;&gt;GDAL&lt;/a&gt; is used to convert shapefiles to GeoJSON. I was able to install this easily on my Mac using homebrew:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;brew install gdal
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Initially I did run into an issue with homebrew when it was installing the &lt;strong&gt;geos&lt;/strong&gt; prerequisite. Following the &lt;a href=&quot;https://github.com/mxcl/homebrew/issues/7049&quot;&gt;instructions on this github issue&lt;/a&gt; fixed this. GDAL would also work on a Linux box, and there looks to be a &lt;a href=&quot;http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries&quot;&gt;Windows port&lt;/a&gt; as well.&lt;/p&gt;

&lt;h3 id=&quot;getting-the-data&quot;&gt;Getting the Data&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://census.ire.org/data/bulkdata.html&quot;&gt;Census.ire.org&lt;/a&gt; provides a way to download census 2010 data, including shapefiles of the tracts / counties the data is for. I downloaded Shapefiles for Kansas and Missouri at the &lt;strong&gt;Census Tract&lt;/strong&gt; Summary Level. The files together are over 10MB in size, and transforming them into GeoJSON at this stage creates over 30MB of data - too much to render in the browser all at once. Certainly there are more sophisticated ways to deal with this issue, but for the time, I just want to explore some KC data quickly.&lt;/p&gt;

&lt;h3 id=&quot;merging-shapefiles&quot;&gt;Merging Shapefiles&lt;/h3&gt;

&lt;p&gt;Open up Quantum GIS and select Add Vector Layer as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/images/gis/02_qgis_gui.png&quot;&gt;&lt;img src=&quot;http://vallandingham.me/images/gis/02_qgis_gui_small.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Browse&lt;/strong&gt; under Source and select your Shapefile. Repeat if you have multiple shape files. Here’s Mine with both Kansas and Missouri open:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/images/gis/04_qgis_ks_and_mo.png&quot;&gt;&lt;img src=&quot;http://vallandingham.me/images/gis/04_qgis_ks_and_mo_small.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Merging these layers was tricky (for me). I ended up needing the &lt;a href=&quot;http://michaelminn.com/linux/mmqgis/&quot;&gt;MMQGIS&lt;/a&gt; plugin for merging. To install this, first select Plugins -&amp;gt; Fetch Python Plugins. In the Repositories tab, I selected &lt;strong&gt;Add 3rd party repositories&lt;/strong&gt;. When it adds the plugin repositories, it seems to get stuck on one of them. Clicking &lt;strong&gt;Abort&lt;/strong&gt; will let you continue without this repo. In the plugins tab, search for MMQGIS, select it, and then click &lt;strong&gt;Install plugin&lt;/strong&gt;. Then you should be good to go.&lt;/p&gt;

&lt;p&gt;With this plugin installed, you will have a new menu item under Plugins called &lt;strong&gt;mmqgis&lt;/strong&gt;. Navigate here, then select &lt;strong&gt;Merge Layers&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/images/gis/07_qgis_merge_layers.png&quot;&gt;&lt;img src=&quot;http://vallandingham.me/images/gis/07_qgis_merge_layers_small.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the Shapefile layers you want to merge then select a location to save the merged Shapefile. After this, you should have an additional Shapefile with all the geometry from your multiple Shapefiles in one file.&lt;/p&gt;

&lt;h3 id=&quot;selecting-a-portion-of-shapefile&quot;&gt;Selecting a Portion of Shapefile&lt;/h3&gt;

&lt;p&gt;Ok, maybe your region doesn’t exist in multiple Shapefiles, but some times you don’t want to deal with an entire state’s worth of data with visualizing. Use the “Select features by rectangle” tool to highlight the portion of the merged Shapefile you are interested in. Holding down Ctrl allows you to add / remove individual sections as well. Once you are satisfied with your selection, right click on the merged Shapefile in the left-hand Layers table, and select &lt;strong&gt;Save selection as&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/images/gis/10_qgis_save_selection.png&quot;&gt;&lt;img src=&quot;http://vallandingham.me/images/gis/10_qgis_save_selection_small.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And presto! You should now have a Shapefile of the smaller selection saved on your system. You can open it back up with Quantum GIS, but for the rest of the tutorial, we will be done with this application.&lt;/p&gt;

&lt;h3 id=&quot;simplifying-a-shapefile&quot;&gt;Simplifying a Shapefile&lt;/h3&gt;

&lt;p&gt;To reduce size further, you might want to simplify your Shapefile. This looks to be possible in Quantum GIS, but I wanted to try out &lt;a href=&quot;http://mapshaper.org/&quot;&gt;MapShaper&lt;/a&gt; which is recommended in the D3 documentation. Click launch, and upload the .shp file from the output of your Quantum GIS work.&lt;/p&gt;

&lt;p&gt;I don’t have a good idea of how simplified you can go, but for Census Tract Shapefiles, I didn’t see much degradation even at 50% simplification level. When happy, click &lt;strong&gt;export&lt;/strong&gt; in the upper right-hand corner and choose &lt;strong&gt;Shapefile - polygons&lt;/strong&gt;. Download the two resulting files.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;
For the next step, we want to maintain the ‘properties’ section populated by data from the Shapefiles. Do ensure this section isn’t empty, &lt;strong&gt;replace&lt;/strong&gt; your .shp and .shx files with these simplified versions, and don’t remove the rest of the files. This is to say delete your original .shp / .shx files and rename these simplified versions to match your old ones. Let me know if that doesn’t make sense.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;converting-to-geojson-using-gdal&quot;&gt;Converting to GeoJSON using GDAL&lt;/h3&gt;

&lt;p&gt;Transfer these files to your Mac / Linux machine. You should have a folder with all the Shapefile files. Now we want to create a GeoJSON file for D3 to use from these files. Using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ogr2ogr&lt;/code&gt; command to do this is pretty straightforward. It would look something like:&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;ogr2ogr -f geoJSON kc.json kc.shp
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that the output file name comes &lt;strong&gt;before&lt;/strong&gt; the input file name.&lt;/p&gt;

&lt;p&gt;You should now have a GeoJSON file of your custom Census Tract section, ready to be used in D3.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/vlandham/d3_geojson_example/blob/master/data/kc_tracts.json&quot;&gt;Here is my KC Metro GeoJSON file&lt;/a&gt; . You can see (if click on a tract) that the &lt;strong&gt;properties&lt;/strong&gt; object maintains the information necessary to map the GeoJSON feature back to a Census Tract.&lt;/p&gt;

&lt;h3 id=&quot;display-in-d3&quot;&gt;Display in D3&lt;/h3&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Update Feb 11, 2015&lt;/strong&gt;
Now this code has its own github repo: &lt;a href=&quot;https://github.com/vlandham/d3_geojson_example&quot;&gt;d3 geojson example&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;As a test, I wanted to display my new GeoJSON file in D3. Make sure to include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.geo.min.js&lt;/code&gt; in addition to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d3.min.js&lt;/code&gt; for the path functions. Below is the minimum amount of code I used to display this GeoJSON file using D3 and coffeescript (and I now have a &lt;a href=&quot;https://github.com/vlandham/d3_geojson_example/blob/master/js/vis.js&quot;&gt;JavaScript version implemented in the repo&lt;/a&gt; ). This assumes that there is a div with the id of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vis&lt;/code&gt; &lt;a href=&quot;https://github.com/vlandham/d3_geojson_example/blob/master/index.html&quot;&gt;in your html&lt;/a&gt; .&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/vlandham/db0b55dab7322eed173a.js&quot;&gt;
&lt;/script&gt;

&lt;p&gt;This is mostly the same code as the &lt;a href=&quot;http://mbostock.github.com/d3/ex/choropleth.html&quot;&gt;D3’s choropleth example&lt;/a&gt; . This now figures out the translation and scale automatically, &lt;a href=&quot;http://bl.ocks.org/mbostock/4707858&quot;&gt;thanks to Mike&lt;/a&gt; once again.&lt;/p&gt;

&lt;p&gt;I also use the “STATEFP10” property of each tract to determine the fill color. This results in different colors for Kansas and Missouri, to show that these properties are present in the simplified GeoJSON. Here’s an image of the result:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vallandingham.me/images/gis/kc_tracts.png&quot;&gt;&lt;img src=&quot;http://vallandingham.me/images/gis/kc_tracts_small.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is certainly just a start to the possibilities of using D3 and geojson. As mentioned at the top, Mike Bostock also has an &lt;a href=&quot;http://bost.ocks.org/mike/map/&quot;&gt;amazing map making tutorial&lt;/a&gt; that focuses on the benefits of topojson - so check that out!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Recreating Old Visualizations with New Technology</title>
   <link href="http://vallandingham.me/recreating_old_vis_with_new_tech.html"/>
   <updated>2011-09-26T00:00:00+00:00</updated>
   <id>http://vallandingham.me/recreating_old_vis_with_new_tech</id>
   <content type="html">&lt;h3 id=&quot;using-d3-and-coffeescript-to-reproduce-old-charts&quot;&gt;Using d3 and coffeescript to reproduce old charts&lt;/h3&gt;

&lt;p&gt;Recently, I stumbled upon a set of statistical charts from the 1800-1900’s in the &lt;a href=&quot;http://www.davidrumsey.com/luna/servlet/view/search?QuickSearchA=QuickSearchA&amp;amp;q=statistics&amp;amp;sort=Pub_List_No_InitialSort%2CPub_Date%2CPub_List_No%2CSeries_No&amp;amp;search=Search&quot;&gt;David Rumsey Map Collection&lt;/a&gt; . While perhaps not the best forms of data visualization by today’s standards (pie charts, stacked bar charts, etc), they serve as beautiful inspirations visualization techniques due to their organization, attention to detail, color scheme, and presentation.&lt;/p&gt;

&lt;p&gt;Here’s an example from the collection:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.davidrumsey.com/luna/servlet/detail/RUMSEY~8~1~32117~1151459:Proportion-of-foreign-born-of-each-?qvq=q:%3D%22U.S.%2BCensus%2BOffice%22%2BAND%2B%3D%22Washington%22;lc:RUMSEY~8~1&amp;amp;mi=144&amp;amp;trs=288&quot;&gt;&lt;img src=&quot;images/vis/rumsey_stat_1.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on the mantra’s of &lt;a href=&quot;http://fellinlovewithdata.com/guides/how-to-become-a-data-visualization-expert-a-recipe&quot;&gt;Enrico Bertini&lt;/a&gt; on &lt;a href=&quot;http://fellinlovewithdata.com&quot;&gt;Fell in Love with Data&lt;/a&gt; and perhaps also the guidelines of creativity from &lt;a href=&quot;http://www.everythingisaremix.info/shop-now-open/&quot;&gt;Everything is a Remix&lt;/a&gt;, I wanted to try to recreate (copy) a small selection of these charts using modern tools.&lt;/p&gt;

&lt;p&gt;I choose to try out &lt;a href=&quot;http://mbostock.github.com/d3/&quot;&gt;d3.js&lt;/a&gt; for this experiment. This is a javascript framework that is the official successor to the popular &lt;a href=&quot;http://mbostock.github.com/protovis/&quot;&gt;Protovis&lt;/a&gt; visualization toolkit. d3 allows you to represent your data with native SVG elements, which provides a lot of power in terms of layout and style. Furthermore, to make writing javascript more fun, I wrote the visualizations in &lt;a href=&quot;http://jashkenas.github.com/coffee-script/&quot;&gt;coffeescript&lt;/a&gt; - a language that compiles down to javascript.&lt;/p&gt;

&lt;p&gt;The process of recreating these graphs was a lot of fun and results are in &lt;a href=&quot;vis/index.html#old_vis_d3&quot;&gt;my visualization section&lt;/a&gt; . Here’s an image of my d3 version of the example above (&lt;a href=&quot;vis/nationality_by_city.html&quot;&gt;click&lt;/a&gt; for the actual d3 version):&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;vis/nationality_by_city.html&quot;&gt;&lt;img src=&quot;images/vis/rumsey_stat_1_recreate.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Though I only have a few examples (3 right now, but I hope to have time to make more), I believe it shows some of the potential power of d3 in terms of customizing exactly how you want your visualizations to look. In the future, I might look at adding functionality like interactions and transformations of the raw data - all of which should be pretty easy with d3.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RNA-seq: Comparing Similar Libraries</title>
   <link href="http://vallandingham.me/Comparing-RNA-seq-Data.html"/>
   <updated>2011-08-10T00:00:00+00:00</updated>
   <id>http://vallandingham.me/Comparing-RNA-seq-Data</id>
   <content type="html">&lt;p&gt;This task involves comparing RNA-seq data generated from 3 similar libraries. The difference between the libraries is the number of cells collected to be used in the construction of the libraries. This dataset contains 2 samples each from libraries constructed from 1,000, 10,000 and 30,000 mouse bone marrow derived hematopoietic stem cells.&lt;/p&gt;

&lt;p&gt;The idea, as it was explained to me, is to see if researchers can get away with small cell numbers when constructing libraries for use with RNA-seq. Specifically, what do you loose in your data as you use lower and lower cell numbers.&lt;/p&gt;

&lt;p&gt;Not a very concrete question, but perhaps a good one all the same.&lt;/p&gt;

&lt;h2 id=&quot;analysis-goals&quot;&gt;Analysis Goals&lt;/h2&gt;

&lt;p&gt;Discussing with other analysts about what to do, Here are some questions I’d like to answer during analysis:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What is the percent FPKM change as we move from higher number of cells to lower number?&lt;/li&gt;
  &lt;li&gt;How does gene coverage change from high to low?
    &lt;ul&gt;
      &lt;li&gt;Does coverage overall go down with fewer cell numbers?&lt;/li&gt;
      &lt;li&gt;Are there spots in the exome that are lacking in the low cell number samples that have coverage in the higher cell number samples?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;How do the numbers of multi-reads change?
    &lt;ul&gt;
      &lt;li&gt;Multi-reads are those reads that map to multiple places on the genome. Does the percentage of the total number of aligned reads that are considered multi-reads increase in low cell number samples?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Does the absolute number of genes covered at all by the data change?
    &lt;ul&gt;
      &lt;li&gt;Here we would like to see if more cells provide more information in terms of the number of genes found in the data. We might expect that the lower cell numbers would have more genes missing from the RNA-seq data, due to lower coverage.&lt;/li&gt;
      &lt;li&gt;Information could be graphed with cell numbers on x-axis, and on the y-axis, show the percentage of the total number of genes of the organism that were detected in the data.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;tools-used&quot;&gt;Tools Used&lt;/h2&gt;

&lt;p&gt;It is my attempt to get a cohesive picture of each of these datasets, so as to better understand what is different about them. So I used a number of tools that can provide various details about the dataset, along with the normal alignment and RPKM tools.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://tophat.cbcb.umd.edu/manual.html&quot;&gt;TopHat&lt;/a&gt; v1.3.1&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://cufflinks.cbcb.umd.edu/tutorial.html&quot;&gt;Cufflinks&lt;/a&gt; v1.0.3&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://samtools.sourceforge.net&quot;&gt;Samtools&lt;/a&gt; v0.1.16&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://picard.sourceforge.net/&quot;&gt;picard&lt;/a&gt; v1.49&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://code.google.com/p/bedtools/&quot;&gt;BEDTools&lt;/a&gt; v2.12&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.bioinformatics.bbsrc.ac.uk/projects/fastqc/&quot;&gt;fastqc&lt;/a&gt; v0.9.3&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://hannonlab.cshl.edu/fastx_toolkit/&quot;&gt;FASTX-Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;pipeline&quot;&gt;Pipeline&lt;/h2&gt;

&lt;p&gt;The initial process is similar to my previous RNA-seq analysis. However after alignment and RPKM values are determined, we need to do a lot more analysis to see patterns between datasets&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;fastqc for initial read quality&lt;/li&gt;
  &lt;li&gt;Align with TopHat&lt;/li&gt;
  &lt;li&gt;Cufflinks for RPKM values&lt;/li&gt;
  &lt;li&gt;picard for alignment metrics&lt;/li&gt;
  &lt;li&gt;BEDTools to discover gene coverage&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’ll avoid explaining all the parameters again for the tools used, but go over how they were used in the analysis.&lt;/p&gt;

&lt;h3 id=&quot;removing-duplicates&quot;&gt;Removing Duplicates&lt;/h3&gt;

&lt;p&gt;As before, no duplication removal was performed. It seems that this would remove information that could be valuable to this particular analysis.&lt;/p&gt;

&lt;h3 id=&quot;trimming&quot;&gt;Trimming&lt;/h3&gt;

&lt;p&gt;The initial look at the data using fastqc indicated serious degradation of the quality of some of the samples’ reads after 25bp. This is unfortunate, and perhaps indicates that the analysis with not be as fruitful as one would like. However, the analysis must go on! FastX was used to trim the samples from all libraries to 25bp. This deals with the bad quality of some of the reads, and prevents biases that would be present for longer reads, if all of the samples were not trimmed.&lt;/p&gt;

&lt;p&gt;Here’s how Fastx was called:&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;zcat sequence.fastq.gz | fastx_trimmer -f 1 -l 25 -z -o sequence.trim.fastq.gz -Q33
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As we are using CASAVA 1.8, everything comes compressed. So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zcat&lt;/code&gt; is used to decompress on the fly. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-z&lt;/code&gt; option re-compresses the trimmed reads, so we can keep using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gz&lt;/code&gt; files. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Q33&lt;/code&gt; option is required to indicate the type of quality score used. CASAVA 1.8 switches to using the standard Sanger 33-offset-based quality scores. At the time FastX couldn’t figure this out, so you have to tell it. This is a undocumented parameter that I found out about from &lt;a href=&quot;http://seqanswers.com/forums/showthread.php?t=7596&quot;&gt;this SEQAnswers post&lt;/a&gt; .&lt;/p&gt;

&lt;h3 id=&quot;tophat&quot;&gt;TopHat&lt;/h3&gt;

&lt;p&gt;Most of the defaults were used. Because of the short reads, Tophat was complaining that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--segment-length&lt;/code&gt; parameter should be made to be equal to roughly half the read length. So that’s what I did. Also, The gene model annotation file (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gtf&lt;/code&gt;) was provided so that it wouldn’t try to figure out junctions de-novo.&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;tophat -G /n/data1/genomes/bowtie-index/mm9/Ens_63/mm9.Ens_63.gtf -p 4 \
--segment-length 12  -o tophat /n/data1/genomes/bowtie-index/mm9/mm9 sequence.trim.fastq.gz
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-G&lt;/code&gt; flag provides the gene model annotation, and the second to last parameter is the path to the bowtie index files.&lt;/p&gt;

&lt;h3 id=&quot;cufflinks&quot;&gt;Cufflinks&lt;/h3&gt;

&lt;p&gt;Similar to TopHat, most of the defaults were used:&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;cufflinks -p 4 -o cufflinks -G /path/to/GTF/file.gtf accepted_hits.bam
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where the input BAM file for each sample was the output produced by TopHat.&lt;/p&gt;

&lt;h3 id=&quot;picard&quot;&gt;picard&lt;/h3&gt;

&lt;p&gt;I wanted to see what information picard’s &lt;strong&gt;CollectAlignmentSummaryMetrics&lt;/strong&gt; tool would provide, so I ran this on all the bam files. Picard and GATK can be particular about the order of the bam files. So, first I used picard’s &lt;strong&gt;AddOrReplaceReadGroups&lt;/strong&gt; and it’s &lt;strong&gt;ReorderSam&lt;/strong&gt; to get the bam files in a state where they would be taken by picard without dying:&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;java -jar picard/AddOrReplaceReadGroups.jar INPUT=accepted_hits.bam OUTPUT=accepted_hits.group.bam \
VALIDATION_STRINGENCY=LENIENT SORT_ORDER=coordinate RGLB=1 RGPL=illumina RGPU=1 RGSM=name

java -jar picard/ReorderSam.jar INPUT=accepted_hits.group.bam OUTPUT=accepted_hits.group.reorder.bam \
VALIDATION_STRINGENCY=LENIENT REFERENCE=mm9.fa CREATE_INDEX=true

java -jar picard/CollectAlignmentSummaryMetrics.jar INPUT=accepted_hits.group.reorder.bam \
OUTPUT=alignment_summary.out.txt REFERENCE_SEQUENCE=mm9.fa
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All that work, and what did I get? Not much. This tool seems like it could be more useful for paired-end data with reads that don’t pass filter in it. It does provide the total number of reads in the bam file, but this would be easy to acquire by other means.&lt;/p&gt;

&lt;h3 id=&quot;bedtools&quot;&gt;BEDTools&lt;/h3&gt;

&lt;p&gt;BEDTools has a &lt;strong&gt;coverageBed&lt;/strong&gt; program that I thought could help shed light on how well the various libraries covered each gene. I used a bed file we have containing exons to provide it the locations of the exons.&lt;/p&gt;

&lt;div class=&quot;box&quot;&gt;
**Note on Exon Bed File**
There are some particulars about this bed file that other analysts helped me understand and generate. First, There are a number of exons that overlap one another. Keeping them all would inflate the perceived coverage of those areas where a lot of overlapping exons existed. So, BEDTools mergeBed tool can be used to squash these overlapping exons. However, then you hit another problem where overlapping exons that belong to separate genes will get squashed together. We don’t want this to happen, as we are also trying to show the number of genes hit by the data. So, the solution we have here is to break up the bedfile based on genes, then squash exons at a per-gene level, and then merging the exons back together. Not sure if there is an easier way…

&lt;/div&gt;
&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;coverageBed -s -split -abam ./accepted_hits.bam -b ./mm9.Ens_63.exons.bed &amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;./coverageBed.out.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;analysis&quot;&gt;Analysis&lt;/h2&gt;

&lt;h3 id=&quot;coverage&quot;&gt;Coverage&lt;/h3&gt;

&lt;p&gt;As mentioned above, I used BEDTools to get coverage information of the exons covered for each sample.&lt;/p&gt;

&lt;p&gt;The command executed should provide an output file that contains a line for each line in the input &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bed&lt;/code&gt; file. Each output line starts with the corresponding bed file line and then ends with a few more tab-delimited fields:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Number of reads in A (the bam file) that overlap the B (the bed file) line’s interval by at least one base pair.&lt;/li&gt;
  &lt;li&gt;Number of bases in B that have some coverage from A.&lt;/li&gt;
  &lt;li&gt;The length of the interval of B&lt;/li&gt;
  &lt;li&gt;The fraction of bases in B that have some coverage from A.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From this run, an example would be:&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;chr1    59768115        59768968        exon281764      1       +       172     342     853     0.4009379
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, for this particular exon, we can see that of the 853 bases in the exon, 342 of them were overlapped by one or more of 172 reads from the bam file. This means about 40% of the exon was covered by the reads, with a maximum coverage of 172… right?&lt;/p&gt;

&lt;p&gt;Further analysis of this output was performed with R. Eventually, I extracted from these bed files:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Total number of exons that were covered by some amount of reads from the sample.&lt;/li&gt;
  &lt;li&gt;Number of exons per chromosome that were covered.&lt;/li&gt;
  &lt;li&gt;Percentage of all exons that were covered by sample (both for the whole sample and by chromosome).&lt;/li&gt;
  &lt;li&gt;Total number of unique genes that were covered by some reads.
    &lt;ul&gt;
      &lt;li&gt;Found by getting the unique gene names from the exons list.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Percentage of unique genes covered by reads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m unsure as to what a meaningful criteria is for the “some amount of reads” coverage stipulation. Should it be at least X number of bases covered by reads, Y number of reads on the exon, or Z percentage of the exon covered?&lt;/p&gt;

&lt;p&gt;With the coverageBed output, I have access to all three options. The trends look to stay the same, regardless of the selection - but the specific numbers change as you would expect.&lt;/p&gt;

&lt;p&gt;I analyzed each sample separately, even though there was two samples per library. The differences were enough to be potentially interesting.&lt;/p&gt;

&lt;p&gt;I also then combined the coverage datasets per library to show a more aggregated form of the data.&lt;/p&gt;

&lt;h3 id=&quot;expression-values&quot;&gt;Expression Values&lt;/h3&gt;

&lt;p&gt;Next, I turned to the FPKM values generated from Cufflinks to see if differences could be seen in the various cell numbers.&lt;/p&gt;

&lt;p&gt;First I looked at the covariance between the samples to see if samples from the same library were similar, and if the expression values from different cell numbers looked different. I borrowed code from another analyst that displays covariances between samples as a matrix of color squares, where the color indicates the correlation.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RNA-seq: Finding Differentially Expressed Genes</title>
   <link href="http://vallandingham.me/RNA_seq_differential_expression.html"/>
   <updated>2011-05-27T00:00:00+00:00</updated>
   <id>http://vallandingham.me/RNA_seq_differential_expression</id>
   <content type="html">&lt;p&gt;Here are some notes on processing RNA-seq data to find differentially expressed genes.&lt;/p&gt;

&lt;p&gt;A much abbreviated version of this pipeline comes from &lt;a href=&quot;http://cufflinks.cbcb.umd.edu/tutorial.html&quot;&gt;Cufflink’s Tutorial Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The extended version given below follows the more exploratory pattern of someone who hasn’t done much (any) NGS data analysis before.&lt;/p&gt;

&lt;h2 id=&quot;tools-used&quot;&gt;Tools Used&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://tophat.cbcb.umd.edu/manual.html&quot;&gt;TopHat&lt;/a&gt; v1.1.2&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://cufflinks.cbcb.umd.edu/tutorial.html&quot;&gt;Cufflinks&lt;/a&gt; v1.0.1&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://samtools.sourceforge.net&quot;&gt;Samtools&lt;/a&gt; v0.1.16&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;requirements&quot;&gt;Requirements&lt;/h2&gt;

&lt;h3 id=&quot;sequence-files&quot;&gt;Sequence Files&lt;/h3&gt;

&lt;p&gt;We are starting from Illumina generated &lt;a href=&quot;http://en.wikipedia.org/wiki/FASTQ_format&quot;&gt;Fastq sequence&lt;/a&gt; files. The reads contained in these files are paired-end and 40bp long. We are using mouse data. The naming convention follows the format: s_LANE_PAIRED_sequence.txt. So s_1_1_sequence.txt is the “left” side of the paired-end data on lane 1 and s_1_2_sequence.txt is the “right” side.&lt;/p&gt;

&lt;h3 id=&quot;pre-built-index&quot;&gt;Pre-built Index&lt;/h3&gt;

&lt;p&gt;There are a number of pre-built indexes that &lt;a href=&quot;ftp://ftp.cbcb.umd.edu/pub/data/bowtie_indexes/&quot;&gt;TopHat makers provide&lt;/a&gt; . For the mouse genome, they have “m_musculus_ncbi37”, “mm8”, and “mm9” currently listed in their ftp directory.&lt;/p&gt;

&lt;p&gt;We also have our own indexes, in our genomes directory. The index used in the initial run was labelled &lt;strong&gt;Mus_musculus.NCBIM37.52&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;gene-model-annotations&quot;&gt;Gene Model Annotations&lt;/h3&gt;

&lt;p&gt;We also want to supply TopHat with a list of gene model annotations. This is in &lt;a href=&quot;http://mblab.wustl.edu/GTF22.html&quot;&gt;GTF v2.2&lt;/a&gt; format, and the chromosome names must match those in the index. For the initial run *Mus_musculus.NCBIM37.52.gtf was used.&lt;/p&gt;

&lt;h2 id=&quot;pipeline-run&quot;&gt;Pipeline Run&lt;/h2&gt;

&lt;p&gt;The pipeline looks to be pretty simple:&lt;/p&gt;

&lt;p&gt;Sequences &lt;del&gt;&amp;gt; TopHat&lt;/del&gt;&amp;gt; Manual Check &lt;del&gt;&amp;gt; Cufflinks&lt;/del&gt;&amp;gt; Analysis&lt;/p&gt;

&lt;h3 id=&quot;removing-duplicates&quot;&gt;Removing Duplicates&lt;/h3&gt;

&lt;p&gt;No duplicate removal step was performed. Pros and Cons that &lt;a href=&quot;http://seqanswers.com/forums/showthread.php?t=6854&quot;&gt;this seqanswers post&lt;/a&gt; seems to address well. Bottom line is that it is impossible to tell if a duplicate read really is from pcr bias. Removing them causes a loss of information and location based removal methods don’t work with RNA-seq data.&lt;/p&gt;

&lt;h3 id=&quot;tophat&quot;&gt;TopHat&lt;/h3&gt;

&lt;h4 id=&quot;tophat-configuration&quot;&gt;TopHat Configuration&lt;/h4&gt;

&lt;p&gt;There are some settings to get right for TopHat. Here are the flags and the initial values I used.&lt;/p&gt;

&lt;h5 id=&quot;average-mate-pair-inner-distance&quot;&gt;Average Mate-Pair Inner Distance&lt;/h5&gt;

&lt;h5 id=&quot;-r--mate-inner-dist&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r/--mate-inner-dist&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;This is a required setting for paired-end data with &lt;strong&gt;no default value&lt;/strong&gt;. For this kind of setting, I would expect them to have a table or something that provides some suggestions on how to get this right.&lt;/p&gt;

&lt;p&gt;Also, when speaking to associates, it sounds like their formula incorrect - or at least misleading. Here, I’ll try to explain it a bit more clearly as how we see it.&lt;/p&gt;

&lt;p&gt;We are trying to provide TopHat the average distance between the ends of the paired-end reads. So, we have our library which is composed of fragmented cDNA (the DNA insert), ligated to adapter sequences on both sides. This library is size selected &lt;strong&gt;after&lt;/strong&gt; the adapters are ligated to the DNA insert. So, a 300bp library would have 300bp - Adapter_Length size inserts.&lt;/p&gt;

&lt;p&gt;The trick is that during sequencing, sequencing starts at the DNA insert - &lt;strong&gt;not&lt;/strong&gt; at the beginning of the adaptor. You can see that this is the case from Illumina documentation. For example in the &lt;a href=&quot;http://www.dkfz.de/gpcf/850.html&quot;&gt;Cluster Generation step shown here&lt;/a&gt; - it ends with the sequencing primer being hybridized to the DNA-templates. So, in order to figure out the distance between pair-end sequences, we need to subtract the Adapter_Length from the library size. There are adapter sequences on both sides of the DNA insert, so we need to subtract from both sides as we are reading from both sides. The total length of the Left_Adapter + Right_Adapter should suffice - this is what I’m calling Adapter_Length.&lt;/p&gt;

&lt;h5 id=&quot;mate-pair-distance-diagram&quot;&gt;Mate-pair Distance Diagram&lt;/h5&gt;

&lt;p&gt;p=. &lt;img src=&quot;images/rna_seq/paired_end_distance.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In total, to determine a good value for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; we need:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;strong&gt;size-selection&lt;/strong&gt; target for the final library (usually around 300bp)&lt;/li&gt;
  &lt;li&gt;The &lt;strong&gt;read length&lt;/strong&gt; (here 40bp)&lt;/li&gt;
  &lt;li&gt;The &lt;strong&gt;adapter length&lt;/strong&gt; (for TruSeq adapters this looks to be 120bp or 121bp. For other paired-end adaptors, it is 98bp.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The formula then becomes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Inner_Distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Library_Size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Read_Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Adapter_Length&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Or, for our specific run:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;mi&quot;&gt;315&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;121&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;114&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;315 was the reported average size of the library for this particular sample.&lt;/p&gt;

&lt;p&gt;I didn’t fully understand all this on my initial run of the TopHat. So, my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; was set to 122 - which is close. I &lt;strong&gt;re-ran TopHat&lt;/strong&gt; using the same parameters, but with an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; of 114, to see if there are any noticeable differences in the mapping quality.&lt;/p&gt;

&lt;h5 id=&quot;gene-model-annotations-1&quot;&gt;Gene Model Annotations&lt;/h5&gt;

&lt;h5 id=&quot;-g--gtf&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-G/--GTF&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;Full path to the .gtf file for mouse that matches the index file you will be using (see above). In my case, &lt;strong&gt;Mus_musculus.NCBIM37.52.gtf&lt;/strong&gt;. This is on a separate file system, but that does not seem to be a big deal.&lt;/p&gt;

&lt;h5 id=&quot;threads&quot;&gt;Threads&lt;/h5&gt;

&lt;h5 id=&quot;-p--num-threads&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p/--num-threads&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;You would think that these software packages would settle on a single unified flag to indicate the number of processes to use - but you would be wrong. I’ve tried running with 4 and 8. Details on run times for these choices below.&lt;/p&gt;

&lt;h5 id=&quot;output&quot;&gt;Output&lt;/h5&gt;

&lt;h5 id=&quot;-o--output-dir&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-o/--output-dir&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;As all the files generated by TopHat have the same name from run to run, it is best to use this option to put them into their own directory.&lt;/p&gt;

&lt;h4 id=&quot;tophat-run&quot;&gt;TopHat Run&lt;/h4&gt;

&lt;p&gt;The total TopHat execution string looks something like:&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;tophat -r 122 -G /full/gtf/path/Mus_musculus.NCBIM37.52.gtf \
-p 4 -o unique_output_dir/tophat/ \
/full/index/path/Mus_musculus.NCBIM37.52 s_1_1_sequence.txt s_1_2_sequence.txt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I would also ensure that your output directory exists prior to running. I do not know if TopHat creates this directory or exits out if it is not present.&lt;/p&gt;

&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p 4&lt;/code&gt; this took around &lt;strong&gt;13 hours&lt;/strong&gt; to complete. With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p 8&lt;/code&gt; it took &lt;strong&gt;ll hours&lt;/strong&gt;.&lt;/p&gt;

&lt;h4 id=&quot;tophat-run-analysis&quot;&gt;TopHat Run Analysis&lt;/h4&gt;

&lt;p&gt;I wanted to have some level of confidence that the output produced by this run was good. The log files produced by TopHat are undocumented and less than helpful.&lt;/p&gt;

&lt;h5 id=&quot;samtools-flagstat&quot;&gt;samtools flagstat&lt;/h5&gt;

&lt;p&gt;Online, I found &lt;a href=&quot;http://seqanswers.com/forums/showthread.php?t=9098&quot;&gt;some&lt;/a&gt; &lt;a href=&quot;http://i.seqanswers.com/questions/80/interpreting-samtools-flagstat-output&quot;&gt;posts&lt;/a&gt; &lt;a href=&quot;http://seqanswers.com/forums/showthread.php?t=8389&quot;&gt;using&lt;/a&gt; &lt;strong&gt;samtools flagstat&lt;/strong&gt; to look at sam/bam files.&lt;/p&gt;

&lt;p&gt;I don’t understand why a tool that everyone seems to know about is &lt;a href=&quot;http://www.google.com/search?sourceid=chrome&amp;amp;ie=UTF-8&amp;amp;q=inurl%3Asamtools.sourceforge.net+flagstat&quot;&gt;not mentioned at all in the samtools manual page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samtools&lt;/code&gt; on the command line with no arguments provides a short help section. Here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flagstat&lt;/code&gt; is listed with the description “simple stats”. Very helpful.&lt;/p&gt;

&lt;p&gt;Here is the output for the first TopHat run that used 122bp for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; parameter:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt; samtools flagstat accepted_hits.bam

102925213 + 0 &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;total &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;QC-passed reads + QC-failed reads&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
0 + 0 duplicates
102925213 + 0 mapped &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;100.00%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
102925213 + 0 paired &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;sequencing
51854282 + 0 read1
51070931 + 0 read2
65032742 + 0 properly paired &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;63.18%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
96061406 + 0 with itself and mate mapped
6863807 + 0 singletons &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;6.67%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
0 + 0 with mate mapped to a different chr
0 + 0 with mate mapped to a different chr &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;mapQ&amp;gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Results from the second run with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r 114&lt;/code&gt; were similar:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;102918381 + 0 &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;total &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;QC-passed reads + QC-failed reads&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
0 + 0 duplicates
102918381 + 0 mapped &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;100.00%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
102918381 + 0 paired &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;sequencing
51850866 + 0 read1
51067515 + 0 read2
63594438 + 0 properly paired &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;61.79%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
96054574 + 0 with itself and mate mapped
6863807 + 0 singletons &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;6.67%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
0 + 0 with mate mapped to a different chr
0 + 0 with mate mapped to a different chr &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;mapQ&amp;gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r 122&lt;/code&gt; performed a bit better, I used it for the rest of the samples&lt;/p&gt;

&lt;p&gt;I am not sure as to how useful this output really is. The 100% mapped sequences would indicate that it is not really looking at the whole picture.&lt;/p&gt;

&lt;p&gt;From a &lt;a href=&quot;http://biostar.stackexchange.com/questions/6143/the-meaning-of-samtools-flagstat-output-of-illuminas-bam-file&quot;&gt;flagstat biostar post&lt;/a&gt; - we see this information about the “properly paired” section:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Properly paired” is from the flags set by whatever aligner you’ve used. For instance, if you use bwa’s ‘sampe’ alingment, you can specify the maximum insert length with -a. For a pair to be “properly paired” it would need to have both reads mapped to the same sequence within this distance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the properly paired section is (perhaps) an indication of how well our choice of the mean inner distance worked for this data (63% not being that great?).&lt;/p&gt;

&lt;p&gt;To clarify, the flag that it looks to be counting is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x2&lt;/code&gt; in the sam/bam file. From the &lt;a href=&quot;http://samtools.sourceforge.net/SAM1.pdf&quot;&gt;SAM format description&lt;/a&gt; this flag is described as “each fragment properly aligned according to the aligner”&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;samtools view &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; 0x2 accepted_hits.bam

&lt;span class=&quot;c&quot;&gt;# 65032742&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# same number as above in properly paired&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;According to an &lt;a href=&quot;http://seqanswers.com/forums/showthread.php?t=8186&quot;&gt;unanswered SEQAnswers question&lt;/a&gt; , TopHat might not be setting this flag correctly or perhaps this flag is used differently in TopHat. I haven’t found any answers from the TopHat developers, and I haven’t looked in the source code yet.&lt;/p&gt;

&lt;h5 id=&quot;samtools-view&quot;&gt;samtools view&lt;/h5&gt;

&lt;p&gt;The &lt;strong&gt;main question&lt;/strong&gt; I would like to answer about this data is how many of the raw sequences were aligned and made it into the accepted_hits.bam file. Fastq files have 4 lines per sequence. So, to find the total number of sequences, one can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wc -l&lt;/code&gt; and divide by 4:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; s_1_1_sequence.txt

&lt;span class=&quot;c&quot;&gt;# 188366840&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 188366840 / 4 = 47091710&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# multiply by 2 to get&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 94183420 reads from both pairs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then we need to know the number of unique alignments in the accepted_hits.bam file. It is possible for one sequence from the fastq file to align multiple times.&lt;/p&gt;

&lt;p&gt;The accepted_hits.bam have collapsed together the two pairs, so the last component of the sequence names - the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/2&lt;/code&gt; are missing. (Look at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head s_1_1_sequence.txt&lt;/code&gt;, then look at the first few values of field 1 of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samtools view accepted_hits.bam&lt;/code&gt; and you will see the name difference). Hence, the total number will be 2 times the number of unique names found in the .bam file. Here is a piping of commands that should pull out the name of the read and then count unique names to determine how many unique read were aligned:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;samtools view accepted_hits.bam | &lt;span class=&quot;nb&quot;&gt;cut&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; 1 | &lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;uniq&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 45153786&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 45153786 \* 2 = 90307572&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So, from all this, we find that the total number of reads from the original sequence files that made it to the accepted_hits.bam file is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;mi&quot;&gt;90307572&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;94183420&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.958&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;96&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h5 id=&quot;fastqc&quot;&gt;fastqc&lt;/h5&gt;

&lt;p&gt;It is also possible to run fastqc on .bam files. I did that for the accepted_hits.bam file, but didn’t get too much from the resulting output.&lt;/p&gt;

&lt;h5 id=&quot;increased--r-parameter&quot;&gt;Increased &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; parameter&lt;/h5&gt;

&lt;p&gt;As a final experiment, I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r 200&lt;/code&gt; to see what difference it would make (as a decrease lowered the % properly paired). The flagstat results did show an increase in the number of properly paired sequences:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;103022448 + 0 &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;total &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;QC-passed reads + QC-failed reads&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
0 + 0 duplicates
103022448 + 0 mapped &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;100.00%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
103022448 + 0 paired &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;sequencing
51902899 + 0 read1
51119549 + 0 read2
72500578 + 0 properly paired &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;70.37%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
96158642 + 0 with itself and mate mapped
6863806 + 0 singletons &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;6.66%:nan%&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
0 + 0 with mate mapped to a different chr
0 + 0 with mate mapped to a different chr &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;mapQ&amp;gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However, I get the same number of unique mappings from the samtools view:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;samtools view accepted_hits.bam | &lt;span class=&quot;nb&quot;&gt;cut&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; 1 | &lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;uniq&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 45153786&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So we will stick with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r 122&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;cufflinks&quot;&gt;Cufflinks&lt;/h3&gt;

&lt;p&gt;Initially at least, I am only looking for differentially expressed genes, and &lt;strong&gt;not&lt;/strong&gt; attempting to discover novel genes and transcripts, so I didn’t think I would need Cufflinks. However, it does provide raw FPKM values - which I found useful when trying to compare the expression values of the sample replicates.&lt;/p&gt;

&lt;p&gt;I ended up running Cufflinks after I did the analysis with Cuffdiff to go back and show that the replicates were similar. The parameters I used for Cufflinks were pretty much the same as the ones used for cuffdiff.&lt;/p&gt;

&lt;h3 id=&quot;cuffdiff&quot;&gt;Cuffdiff&lt;/h3&gt;

&lt;p&gt;From the &lt;a href=&quot;http://cufflinks.cbcb.umd.edu/manual.html#cuffdiff&quot;&gt;cufflinks manual&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Cufflinks includes a program, “Cuffdiff”, that you can use to find significant changes in transcript expression, splicing, and promoter use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;cuffdiff-configuration&quot;&gt;Cuffdiff Configuration&lt;/h4&gt;

&lt;p&gt;Cuffdiff requires just a few inputs&lt;/p&gt;

&lt;h5 id=&quot;gtf-file&quot;&gt;GTF file&lt;/h5&gt;

&lt;h5 id=&quot;transcriptsgtf&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;transcripts.gtf&amp;gt;&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;This is the same gene annotation file that is provided as input with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-G&lt;/code&gt; flag to TopHat.&lt;/p&gt;

&lt;h5 id=&quot;output-directory&quot;&gt;Output directory&lt;/h5&gt;

&lt;h5 id=&quot;-o&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-o&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;Same as TopHat, quarantine all the output to a uniquely named directory.&lt;/p&gt;

&lt;h5 id=&quot;number-of-threads&quot;&gt;Number of Threads&lt;/h5&gt;

&lt;h5 id=&quot;-p&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;Same as TopHat, number of processes to use.&lt;/p&gt;

&lt;h5 id=&quot;labels&quot;&gt;Labels&lt;/h5&gt;

&lt;h5 id=&quot;-l--labels&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-L/--labels&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;Comma separated input to name each sample with.&lt;/p&gt;

&lt;h5 id=&quot;sample-bam-files&quot;&gt;Sample Bam files&lt;/h5&gt;

&lt;h5 id=&quot;sample1sam&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sample1.sam&amp;gt;&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;Bam files produced by TopHat runs&lt;/p&gt;

&lt;h4 id=&quot;cuffdiff-run&quot;&gt;Cuffdiff Run&lt;/h4&gt;

&lt;p&gt;For this experiment, we have two wild type sample replicates and two mutant sample replicates. Thus, we call Cuffdiff like:&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;cuffdiff -p 4 -o unique_output_dir/tophat/ -L wt,mut \
/full/gtf/path/Mus_musculus.NCBIM37.52.gtf wt_1.bam,wt_2.bam mut_1.bam,mut_2.bam
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that was it. It produces a set of files - including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gene_exp.diff&lt;/code&gt; which was the main output that I used for analyzing gene expression differences.&lt;/p&gt;

&lt;h3 id=&quot;analysis&quot;&gt;Analysis&lt;/h3&gt;

&lt;p&gt;Some quick notes on the limited analysis I performed on this data. Most analysis was done using R:&lt;/p&gt;

&lt;h4 id=&quot;replicate-analysis&quot;&gt;Replicate Analysis&lt;/h4&gt;

&lt;p&gt;First I wanted to show that the data was good. This included comparing the gene expression profiles of the two replicates for each sample. I normalized the FPKM data by taking the log2 of these values. I also removed values that were marked as having problems from TopHat (one of the columns in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gene_exp.diff&lt;/code&gt; has an “OK” if things were ok, and other values if things went wrong. I used only “OK” entries - which proved important when trying to compare replicates), and genes that were not expressed in both replicates.&lt;/p&gt;

&lt;p&gt;I produced a lattice of scatterplots that showed correlation between each sample. I also produced a correlation matrix and the resulting correlation values that showed the replicates to be highly correlated.&lt;/p&gt;

&lt;h4 id=&quot;differential-expression-analysis&quot;&gt;Differential Expression Analysis&lt;/h4&gt;

&lt;p&gt;First I plotted the log2 values and highlighted those that cuffdiff thought were statistically significant (Up-regulated in red. Down-regulated in blue). Cuffdiff listed over 8,000 genes as noteworthy, so most of the rest of the analysis here was spent cutting that down to smaller chunks.&lt;/p&gt;

&lt;p&gt;I used the log2 values and took only those genes with a 2-fold or more change. And then cut this down further by specifying to only look in the region we were interested in.&lt;/p&gt;

&lt;h3 id=&quot;the-end&quot;&gt;The End&lt;/h3&gt;

&lt;p&gt;Hopefully this can help others just getting started with RNA-seq data analysis. We hope to evolve this process and get good at finding biologically interesting/relevant changes for the researchers we support.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Really Quick Git</title>
   <link href="http://vallandingham.me/Quick_Git.html"/>
   <updated>2011-05-17T00:00:00+00:00</updated>
   <id>http://vallandingham.me/Quick_Git</id>
   <content type="html">&lt;div class=&quot;alert&quot;&gt;
&lt;p&gt;An attempt to quickly demonstrate the usefulness of Git for the single-developer environment&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id=&quot;what-does-git-give-you-as-an-individual-developer&quot;&gt;What does Git give you as an individual developer?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;History of changes you made to your files.
    &lt;ul&gt;
      &lt;li&gt;Allows you to see when particular changes / features were implemented.&lt;/li&gt;
      &lt;li&gt;Also can provide an explanation to why you changed something the way you did.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;‘Universal undo’
    &lt;ul&gt;
      &lt;li&gt;Revert changes to any file you are tracking in Git.&lt;/li&gt;
      &lt;li&gt;Completely external to the particular editor you are using at the time.&lt;/li&gt;
      &lt;li&gt;Useful when a rm goes bad, or when you get crazy with Vim (“:d20j :wq”).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Test out new changes / ideas without fear.
    &lt;ul&gt;
      &lt;li&gt;Branching capabilities in Git make it easy to try out large scale modifications to your code that you can always revert if things don’t work out.&lt;/li&gt;
      &lt;li&gt;Also could be useful if you need to have a number of versions of your code with small tweaks in them.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Tagging allows you to know exactly how your code looked at a particular revision
    &lt;ul&gt;
      &lt;li&gt;Useful for when you need to know if a bug / feature was present in the code at version x&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-a-central-git-repository-like-github-gives-you&quot;&gt;What a central Git repository (like Github) gives you&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Easily share code in a consistent, familiar manner.&lt;/li&gt;
  &lt;li&gt;Provide a backup of your source code for when your harddrive crashes.&lt;/li&gt;
  &lt;li&gt;A quick place to share code with yourself on multiple computers.
    &lt;ul&gt;
      &lt;li&gt;Keep working (and maintaining a history of your work) no matter where you are.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;worth-it&quot;&gt;Worth it?&lt;/h2&gt;

&lt;p&gt;I think it can be hard to prove that the added benefit you get from a version control system is worth the effort it takes to use it. Hopefully I can show that even with just a minimal amount of overhead, Git can be an valuable tool.&lt;/p&gt;

&lt;h2 id=&quot;assumptions&quot;&gt;Assumptions&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;You are on a *nix based machine&lt;/li&gt;
  &lt;li&gt;Git is already installed on your system&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;initial-setup&quot;&gt;Initial Setup&lt;/h2&gt;

&lt;p&gt;There are a few steps that are good to take care of up front, to avoid frustrations later on. We will just execute these commands without too much explanation as to the details of what they do. Commands are executed in the terminal.&lt;/p&gt;

&lt;h3 id=&quot;set-your-get-name-and-email&quot;&gt;Set your get name and email&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.name &lt;span class=&quot;s2&quot;&gt;&quot;Jim Somebody&quot;&lt;/span&gt;
git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.email &lt;span class=&quot;s2&quot;&gt;&quot;jims@domain.com&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;turn-on-color-for-your-git-output&quot;&gt;Turn on color for your git output&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; color.ui &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;add-global-gitignore-file-for-temporary-files&quot;&gt;Add global gitignore file for temporary files&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# create .gitignore in home directory&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;touch&lt;/span&gt; ~/.gitignore

&lt;span class=&quot;c&quot;&gt;# add some files patterns to ignore&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.swp&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gitignore
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.DS_Store&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gitignore

&lt;span class=&quot;c&quot;&gt;# tell git about our global ignore&lt;/span&gt;

git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; core.excludesfile ~/.gitignore

&lt;span class=&quot;c&quot;&gt;# you can add to this .gitignore file later&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# and each git project also can have its own&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# specific .gitignore&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ok, that takes care of most of the setup stuff. Lets get to using Git.&lt;/p&gt;

&lt;h2 id=&quot;how-git-works---the-basics&quot;&gt;How Git works - the basics&lt;/h2&gt;

&lt;p&gt;Here’s a quick rundown of the basic points on how Git operates.&lt;/p&gt;

&lt;h4 id=&quot;you-commit-changesets-to-a-git-repository&quot;&gt;You Commit Changesets to a Git repository&lt;/h4&gt;

&lt;p&gt;Git works with groups of changes to your files, which we will call changesets. A changeset can include adding / removing text inside a file and / or adding / removing entire files. A changeset is commited to the git repository to track the changes. The idea here is that each changeset should optimally contain changes for a single logical modification to your code.&lt;/p&gt;

&lt;p&gt;So, for example, if you codebase is a command line tool, a possible changeset would be adding the ability to specify an output directory. You would commit all the file modifications to complete this change as a single changeset. Another changeset could be the creation of a new class to represent ‘xyz’. That would go into its own changeset and that changeset would be committed to the repository.&lt;/p&gt;

&lt;p&gt;You can work at a lower or higher scope than this, but I belive working with individual logical changes as individual changes allows you to get the most from your repository.&lt;/p&gt;

&lt;h4 id=&quot;git-has-a-staging-area-to-prepare-your-commits&quot;&gt;Git has a Staging area to Prepare your Commits&lt;/h4&gt;

&lt;p&gt;As changesets can and often do include multiple files, you need a way to group your changes before committing. That’s where the staging area comes in. The staging area is a holding place for changes in a changeset that will be committed.&lt;/p&gt;

&lt;p&gt;This makes committing a change a 2 step process:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;First, a change is added to the staging area&lt;/li&gt;
  &lt;li&gt;Then, the set of changes in the staging area (your changeset) is committed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it easy to have lots of modified files, but pick and choose which changes go into individual commits. Without a staging area, you would have to either only work on a single changeset at a time, or be forced to combine modifications from different logical modifications into one large commit. Both of these options are no good - hence the staging area.&lt;/p&gt;

&lt;h2 id=&quot;working-with-git&quot;&gt;Working with Git&lt;/h2&gt;

&lt;p&gt;Enough of the theoretical, lets start using it.&lt;/p&gt;

&lt;h3 id=&quot;initialize-git-repo&quot;&gt;Initialize Git Repo&lt;/h3&gt;

&lt;p&gt;The first step is to create a Git repository. You can do this in a directory that already has files in it that you now want to track, or you can do this in a clean directory as a first step to starting a project.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /path/to/directory
git init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You now have a git repository in your current directory capable of tracking changes to all files in this directory and any sub-directory of this directory. It current is not tracking any files.&lt;/p&gt;

&lt;h3 id=&quot;preparing-for-the-first-commit-excluding-files&quot;&gt;Preparing for the First Commit: Excluding Files&lt;/h3&gt;

&lt;p&gt;Usually, you will &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git init&lt;/code&gt; in a directory that already has files in it. Lets assume that is the situation for the rest of this article.&lt;/p&gt;

&lt;p&gt;In this situation, it is beneficial to add all current files at once to git, and use this as your first commit.&lt;/p&gt;

&lt;p&gt;But before we do that, lets make sure that there aren’t any files we want to not have tracked in git. Usually, files that are automatically generated and temporary files are good candidates for files we don’t want to track.&lt;/p&gt;

&lt;p&gt;Lets say that there is a directory called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;temp&lt;/code&gt; that we don’t want to track changes to. To tell git about this directory, we add it to the repositories &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; file. So create this file and add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;temp&lt;/code&gt; to ignore:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;touch&lt;/span&gt; ./.gitignore
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;temp/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ./.gitignore&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Notice that we actually give a file matching pattern that says “ignore all files and folders inside of temp”. Git automatically ignores empty directories, and so Git will ignore the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;temp&lt;/code&gt; directory as well as we have made it ‘empty’ by ignoring all the files inside it.&lt;/p&gt;

&lt;h3 id=&quot;first-commit&quot;&gt;First Commit&lt;/h3&gt;

&lt;p&gt;Ok, now we are ready to commit our current set of files to git.&lt;/p&gt;

&lt;p&gt;First, its nice to see the status of git using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git status

&lt;span class=&quot;c&quot;&gt;# output with all files listed in 'untracked files' section&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;git-add&quot;&gt;git add&lt;/h3&gt;

&lt;p&gt;Like I mentioned above, committing in git is really a 2 step process: add and then commit. This allows you to be very particular about which files go into a specific commit.&lt;/p&gt;

&lt;p&gt;As this is our first commit, we want to add all the files to our repository. This can be done a number of ways, but I like the following method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git add .&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And that’s it. See what you just did with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git status

&lt;span class=&quot;c&quot;&gt;# output with all files in the 'Changes to be committed' section&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;git-commit&quot;&gt;git commit&lt;/h3&gt;

&lt;p&gt;Now we are ready to commit these changes to our repository. Each commit in git is given a “commit message” which describes what these changes are about. You can make these messages as long as you want, but for individual developers, its usually easiest to provide short but meaningful comments on what you changed. You can provide this short style comment using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-m&lt;/code&gt; flag when committing.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;initial commit&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And that’s it! Your new files have been added to git to track. Check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt; and you will see that there are no new changes.&lt;/p&gt;

&lt;h2 id=&quot;git-workflow&quot;&gt;Git Workflow&lt;/h2&gt;

&lt;p&gt;With just a few commands, you can quickly utilize git to track changes, try out new experimental changes, and figure out why or when things changed.&lt;/p&gt;

&lt;h3 id=&quot;adding-changesets-to-git&quot;&gt;Adding changesets to git&lt;/h3&gt;

&lt;p&gt;By far the most common procedure is checking in new commits to git. Here is the general workflow for this process:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git status

&lt;span class=&quot;c&quot;&gt;# see what changes have been made&lt;/span&gt;

git add file1
git add file2

&lt;span class=&quot;c&quot;&gt;# add particular files that have been modified as part&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# of the current change you are working on&lt;/span&gt;

git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;added xyz feature for abc reason&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# commit with comment&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So just 3 commands: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit&lt;/code&gt;. If you aren’t sure what you did to a particular modified file use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff file_name&lt;/code&gt; to get a quick diff of the uncommitted changes.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bioinformatic File Cheatsheet</title>
   <link href="http://vallandingham.me/Bioinformatic-File-Cheatsheet.html"/>
   <updated>2011-05-13T00:00:00+00:00</updated>
   <id>http://vallandingham.me/Bioinformatic-File-Cheatsheet</id>
   <content type="html">&lt;p&gt;Some quick notes on common file formats used in the bioinformatic world I am now part of.&lt;/p&gt;

&lt;h2 id=&quot;gffv2&quot;&gt;GFFv2&lt;/h2&gt;

&lt;p&gt;Apparently there are 3 different versions of GFF from 2 different sources.
GFFv2 and GFFv3 are the most interesting currently.&lt;/p&gt;

&lt;h3 id=&quot;name&quot;&gt;Name&lt;/h3&gt;

&lt;p&gt;General Feature Format (v1,v2)&lt;/p&gt;

&lt;h3 id=&quot;format&quot;&gt;Format&lt;/h3&gt;

&lt;p&gt;Nine required fields that must be tab-separated.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;seqname - The name of the sequence. Must be a chromosome or scaffold.&lt;/li&gt;
  &lt;li&gt;source - The program or database that generated this feature.&lt;/li&gt;
  &lt;li&gt;feature - The name of this type of feature. Some examples of standard feature types are “CDS”, “start_codon”, “stop_codon”, and “exon”.&lt;/li&gt;
  &lt;li&gt;start - The starting position of the feature in the sequence. The first base is numbered 1.&lt;/li&gt;
  &lt;li&gt;end - The ending position of the feature (inclusive).&lt;/li&gt;
  &lt;li&gt;score - A score between 0 and 1000. If no score, then ‘.’ is used&lt;/li&gt;
  &lt;li&gt;strand - Valid entries include ‘+’, ‘-’, or ‘.’ (for don’t know/don’t care).&lt;/li&gt;
  &lt;li&gt;frame - If the feature is a coding exon, frame should be a number between 0-2 that represents the reading frame of the first base. If the feature is not a coding exon, the value should be ‘.’. Field should be called “Phase”&lt;/li&gt;
  &lt;li&gt;attribute - not-well defined field with tag value ; structure&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;application-support&quot;&gt;Application Support&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://genome.ucsc.edu/FAQ/FAQformat.html#format3&quot;&gt;UCSC Genome Browser&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;source&quot;&gt;Source&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GFF v1&lt;/strong&gt; &amp;amp; &lt;strong&gt;GFF v2&lt;/strong&gt; come from &lt;a href=&quot;http://www.sanger.ac.uk/resources/software/gff/&quot;&gt;The Sanger Institute&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;gffv3&quot;&gt;GFFv3&lt;/h2&gt;

&lt;h3 id=&quot;name-1&quot;&gt;Name&lt;/h3&gt;

&lt;p&gt;Generic Feature Format (v3)&lt;/p&gt;

&lt;h3 id=&quot;format-1&quot;&gt;Format&lt;/h3&gt;

&lt;p&gt;9 fields separated by tab characters&lt;/p&gt;

&lt;h3 id=&quot;application-support-1&quot;&gt;Application Support&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://snpeff.sourceforge.net/supportNewGenome.html&quot;&gt;SnpEff&lt;/a&gt; - for new genome creation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;source-1&quot;&gt;Source&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GFF v3&lt;/strong&gt; comes from &lt;a href=&quot;http://www.sequenceontology.org/gff3.shtml&quot;&gt;The Sequence Ontology Project&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; 0  ##gff-version   3
 1  ##sequence-region   ctg123 1 1497228
 2  ctg123 . gene            1000  9000  .  +  .  ID=gene00001;Name=EDEN

 3  ctg123 . TF_binding_site 1000  1012  .  +  .  ID=tfbs00001;Parent=gene00001

 4  ctg123 . mRNA            1050  9000  .  +  .  ID=mRNA00001;Parent=gene00001;Name=EDEN.1
 5  ctg123 . mRNA            1050  9000  .  +  .  ID=mRNA00002;Parent=gene00001;Name=EDEN.2
 6  ctg123 . mRNA            1300  9000  .  +  .  ID=mRNA00003;Parent=gene00001;Name=EDEN.3

 7  ctg123 . exon            1300  1500  .  +  .  ID=exon00001;Parent=mRNA00003
 8  ctg123 . exon            1050  1500  .  +  .  ID=exon00002;Parent=mRNA00001,mRNA00002
 9  ctg123 . exon            3000  3902  .  +  .  ID=exon00003;Parent=mRNA00001,mRNA00003
10  ctg123 . exon            5000  5500  .  +  .  ID=exon00004;Parent=mRNA00001,mRNA00002,mRNA00003
11  ctg123 . exon            7000  9000  .  +  .  ID=exon00005;Parent=mRNA00001,mRNA00002,mRNA00003
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;bed&quot;&gt;BED&lt;/h2&gt;

&lt;h3 id=&quot;name-2&quot;&gt;Name&lt;/h3&gt;

&lt;p&gt;BED&lt;/p&gt;

&lt;h3 id=&quot;format-2&quot;&gt;Format&lt;/h3&gt;

&lt;p&gt;3 initial required fields and 9 additional optional fields. Fields are separated by a tab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Required&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;chrom&lt;/strong&gt; - name of chromosome&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;chromStart&lt;/strong&gt; - Starting position in chromosome. First base in chromosome is numbered 0. This 0 based indexing is different from other formats that use a 1 based index.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;chromEnd&lt;/strong&gt; - End position of feature in chromosome.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Optional&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;name&lt;/strong&gt; - Name of BED line.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;score&lt;/strong&gt; - Score with range of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0..1000)&lt;/code&gt;. Can denote display indcations&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;strand&lt;/strong&gt; - ‘+’ or ‘-’&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;thickStart&lt;/strong&gt; - The starting position at which feature is drawn thickly&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;thickEnd&lt;/strong&gt; - The ending position at which feature is drawn thickly&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;itemRgb&lt;/strong&gt; - RGB value example: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;255,0,0&lt;/code&gt; which can denote color to display data in BED line. Should limit to 8 colors or less in file.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;blockCount&lt;/strong&gt; - Number of exons (blocks) in the BED line&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;blockSizes&lt;/strong&gt; - comma separated list of block sizes. Number of items in list should be equal to &lt;strong&gt;blockCount&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;blockStarts&lt;/strong&gt; - comma separated list of block starts. Values are relative to &lt;strong&gt;chromStart&lt;/strong&gt;. Number of items should be equal to &lt;strong&gt;blockCount&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;application-support-2&quot;&gt;Application Support&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://genome.ucsc.edu/FAQ/FAQformat.html&quot;&gt;USCS Genome Browser&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;source-2&quot;&gt;Source&lt;/h3&gt;

&lt;p&gt;USCS?&lt;/p&gt;

&lt;h3 id=&quot;example-1&quot;&gt;Example&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;chr1  213941196  213942363
chr1  213942363  213943530
chr1  213943530  213944697
chr2  158364697  158365864

chr7  127473530  127474697  Pos3  0  +  127473530  127474697  255,0,0
chr7  127474697  127475864  Pos4  0  +  127474697  127475864  255,0,0
chr7  127475864  127477031  Neg1  0  -  127475864  127477031  0,0,255

track name=pairedReads description=&quot;Clone Paired Reads&quot; useScore=1
chr22 1000 5000 cloneA 960 + 1000 5000 0 2 567,488, 0,3512
chr22 2000 6000 cloneB 900 - 2000 6000 0 2 433,399, 0,3601
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 
</feed>
