Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining two matplotlib colormaps

I would like to merge two colormaps into one, such that I can use one cmap for negative values and the other one for positive values.

At the moment I do it with masked arrays and plotting one image with one cmap and the other image with the other, resulting in:

enter image description here

with the following data

dat = np.random.rand(10,10) * 2 - 1
pos = np.ma.masked_array(dat, dat<0)
neg = np.ma.masked_array(dat, dat>=0)

I plotted pos with gist_heat_r and neg with binary.

I would like to have a single colorbar with the combined cmap's, so this is not the correct approach for me.

So, how do I take two existing cmaps's and merge them into one?

EDIT: I admit, this is a duplicate, but the answer that's given is much more clear here. Also the example images make it more clear.

like image 465
johnbaltis Avatar asked Jun 25 '15 13:06

johnbaltis


People also ask

How do I combine Cmaps?

From an open Cmap: You can combine the contents of multiple nested nodes. To combine the contents of multiple nested nodes into one nested node, right-click a selection of nested nodes, then left-click Merge Nodes...

What is CMAP =' viridis?

( cmaps.viridis is a matplotlib.colors.ListedColormap ) import matplotlib.pyplot as plt import matplotlib.image as mpimg import numpy as np import colormaps as cmaps img=mpimg.imread('stinkbug.png') lum_img = np.flipud(img[:,:,0]) imgplot = plt.pcolormesh(lum_img, cmap=cmaps.viridis)

What is the default Matplotlib colormap?

Colormap. The new default colormap used by matplotlib. cm. ScalarMappable instances is 'viridis' (aka option D).


1 Answers

Colormaps are basically just interpolation functions which you can call. They map values from the interval [0,1] to colors. So you can just sample colors from both maps and then combine them:

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

data = np.random.rand(10,10) * 2 - 1

# sample the colormaps that you want to use. Use 128 from each so we get 256
# colors in total
colors1 = plt.cm.binary(np.linspace(0., 1, 128))
colors2 = plt.cm.gist_heat_r(np.linspace(0, 1, 128))

# combine them and build a new colormap
colors = np.vstack((colors1, colors2))
mymap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors)

plt.pcolor(data, cmap=mymap)
plt.colorbar()
plt.show()

Result: enter image description here

NOTE: I understand that you might have specific needs for this, but in my opinion this is not a good approach: How will you distinguish -0.1 from 0.9? -0.9 from 0.1?

One way to prevent this is to sample the maps only from ~0.2 to ~0.8 (e.g.: colors1 = plt.cm.binary(np.linspace(0.2, 0.8, 128))) so they wont go all the way up to black:

enter image description here

like image 138
hitzg Avatar answered Sep 18 '22 11:09

hitzg