How to create a linear colormap with color defined at specific values with matplotlib?

849 views Asked by At

I would like to create a colormap that fade linearly through colors defined for specific values. Below here is my Minimal Non Working Example.

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

data = np.random.uniform(0, 10, (10, 10))

values = [0., 0.8, 1., 10.]
colors = ["#ff0000", "#00ff00", "#0000ff", "#cccccc"]

I have the feeling this can be solved by using cmap and norm switches when plotting with imshow but I could not succeed to have a smooth gradient of colors passing by defined colors at values.

cmap = mpl.colors.ListedColormap(colors, name="mycmap")
norm = mpl.colors.BoundaryNorm(values, len(colors))

fig, axe  = plt.subplots()
cmap_ = axe.imshow(data, aspect="auto", origin="upper", cmap=cmap, norm=norm)
cbar = fig.colorbar(cmap_, ax=axe)

Also the scale is then non linear.

enter image description here

How can I setup this colormap using the provided values and colors above?

1

There are 1 answers

1
jlandercy On BEST ANSWER

Here is the current solution I have found to solve my problem:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
    
def get_colormap(values, colors, name="custom"):
    values = np.sort(np.array(values))
    values = np.interp(values, (values.min(), values.max()), (0., 1.))
    cmap = mpl.colors.LinearSegmentedColormap.from_list(name, list(zip(values, colors)))
    return cmap

data = np.random.uniform(0, 10, (10, 10))
values = np.array([0., 0.8, 1., 10.])
colors = ["#ff0000", "#00ff00", "#0000ff", "#cccccc"]
cmap_ = get_colormap(values, colors)

fig, axe  = plt.subplots()
cmap = axe.imshow(data, aspect="auto", origin="upper", cmap=cmap_)
cbar = fig.colorbar(cmap, ax=axe)

Not straightforward but functional. I'll keep the question unanswered to leave opportunity to best solution to come.

enter image description here