Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to extract a subset of a colormap as a new colormap in matplotlib?

I would like to use a colormap from matplotlib e.g. CMRmap. But I don't want to use the "black" color at the beginning and the "white" color at the end. I'm interested to plot my data using the in-between colors. I think ppl use it quite often but I was searching over internet and could not manage to find any simple solution. I'll appreciate if someone suggest any solution.

like image 704
rana Avatar asked Sep 20 '13 21:09

rana


People also ask

What is the name of the colormap that became the default Matplotlib colormap?

Jet is the default colorbar originally used by matlab, and this default was inherited in the early days of Python's matplotlib package.

What is a sequential colormap?

Sequential colormaps (that are perceptually uniform of course) are basic colormaps that start at a reasonably low lightness value and uniformly increase to a higher value. They are commonly used to represent information that is ordered.

How do you reverse colormap?

By using the reversed() function to reverse the colormap. By using “_r” at the end of colormap name.


2 Answers

The staticmethod colors.LinearSegmentedColormap.from_list can be used to create new LinearSegmentedColormaps. Below, I sample the original colormap at 100 points between 0.2 and 0.8:

cmap(np.linspace(0.2, 0.8, 100)) 

and use these colors to generate a new colormap:

import matplotlib.pyplot as plt import matplotlib.colors as colors import numpy as np  def truncate_colormap(cmap, minval=0.0, maxval=1.0, n=100):     new_cmap = colors.LinearSegmentedColormap.from_list(         'trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name, a=minval, b=maxval),         cmap(np.linspace(minval, maxval, n)))     return new_cmap  arr = np.linspace(0, 50, 100).reshape((10, 10)) fig, ax = plt.subplots(ncols=2)  cmap = plt.get_cmap('jet') new_cmap = truncate_colormap(cmap, 0.2, 0.8) ax[0].imshow(arr, interpolation='nearest', cmap=cmap) ax[1].imshow(arr, interpolation='nearest', cmap=new_cmap) plt.show() 

enter image description here

The plot on the left shows the image using the original colormap (in this example, jet). The plot on the right shows the same image using new_cmap.

like image 127
unutbu Avatar answered Sep 23 '22 02:09

unutbu


I was just recently struggling with this on my own. Here are some possible solutions:


Try using vmin, vmax keyword arguments in your plotting function. For example, say you had data between 0 and 1 but didn't like the colors used at the extremes of the colormap for 0 and 1.

import matplotlib.pyplot as plt import matplotlib.cm as cm  my_cmap = cm.spectral_r my_cmap.set_over('c') my_cmap.set_under('m') plt.pcolor(data, vmin=0.01, vmax=0.99, cmap=my_cmap) 

This will force the entire colormap to be used for values between 0.01 and 0.99 and values above and below will be cyan and magenta respectively. This may not solve your problem exactly, but it could be useful if you like a particular colormap and wish it had additional colors at both ends.


If you really want to change the colormap, look at the documentation here and for LinearSegmentedColormap here.

First,

import matplotlib.cm as cm cdict = cm.get_cmap('spectral_r')._segmentdata 

This returns a dictionary of all the colors that make up the colormap. However, it's pretty tricky figuring out exactly how to alter this dictionary. This dict has three keys, red, green, blue. cdict[key] returns a list of values of the form (x, y0, y1). Let's take a look at two consecutive elements of cdict['red']:

((0.0, 0.0, 0.0)  (0.5, 1.0, 1.0),... 

What this means is that data with z (assuming we're doing a pcolor or imshow) between 0.0 and 0.5 will have the red component of the rgb color associated with that data will increase from 0.0 (no red) to 1.0 (maximum red). This means that to change the color of the colormap, you have to examine how each of the three components of rgb are interpolated in the region of the colormap that you are interested in. Just make sure that for each color, the first and the last entry start with x=0 and x=1 respectively; you must cover the whole spectrum of [0, 1].

If you want to change the beginning and end colors, try

import matplotlib.cm as cm from matplotlib.colors import LinearSegmentedColormap cdict = cm.get_cmap('spectral_r')._segmentdata  cdict['red'][0] = (0, 0.5, 0.5) # x=0 for bottom color in colormap cdict['blue'][0] = (0, 0.5, 0.5) # y=0.5 gray cdict['green'][0] = (0, 0.5, 0.5) # y1=y for simple interpolation cdict['red'][-1] = (1, 0.5, 0.5) # x=1 for top color in colormap cdict['blue'][-1] = (1, 0.5, 0.5) cdict['green'][-1] = (1, 0.5, 0.5)  my_cmap = LinearSegmentedColormap('name', cdict) 

Then use this cmap in your plotting function.


What I wanted to do was change the gray at the end of the spectral_r colormap to pure white. This was achieved using

# Using imports from above cdict = matplotlib.cm.get_cmap('spectral_r')._segmentdata cdict['red'][0] = (0, 1, 1) cdict['green'][0] = (0, 1, 1) cdict['blue'][0] = (0, 1, 1) my_cmap = LinearSegmentedColormap('my_cmap', cdict) 
like image 40
wflynny Avatar answered Sep 22 '22 02:09

wflynny