Sunday, December 30, 2012

The other Avatar is racist too

My sister and I used to avidly follow the Nickelodeon series Avatar: The Last Airbender. She was 9 and I was 19 but it worked out. When the movie for the series was announced, it was supposed to be titled Avatar and I was so excited I literally counted down the days - so excited that I watched the trailer for Avatar and saw suspicious looking blue people and a lot of helicopters but assumed that they decided to take the ethnic kungfu thing really seriously and very far out. I still thought that I was watching Avatar: The Last Airbender in the theater 15 minutes into the suspicious 3d movie full of tall blue people.

Er.. turns out that Avatar: The Last Airbender decided to change names to The Last Airbender because Avatar was such a big hit. No matter. I counted down the days again and this time no one wanted to go see the movie with me because no one my age was a fan of the Nickelodeon series. So I went to the theater alone, 20 minutes early, bought a popcorn and coke for myself and watched the movie, and walked out sad, disappointed, and alone in a sea of chattering children a couple hours later.

So my sister and I were rummaging around Netflix around 1am and found The Last Airbender and I decided to give it another shot - the last time I watched it was two and a half years ago, maybe I'll like it more this time around.


The only good part about the movie was the ramen we inhaled while watching it. After we finished the movie, we watched the first episode of the original Nickelodeon series, and it was so good.

The core problem with the movie was that they swapped out all the non-white actors into white actors who made Kristen Stewart look like she deserves an Oscar.

Aang is clearly an Asian monk hero:

The real Aang should have looked something like the left drawing below, complete with the playful, childlike expression. In the movie, he is as shown in the next picture, complete with an all-too-serious face for a 12-year-old and very distinctly Caucasian features.

Now these kind of jokes don't even make sense:

In addition to changing the race of the hero of the story, they swapped out all the Inuit tribespeople too! Aang's closest friend Katara is unmistakably brown in the original series, while in the movie, she is decidedly white.


Even when they did cast Asian people, they casted the wrong type of Asians! Prince Zuko is clearly of Chinese descent in the original series. The people in the Fire Kingdom even have Chinese names, such as General Zhao. But they decided that Fire Kingdom citizens should be Indian. Except for Prince Zuko's uncle, who is Caucasian for some incomprehensible reason.

I've been a fan of Dev Patel long before he hit it big with Slumdog Millionaire, but it does not change the fact that he's not the right type of Asian for Avatar.

Apparently draining heros of color has been happening in Hollywood for a long time. I just found out that the movie 21 was actually based on a book that has an Asian American protagonist that defies stereotypes, but the director decided to cast a white person instead, killing all the second-generation Asian immigrant aspect of the storyline.

I felt like the following talk captured the essence of the problem:

It's so weird. At Stanford, I never feel stereotyped or marginalized as an Asian. And then I see some ridiculous things happening like The Last Airbender and 21 that people are oblivious to, and I suddenly feel unwelcome here. But I guess Stanford just spoils you like that. It doesn't hurt that there's this trend for shiny new Asian-named buildings on campus either.

If Hollywood ever goes through with making Snow Crash into a movie and turns Hero Protagonist - the half-Black, half-Korean hero of the novel who practices Japanese-style sword-fighting - into a white male that is "easy on the eyes," it will be a very, very sad day.

Friday, December 28, 2012

D3GL Tutorials 02: Binding data to each globe

So far we have discussed binding a dataset to a globe-rendering template, then creating multiple globes that utilize the template. But you also want to bind datasets per globe - you want color-coded maps, points, bars with different heights jutting out of the sphere, arcs stretching across oceans.

The elements of data - points, bars, etc. - we call data primitives. With
, we bind data per type of data primitive. That is, each globe can have multiple data primitives, and each data primitive type gets its own dataset to visualize. We will talk more about data primitives, their shared properties, and available user interactions in the next tutorial.

In this tutorial, we go over how you bind a different dataset to a data primitive on each globe.

Bind data to a primitive

var rainfall = [10, 0, 5, 20];

In the above snippet of code, the variable
is a globe template. We are creating the points layer on top of the globe, and telling it that a point should be rendered per data item in
[10, 0, 5, 20]

But let's not forget that the same globe template can be used to create multiple globes. With the above code, each globe rendered from the globe template will render points using the same dataset. We probably don't want that.

Bind different data to each globe

