'How do I make non-continuous colorbar in matplotlib?

Using matplotlib, I want to make a colorbar like the one pictured here:

I want my colorbar to basically jump from 0 to 65/-65, then go linearly up to 100/-100. In other words, I want 65/-65 to be the dimmest colors (red/blue using seismic colormap) on the colorbar, 0 to be white, and 100/-100 to be the darkest colors.



Solution 1:[1]

Here is an attempt to use the SymLogNorm. It doesn't completely work out as it should; especially the tick locations seem to be a bit off. Maybe it can serve as a start for further experimentation.

from matplotlib import pyplot as plt
from matplotlib.colors import SymLogNorm
from matplotlib.cm import ScalarMappable
from matplotlib.ticker import ScalarFormatter
import numpy as np

norm = SymLogNorm(linthresh=60, linscale=0.05, vmin=-100, vmax=100)
xs = np.linspace(-100, 100, 1000)
plt.figure(figsize=(15, 5))
plt.plot(xs, norm(xs))
x = np.linspace(-100, 100, 21)
plt.scatter(x, norm(x), c=x, norm=norm, cmap='seismic', s=200, edgecolor='black')
cbar = plt.colorbar(ScalarMappable(cmap='seismic', norm=norm), pad=0.02)
cbar.ax.yaxis.set_major_formatter(ScalarFormatter())
cbar.ax.yaxis.set_ticks([-100, -90, -80, -70, -60, 60, 70, 80, 90, 100])
plt.xlabel('input value')
plt.ylabel('normalized value')
plt.tight_layout()
plt.show()

visualizing SymLogNorm

Here is a test with a BoundaryNorm using many subdivisions to counter its stepwise nature.

from matplotlib import pyplot as plt
from matplotlib.colors import BoundaryNorm
from matplotlib.cm import ScalarMappable
from matplotlib.ticker import ScalarFormatter
import numpy as np

ticks = [-100, -90, -80, -70, -60, 60, 70, 80, 90, 100]
bounds = np.r_[np.arange(-100, -59), np.linspace(-50, 50, 11), np.arange(60, 101)]
norm = BoundaryNorm(bounds, 256)
xs = np.linspace(-100, 100, 1000)
plt.figure(figsize=(15, 5))
plt.plot(xs, norm(xs))
x = np.linspace(-100, 100, 21)
plt.scatter(x, norm(x), c=x, norm=norm, cmap='seismic', s=200, edgecolor='black')
cbar = plt.colorbar(ScalarMappable(cmap='seismic', norm=norm), pad=0.02, ticks=ticks)
plt.xlabel('input value')
plt.ylabel('normalized value')
plt.tight_layout()
plt.show()

visualizing BoundaryNorm

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1