jlandercy
jlandercy

Reputation: 11042

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

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?

Upvotes: 0

Views: 1604

Answers (1)

jlandercy
jlandercy

Reputation: 11042

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

Upvotes: 0

Related Questions