How can I get the matplotlib rgb color, given the colormap name, BoundryNorm, and 'c='?

TrailDreaming picture TrailDreaming · Sep 29, 2014 · Viewed 20.6k times · Source

How can I get the matplotlib rgb value for a number, NUM, given:

  1. A colormap ('autumn_r' which is yellow-to-red in the example below)
  2. BoundryNorm values("2 to 10" in the example below)
  3. The number NUM

In my example, I would like:

  1. Given any value 2 or less, returns the rgb value for yellow.
  2. Given any value 10 or more, returns the rgb value for red.
  3. Given values in the range 3 <= NUM <= 9, a color between yellow and red will be chosen from the specified colormap

The code below shows the use of the colormap and defining my boundry values. Now I just need a function which will return my rgb value instead of doing a scatter plot. The scatter plot is for visualization only so I could see that the Normalization was working as I had wished.

import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib import cm
import numpy as np
import copy

# setup the plot
fig, ax = plt.subplots(1,1, figsize=(6,6))

# define the data
NUM_VALS = 20
NORM_ENDS = (2,10)
x = np.random.uniform(0, NUM_VALS, size=NUM_VALS)
y = np.random.uniform(0, NUM_VALS, size=NUM_VALS)
tag = copy.deepcopy(y)

# define the colormap
cmap = plt.get_cmap('autumn_r')
cmaplist = [cmap(i) for i in range(cmap.N)]

# create the new map
cmap = cmap.from_list('Custom cmap', cmaplist[0:], cmap.N)

# define the bins and normalize
bounds = np.linspace(NORM_ENDS[0], NORM_ENDS[1], NORM_ENDS[1]-NORM_ENDS[0]+1)
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)

# make the scatter
scat = ax.scatter(x,y,s=300, c=tag,cmap=cmap,norm=norm)

# create a second axes for the colorbar
ax2 = fig.add_axes([0.90, 0.1, 0.03, 0.8])
cb = mpl.colorbar.ColorbarBase(ax2, cmap=cmap, norm=norm, spacing='proportional', ticks=bounds, boundaries=bounds, format='%1i')

ax.set_title('Well defined discrete colors')
ax2.set_ylabel('Very custom cbar [-]', size=12)

plt.show()

Answer

TrailDreaming picture TrailDreaming · Sep 29, 2014

Got it. I created a colormap helper object containing a "get_rgb" function:

import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm

class MplColorHelper:

  def __init__(self, cmap_name, start_val, stop_val):
    self.cmap_name = cmap_name
    self.cmap = plt.get_cmap(cmap_name)
    self.norm = mpl.colors.Normalize(vmin=start_val, vmax=stop_val)
    self.scalarMap = cm.ScalarMappable(norm=self.norm, cmap=self.cmap)

  def get_rgb(self, val):
    return self.scalarMap.to_rgba(val)

And example usage:

import numpy as np
# setup the plot
fig, ax = plt.subplots(1,1, figsize=(6,6))

# define the data between 0 and 20
NUM_VALS = 20
x = np.random.uniform(0, NUM_VALS, size=NUM_VALS)
y = np.random.uniform(0, NUM_VALS, size=NUM_VALS)

# define the color chart between 2 and 10 using the 'autumn_r' colormap, so
#   y <= 2  is yellow
#   y >= 10 is red
#   2 < y < 10 is between from yellow to red, according to its value
COL = MplColorHelper('autumn_r', 2, 10)

scat = ax.scatter(x,y,s=300, c=COL.get_rgb(y))
ax.set_title('Well defined discrete colors')
plt.show()