2

Some background

I have a 2-d array in the shape of (50,50), the data value are range from -40 ~ 40.
But I want to plot the data in three data range[<0], [0,20], [>20]

Then, I need to generate a colormap corresponding to the three section.

I have some thought now

## ratio is the original 2-d array
binlabel = np.zeros_like(ratio)
binlabel[ratio<0] = 1
binlabel[(ratio>0)&(ratio<20)] = 2
binlabel[ratio>20] = 3

def discrete_cmap(N, base_cmap=None):
    base = plt.cm.get_cmap(base_cmap)
    color_list = base(np.linspace(0, 1, N))
    cmap_name = base.name + str(N)
    return base.from_list(cmap_name, color_list, N)

fig  = plt.figure()
ax = plt.gca()
plt.pcolormesh(binlabel, cmap = discrete_cmap(3, 'jet'))
divider = make_axes_locatable(ax)
cax = divider.append_axes("bottom", size="4%", pad=0.45)
cbar = plt.colorbar(ratio_plot, cax=cax, orientation="horizontal")
labels = [1.35,2,2.65]
loc    = labels
cbar.set_ticks(loc)
cbar.ax.set_xticklabels(['< 0', '0~20', '>20']) 

Is there any better approach? Any advice would be appreciate.

1 Answer 1

3

There are various answers to other questions using ListedColormap and BoundaryNorm, but here's an alternative. I've ignored the placement of your colorbar, as that's not relevant to your question.

You can replace your binlabel calculation with a call to np.digitize() and replace your discrete_cmap() function by using the lut argument to get_cmap(). Also, I find it easier to place the color bounds at .5 midpoints between the indexes rather than scale to awkward fractions of odd numbers:

import matplotlib.colors as mcol
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np

ratio = np.random.random((50,50)) * 50.0 - 20.0

fig2, ax2 = plt.subplots(figsize=(5,5))

# Turn the data into an array of N bin indexes (i.e., 0, 1 and 2).
bounds = [0,20]
iratio = np.digitize(ratio.flat,bounds).reshape(ratio.shape)

# Create a colormap containing N colors and a Normalizer that defines where 
# the boundaries of the colors should be relative to the indexes (i.e., -0.5, 
# 0.5, 1.5, 2.5).
cmap = cm.get_cmap("jet",lut=len(bounds)+1)
cmap_bounds = np.arange(len(bounds)+2) - 0.5
norm = mcol.BoundaryNorm(cmap_bounds,cmap.N)

# Plot using the colormap and the Normalizer.
ratio_plot = plt.pcolormesh(iratio,cmap=cmap,norm=norm)
cbar = plt.colorbar(ratio_plot,ticks=[0,1,2],orientation="horizontal")
cbar.set_ticklabels(["< 0","0~20",">20"])

Example discrete color bar

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.