Tuesday, December 15, 2009

Matplotlib: topo.colors

I looked around a bit on the web for topo colors for matplotlib, but didn't see anything. So, I used my new understanding of how to make a LinearSegmentedColormap, and the previous analysis of R's topo.colors from here. Reprinting the figure from that post



we see how the RGB components vary individually over the course of the range 0-1000 (or 0.000 to 1.000). Examining the values for the colors obtained from R at those points (in R do: topo.colors(1000), I estimated these values:

1    4c00ff
84 0000ff
334 00e5ff
335 00ff4d
418 00ff00
667 e6ff00
668 ffff00
850 ffdd62
1000 ffe0b3


I converted the hex values for the colors at the breakpoints to fractions of 256 in Python:

L = ['4c','b3','dd','e0','e5']
>>> for e in L:
... print e, int(e,16), int(e,16)*1.0/256
...
4c 76 0.296875
b3 179 0.69921875
dd 221 0.86328125
e0 224 0.875
e5 229 0.89453125


And that allowed me to construct the Colormap. In filling out the map, I came to appreciate the unusual data structure. It's natural to extend something like this:

x y0 y1
x y0
x


by adding the next y1 to the middle row (the value of the color at the beginning of the interval), and the next y0 to the last row (the value at the end of the interval). Here's what I got. It looks pretty good to me:


Here's the code:


import matplotlib.pyplot as plt
import matplotlib
import numpy as np

# topo colors
r = ((0.000, 0.000, 0.297),
(0.084, 0.000, 0.000),
(0.418, 0.000, 0.000),
(0.667, 0.895, 0.895),
(0.668, 1.000, 1.000),
(1.000, 1.000, 1.000))

g = ((0.000, 0.000, 0.000),
(0.084, 0.000, 0.000),
(0.334, 0.895, 0.895),
(0.335, 1.000, 1.000),
(0.667, 1.000, 1.000),
(0.850, 0.863, 0.863),
(1.000, 0.875, 1.000))

b = ((0.000, 0.000, 1.000),
(0.334, 1.000, 1.000),
(0.335, 0.297, 0.297),
(0.418, 0.000, 0.000),
(0.667, 0.000, 0.000),
(1.000, 0.700, 1.000))

colors = {'red':r, 'green':g, 'blue':b}

f = matplotlib.colors.LinearSegmentedColormap
m = f('my_color_map', colors, 256)
A = np.array(range(100))
A.shape = (10,10)
plt.pcolor(A,cmap=m)
plt.colorbar()
plt.savefig('example.png')