Combine three 2D colorap in one figure using Python and Matplotlib.pyplot


The result is:
If you want to plot three 2D colormaps on one figure, the only feasible way is combining these three colormaps to one image. This can be achieved by corresponding three values to three primary elements, i.e. red, green, blue. However, interpretation of the completed figure is quite complex, and easiness of understanding for readers would be decreased. In my opinion, this way for plotting should be avoided.

If you want to plot three 2D colormaps on one figure, the only feasible way is combining these three colormaps to one image. This can be achieved by corresponding three values to three primary elements, i.e. red, green, blue. However, interpretation of the completed figure is quite complex, and easiness of understanding for readers would be decreased. In my opinion, this way for plotting should be avoided.


See also:

Python Matplotlib Tips: Combine multiple line plot and contour plot with a colorbar using Python and matplotlib.pyplot

This code shows how to combine multiple line plot and contour plot with colorbar in one figure using Python and matplotlib.pyplot. To combine these plots, plt.subplots with gridspec_kw options are used. The xlims are also adjusted.

Python Matplotlib Tips: Draw second colorbar axis outside of first axis

This code shows how to draw second colorbar ticks outside of first colorbar axis.


In [1]:
import platform
print('python: '+platform.python_version())
import matplotlib.pyplot as plt
from matplotlib import __version__ as matplotlibversion
print('matplotlib: '+matplotlibversion)
import numpy as np
print('numpy: '+np.__version__)
%matplotlib inline

from matplotlib.colors import LinearSegmentedColormap
from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec
python: 3.6.3
matplotlib: 3.0.1
numpy: 1.15.4
In [2]:
# define values to plot, mn:min, mx: max
xmn, xmx, xnn = -10, 10, 501
x = np.linspace(xmn, xmx, xnn)
ymn, ymx, ynn = 0, 20, 501
y = np.linspace(ymn, ymx, ynn)
xx, yy = np.meshgrid(x, y)

# the offset of each values is meaningless values
u = np.sin(xx)
umn, umx = -1, 1
v = 10 + np.sin(yy)
vmn, vmx = 10-1, 10+1
w = -10 + np.sin(xx*yy)
wmn, wmx = -10-1, -10+1
In [3]:
plt.contourf(xx, yy, u)
plt.gca().set_aspect('equal')
plt.colorbar()
plt.show()
In [4]:
plt.contourf(xx, yy, v)
plt.gca().set_aspect('equal')
plt.colorbar()
plt.show()
In [5]:
plt.contourf(xx, yy, w)
plt.gca().set_aspect('equal')
plt.colorbar()
plt.show()

Convert array to uint8. The minimum and maximum values of uint8 are 0 and 255.

In [6]:
def array_to_0_255_float(arr, mn, mx):
    return (arr-mn)/(mx-mn)*255

def array_to_0_255_uint8(arr, mn, mx):
    return array_to_0_255_float(arr, mn, mx).astype("uint8")
    
umod = array_to_0_255_uint8(u, umn, umx)
vmod = array_to_0_255_uint8(v, vmn, vmx)
wmod = array_to_0_255_uint8(w, wmn, wmx)

Check w array whose type is now uint8

In [7]:
plt.imshow(wmod, origin="lower")
plt.colorbar()
plt.show()

Combine u, v, and w array. The order is corresponding to [r, g, b]

