I'm trying to create a color bar with 13 levels and use a diverging RdBu_r colormap with the central value spaced at 0. Currently, I have an evenly spaced colorbar with values descending by 8 ranging from -48 to +48
What I would like to make is a colorbar with even colored spacing, but unevenly spaced values, like this colorbar which I modified in photoshop, such that the values go from [-96.0, -72, -48, -24, -12, -6, 0, 6, 12, 24, 48, 72, 96]
My current attempt looks like this:
from cartopy import crs as ccrs; import matplotlib.pyplot as plt
crs_new = ccrs.PlateCarree()
fig, axs = plt.subplots(subplot_kw={'projection': crs_new},figsize=(8, 6))
cmap = 'RdBu_r'
uneven_levels = [-96.0, -72, -48, -24, -12, -6, 0, 6, 12, 24, 48, 72, 96]
vmin,vmax = -48,48
cs=plt.pcolormesh(lon,lat, data,cmap=cmap, transform=crs_new,vmin=vmin,vmax=vmax)
cbar=plt.colorbar(cs,boundaries= uneven_levels)
Which results in a colorbar with really dark ends and clearly uses linearly spaced coloring.
Using countourf and "spacing = uniform" did not work.
Using "colors.DivergingNorm(vmin=vmin, vcenter=0, vmax=vmax)" did not work.
I've tried to define my own color bar with
cmap = plt.get_cmap('RdBu_r')
colors = cmap(np.linspace(0, 1, len(uneven_levels)))
but have no idea to get the data to match up with these levels, results in the same thing as figure 3, so this also did not work.
Any help is greatly appreciated! :)
The reason there are a lot of dark colors is vmin, vmax = -48, 48
which forces all values below -48
to the darkest blue, and all values above 48
to the darkest red.
To obtain a similar effect as contourf
, matplotlib's from_levels_and_colors
could be helpful. This generates a colormap with 12 colors, and a norm. The norm is a function that converts values between -96 and 96 to values for the colormap, as defined by the levels.
Here is some example code:
import numpy as np
import seaborn as sns
from matplotlib import pyplot as plt
import matplotlib.colors as mcolors
x = np.linspace(0, 3 * np.pi, 500)
data = np.sin(x - x[:, np.newaxis] * 2) * 95
uneven_levels = [-96, -72, -48, -24, -12, -6, 0, 6, 12, 24, 48, 72, 96]
cmap_rb = plt.get_cmap('RdBu_r')
colors = cmap_rb(np.linspace(0, 1, len(uneven_levels) - 1))
cmap, norm = mcolors.from_levels_and_colors(uneven_levels, colors)
fig, axs = plt.subplots(ncols=2, figsize=(8, 6))
v = np.linspace(-96, 96, 1000)
axs[0].plot(v, norm(v))
cs = axs[1].pcolormesh(data, cmap=cmap, norm=norm)
cbar = fig.colorbar(cs, ticks=uneven_levels)
plt.show()
The image on the left shows how the boundary norm maps values between -96 and 96 to their respective color in a nonlinear fashion. The image on the right show the a colorbar with the boundaries.