Colormap Gradient for Scatter Plot Circles

1,079 views
Skip to first unread message

Michael Smith

unread,
Apr 16, 2012, 1:02:00 PM4/16/12
to d3-js
Hello,

I wrote a small script to display data (time vs range) via a scatter
plot. I'm a bit lost. I have a third value (signal to noise ratio..
generally the min value is 10 dB and the max is around 35 dB)) that I
would like to use in order to color the scatter plot circles. My goal
is to create a very specific colormap (my boss wants this) from blue,
green, yellow, orange, and red and have the circles mapped linearly
across the range of colors. I'm not a really a programmer, but i've
been learning d3 recently in order to have interactive data displays
rather than matlab generated png images. Can anyone help?

The code I've been using which obviously doesn't work. It's only
displaying dark blue.

d3.scale.linear()
.domain(d3.extent(data, function(d) { return d.snr3; }))
.range(['darkblue', 'mediumblue', 'blue', 'aqua', 'lightgreen',
'yellow', 'orange', 'orangered', 'red', 'darkred'])

Thanks

Mike Bostock

unread,
Apr 19, 2012, 1:50:37 AM4/19/12
to d3...@googlegroups.com
First, read "Rainbow Color Map (Still) Considered Harmful" (and send
it to your boss):

http://www.jwave.vt.edu/~rkriz/Projects/create_color_table/color_07.pdf

Now that you understand that making rainbow scales are bad (and
literally kill people! [1]), I'll give you some hints as to how to do
it: if you have multiple values in the range, you want the same number
of values in the domain. This is sometimes called a "polylinear"
scale.

For example, say you wanted a diverging color scale, where negative
values are increasingly red and positive values are increasingly
green:

var color = d3.scale.linear()
.domain([-1, 0, 1])
.range(["red", "white", "green"]);

If you want to extend this approach to 10 (or an arbitrary number)
colors, then you need to specify a domain with the same number of
values. If you want to split the domain evenly, then you can use a
second linear scale to sample intermediate values in the domain. Take
the array of output colors:

var colors = ["red", "orange", "yellow", "green", "blue", "violet"];

Create a linear scale that maps 0 to the minimum value, and
colors.length - 1 to the maximum value:

var scale = d3.scale.linear()
.domain([0, colors.length - 1])
.range(d3.extent(data, function(d) { return d.snr3; }));

Finally sample the domain of the first scale to create the domain of
the second scale:

var color = d3.scale.linear()
.domain(d3.range(colors.length).map(scale))
.range(colors);

Also see:

https://github.com/mbostock/d3/wiki/Arrays#wiki-d3_range
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map

Mike

[1] http://www.seas.harvard.edu/news-events/press-releases/hemovis

Reply all
Reply to author
Forward
0 new messages