To pass in different datasets for globes using the same template, we can do the following:
var precipitation = {
  ‘rainfall’: [10, 0, 5, 20],
  ‘snowfall’: [0, 30, 0, 10]

// create a globe rendering template
var globe =

// add points, specify dataset for points
var points = globe.points()
  .data( function(d) {
    return precipitation[d];

// render two globes“body”)

This binds the array
['rainfall', 'snowfall']
to the globe rendering template with
. Then each element in the array is passed in as a parameter to each of the two globes that are created with the template.

Because we added the
primitive to the globe template, each globe instance renders a points layer. The points on the globe that has the data element
binds to the array
[10, 0, 5, 20]
, which it grabbed with its
property, as specified in the template:
.data( function(d) {
  return precipitation[d];

Likewise, the globe that is passed in
binds its points to
[0, 30, 0, 10]


Since we haven't given
enough settings to be able to display the data, there will be no demo for this tutorial. To check out data-binding in action, you should continue on to the next tutorials that cover the different primitives you can bind data with!


, the data primitives are closures with getters and setters. They have a rendering call, just like
has a rendering call that is invoked with
. But the rendering call for a data primitive type is invoked internally in the rendering loop started when the globes are rendered. Each rendering call for a primitive gets the data element assigned to the globe the primitive belongs to, which is then used to grab the relevant dataset.

The implementation for data primitives will be discussed more in depth in the next tutorial.

← Prev


Staying home for the holidays, I spent a lot of time with my mom.
She inspired me to draw this little piece:

Thursday, December 27, 2012

A Romantic Brain

Dissecting Love

How on earth are you ever going to explain in terms of chemistry and physics so important a biological phenomenon as first love?
- Albert Einstein
I have long been fascinated by the mechanisms of romantic love. Why does my romance feel so unique and intense, only to realize that the same feelings have been documented world-wide for as long as writing has existed?

Some may say that dissecting love into what it really is - a chemical process in the brain and in the body - is unromantic, cold-hearted, sacrilegious. But I think it simply adds to the wonder: Earth remains awe-inspiring even after we learn that it is but one of a myriad planets in existence; water does not stop quenching our thirst because we know that it is but an amalgamation of tiny particles strewn together not unlike lego pieces; love is no less beautiful with the discovery that it is but a serious of reaction firing in our cells.

Earth is even more awe-inspiring when seen from the moon, despite - or because of - how
the view shows you that Earth is not the center of the universe

Is passionate romantic love really a uniquely human feature? I have learned to be wary of anything being described as "uniquely human." The more I learn, the more it seems as though we are nothing special compared to the rest of the universe. And yes, passionate love exists in other species, if you define passionate love as an uncontrollable, burning desire to be with a particular someone, including sexual desire but more the need to be together as companions.

Prairie voles develop lifelong bonds between mates

Of course, romantic passion observed in animals vary in how long it lasts, from mere seconds in rats, two weeks in foxes, and a lifetime in wolves. But after all, so does love between people, as Violetta puts it as she sings in Verdi's opera La Traviata: "Let's live for pleasure alone, since love, like flowers, swiftly fades."

A Romantic Brain

This series of posts will cover how romance looks in the brain, and how it alters the body and mind of those affected. Unlinked titles are yet to be written:

The romantic instinct

... talks about the different hormones involved with romance
as a basic human instinct, not unlike drives such as hunger, thirst, and lust.

Manipulating love

... discusses various ways love is and can be manipulated - how various behaviors,
circumstances, and substances can lead to romance or heartbreak.

Love as a maleable emotion

... brings up the nurture aspect of love - the emotional aspect of love
that may play a large role in humans but not in animals.

D3GL Tutorials 01: Creating globes
is one of D3GL's data visualization templates that is useful for visualizing global, location-based data. 2D projections of the globe pose problems of distortion and misrepresentation. To take a simple, common example, a Mercator projection of the world's countries has a large “lie factor”, because countries like Greenland and Russia appear much larger than they actually are.

3D visualization has a lie factor of one. Through projection, rotation, zooming, etc, 3D visualization leverages the human brain's powerful faculties for understanding spatial data. Flight paths, for instance, make much more sense when depicted on a three-dimensional Earth because the best paths fit the curve of the Earth, which may look strange and arbitrary on a flat projection of the world. Stellar bodies other than the Earth may also benefit from three- dimensional visualizations, particularly because unlike the world map, most viewers are not familiar with flat maps of the sun, moon, Mars, and more.

D3GL's globe template can overlay the following data primitives:
points, painter, arcs, bars, shapes
. In this tutorial, we will focus on rendering naked globes without any overlays using custom globe templates.

Creating a globe template

Before you can render a globe or several, you need to create a globe template and set its properties using chaining, as in
var globe =

The globe template serves as a rendering template for multiple globes. For properties shared among all globes, static values can be passed in, as in the width, height, and texture calls in the above snippet of code.

Customizing per globe

To configure a specific property per globe, a function is passed in as argument, as in the texture call in the modified code below:
var globe =
  .texture(function(d) {
    return "../" + d + ".jpg";

The function passed into the texture call has a parameter
, which refers to the data element that is passed in per globe once data is bound to the globe template. In this code example, each data element can be used to create a path for a texture for each globe.

Binding data to the globe template

The globes can be rendered by binding data, appending DOM elements to contain them, and calling globe, which refers to the object previously initialized with a call to
var data = ['earth', 'moon'];"body").selectAll("span")

This is analogous to the
style for adding elements bound to data. The above code will pass the bound data, which is the array
['earth', 'moon']
, when it invokes

Then for each element in the data that is passed in, a new D3
object is created to be rendered on screen. Each element in the data array will be passed in as argument. In this example, the first globe is passed in
and the second
, which are used to determine the texture of each globe.


Hello Earth


The conventions for this API were inspired by Michael Bostock's essay “Toward Reusable Charts,” which encourages the use of closures with getter and setter methods and outlines specific design patterns. Thus
is a closure with properties such as
width, height, texture, transparency, zoom, and rotation.
It supports method chaining, which means each setter returns the closure.

is invoked, a function is called for each data element in the bound data that evaluates the appropriate values for the properties of the globe -
width, height, texture, transparency, zoom, rotation

WebGL is initialized once per globe using Three.js. Unlike D3.js, the render function is is called 60 frames per second using RequestAnimationFrame. Since each property of the globe is evaluated per frame, any change will be reflected immediately.

← Prev    Next →

D3GL Tutorials 00: Getting started

In this tutorial, we will go over how to incorporate D3GL into your webpage.

Linking D3GL

To get started with D3GL, first download D3GL here, by right-clicking the link and choosing "Save as..." or something similar.

Alternatively, you can add the following line between
<script type="text/javascript" src=""></script>

I will keep the above links updated, but keep in mind that D3GL is under heavy development, so the latest (un-minified) version lives here on Github.

Running a local server

When you are developing locally, your browser may raise something along the lines of
XMLHttpRequest cannot load the url Origin null is not allowed by Access-Control-Allow-Origin
when you try to read files out of the local file system. To avoid this, you can run a local web server. I find that a simple solution is to run Python's built-in server:
python -m SimpleHTTPServer 8888 &

... after which you can access

If you are using a Mac, I find that MAMP works beautifully.

Using D3GL

Now that you have linked D3GL and run a local server, you can use
in your code:
<script type="text/javascript">
  // use to create a beautiful visualization

Next →

Saturday, December 15, 2012

D3GL Tutorials

My friend Daniel Posch and I created D3GL as a final project for CS 448B at Stanford, a course titled Data Visualization. Our motivation stemmed from when we were working on an interactive visualization assignment that involved using raw WebGL. It was painful. We decided that it shouldn't be so.

D3GL is a D3 plug-in library that lets users control WebGL elements and bind data in an intuitive way. WebGL is a powerful but unwieldy Javascript library, the only way to do hardware- accelerated 3D rendering in the browser. It is a thin wrapper on a low-level C API called OpenGL ES. D3GL abstracts away the setup and provides the user with a streamlined interface to render and manipulate data visualizations. It currently supports interactions including zoom, rotation, and selection with various data primitives such as points, user-defined overlays, shapes, and bars on globes.

D3GL is under heavy development at the moment, and you can check out the most recent developments at

You can check out the official D3GL site at

Check out D3.js, the library that D3GL builds on top of, at

These tutorials for D3GL are aimed for people familiar with JavaScript, HTML, and CSS, although experience with D3 is unnecessary. The tutorials will cover the following:

As more data visualization types and primitives are added to D3GL, the list will grow. Existing tutorials will be linked - unlinked tutorials are yet to be written.

In addition to explaining basic D3GL concepts and usages, these tutorials will also discuss the internal implementation of each feature for those who are interested in adding to the open-source development of D3GL.