Is there a simple way to form a new colormap by stacking together two existing ones?
What I\'m trying to achieve is to make yet another color-coded scatter plot, wh
This isn't tested, but as a first pass I would try making a simple sub-class of colors.Colormap
.
class split_cmap(colors.Colormap):
def __init__(self, cmap_a, cmap_b, split=.5):
'''Makes a split color map cmap_a is the low range,
cmap_b is the high range
split is where to break the range
'''
self.cmap_a, self.cmap_b = cmap_a, cmap_b
self.split = split
def __call__(self, v):
if v < self.split:
return self.cmap_a(v)
# or you might want to use v / self.split
else:
return self.cmap_b(v)
# or you might want to use (v - self.split) / (1 - self.split)
def set_bad(self,*args, **kwargs):
self.cmap_a.set_bad(*args, **kwargs)
self.cmap_b.set_bad(*args, **kwargs)
def set_over(self, *args, **kwargs):
self.cmap_a.set_over(*args, **kwargs) # not really needed
self.cmap_b.set_over(*args, **kwargs)
def set_under(self, *args, **kwargs):
self.cmap_a.set_under(*args, **kwargs)
self.cmap_b.set_under(*args, **kwargs) # not really needed
def is_gray(self):
return False
colors.Colormap class definition.
You are going to need to dig into the Normalize
classes as well. The color maps only know about [0, 1]
, so you will have to make sure that your norm
maps to .5
where you want the change over to happen.
You could probably generalize this to take a list of maps and split points and have as many color maps as you want. This also needs all manner of sanity checks.
If you re-normalize the input, you could also use this to make a periodic version of any existing color map by passing it the color map and it's reversed partner.
I think it is simpler to make the colormap yourself, especially when so few colors are involved. This one is orange-white-blue.
cdict = {'red': [ (0.0, 0.0, 0.0),
(0.475, 1.0, 1.0),
(0.525, 1.0, 1.0),
(1.0, 1.0, 1.0)
],
'green': [ (0.0, 0.0, 0.0),
(0.475, 1.0, 1.0),
(0.525, 1.0, 1.0),
(1.0, 0.65, 0.0)
],
'blue': [ (0.0, 1.0, 1.0),
(0.475, 1.0, 1.0),
(0.525, 1.0, 1.0),
(1.0, 0.0, 0.0)
]
}
rwb_cmap = matplotlib.colors.LinearSegmentedColormap(name = 'rwb_colormap', colors = cdict, N = 256)
A colormap is a dictionary for the RGB values. For each color, a list of tupples gives the different segments. Each segment is a point along the z-axis, ranging from 0 to 1. The colors for the levels is interpolated from these segments.
segment z-axis end start
i z[i] v0[i] v1[i]
i+1 z[i+1] v0[i+1] v1[i+1]
i+2 z[i+2] v0[i+2] v1[i+2]
Levels between z[i]
and z[i+1]
will have colors between v1[i]
and v0[i+1]
etc. This makes it possible to 'jump' colors. v0[0]
and v1[-1]
are not used. You can use as many segments as you want. (adapted from here: http://matplotlib.org/api/colors_api.html#matplotlib.colors.LinearSegmentedColormap)
N
is the number of quantization levels. So for N = 256
it will interpolate the map for 256 levels. I use 256 out of laziness. I guess you have to be careful when you set N = 6
and you make 4 contours.
The 0.475 and 0.525 are to ensure that the middle contour is truly white. For the levels [-1.5, -0.5, 0.5, 1.5]
the fill is now orange-white-blue. If I had used 0.5 instead the middle level would be an interpolation of blue-ish and orange-ish.
The RGB code for orange is 255-165-0 or 1-0.65-0 if the scale is 0-1.