In [8]:
uvwmod = np.dstack([umod, vmod, wmod])
uvwmod
Out[8]:
array([[[196, 127, 127],
        [192, 127, 127],
        [188, 127, 127],
        ...,
        [ 66, 127, 127],
        [ 62, 127, 127],
        [ 58, 127, 127]],

       [[196, 132,  77],
        [192, 132,  78],
        [188, 132,  78],
        ...,
        [ 66, 132, 176],
        [ 62, 132, 176],
        [ 58, 132, 177]],

       [[196, 137,  36],
        [192, 137,  36],
        [188, 137,  36],
        ...,
        [ 66, 137, 218],
        [ 62, 137, 218],
        [ 58, 137, 218]],

       ...,

       [[196, 239, 249],
        [192, 239, 186],
        [188, 239,  88],
        ...,
        [ 66, 239, 166],
        [ 62, 239,  68],
        [ 58, 239,   5]],

       [[196, 241, 254],
        [192, 241, 225],
        [188, 241, 138],
        ...,
        [ 66, 241, 116],
        [ 62, 241,  29],
        [ 58, 241,   0]],

       [[196, 243, 238],
        [192, 243, 249],
        [188, 243, 186],
        ...,
        [ 66, 243,  68],
        [ 62, 243,   5],
        [ 58, 243,  16]]], dtype=uint8)

Generate three colormaps for red, green and blue.
The minimum values of each colormap are set to (0, 0, 0) = black.

In [9]:
def cmap_generator(colors):
    vals = range(len(colors))
    vmax = np.ceil(np.max(vals))
    color_list = [( v/ vmax, c) for v, c in zip(vals, colors)]
    return LinearSegmentedColormap.from_list('custom_cmap', color_list)

cmap_r = cmap_generator([(0, 0, 0), (1, 0, 0)])
cmap_g = cmap_generator([(0, 0, 0), (0, 1, 0)])
cmap_b = cmap_generator([(0, 0, 0), (0, 0, 1)])
In [10]:
fig = plt.figure(figsize=(6, 5))

gs = GridSpec(nrows=5, ncols=2, width_ratios=[1,0.5], height_ratios=[1, 0.2, 0.2, 0.2, 1])
ax11 = fig.add_subplot(gs[:, 0])
ax21, ax22, ax23, ax24, ax25 = [fig.add_subplot(gs[i, 1]) for i in range(5)]
ax21.set_visible(False)
ax25.set_visible(False)

ax11.imshow(uvwmod, origin="lower")

ax11.set_xticklabels(np.linspace(xmn, xmx, 5))
ax11.set_xticks(np.linspace(0, len(x)-1, 5))
ax11.set_yticklabels(np.linspace(ymn, ymx, 5))
ax11.set_yticks(np.linspace(0, len(y)-1, 5))
ax11.set_xlabel("x")
ax11.set_ylabel("y")

# dummpy plot to generate colorbar 1 for value u
cimg = ax21.imshow([[0,0],[0,255]], vmin=0, vmax=255, cmap=cmap_r)
# draw colorbar 1
cbar1 = plt.colorbar(cimg, cax=ax22, orientation='horizontal')
uctkls = np.linspace(umn, umx, 5)
uctks = array_to_0_255_float(uctkls, umn, umx)
cbar1.set_ticks(uctks)
cbar1.set_ticklabels(uctkls)
cbar1.set_label("Value 1: u")

# dummpy plot to generate colorbar 2 for value v
cimg = ax21.imshow([[0,0],[0,255]], vmin=0, vmax=255, cmap=cmap_g)
# draw colorbar 2
cbar2 = plt.colorbar(cimg, cax=ax23, orientation='horizontal')
vctkls = np.linspace(vmn, vmx, 5)
vctks = array_to_0_255_float(vctkls, vmn, vmx)
cbar2.set_ticks(vctks)
cbar2.set_ticklabels(vctkls)
cbar2.set_label("Value 2: v")

# dummpy plot to generate colorbar 3 for value w
cimg = ax21.imshow([[0,0],[0,255]], vmin=0, vmax=255, cmap=cmap_b)
# draw colorbar 3
cbar3 = plt.colorbar(cimg, cax=ax24, orientation='horizontal')
wctkls = np.linspace(wmn, wmx, 5)
wctks = array_to_0_255_float(wctkls, wmn, wmx)
cbar3.set_ticks(wctks)
cbar3.set_ticklabels(wctkls)
cbar3.set_label("Value 3: w")

plt.tight_layout()
plt.savefig("three_2d_map_in_one_figure.png", dpi=150, bbox_inches="tight", pad_inches=0.02)