A. Create new colormap
You can indeed create a new colormap specifically for this case,
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
p = [-6, -1.5, 0.5, 6]
f = lambda x: np.interp(x, p, [0, 0.5, 0.5, 1])
cmap = LinearSegmentedColormap.from_list('map_white',
list(zip(np.linspace(0,1), plt.cm.seismic(f(np.linspace(min(p), max(p)))))))
plt.imshow(np.random.rand(10,10)*12-6, vmin=min(p), vmax=max(p), cmap=cmap)
plt.colorbar()
plt.show()
B. Create new normalization
Alternatively, create a new normalization with two inner points, which are interpolated to. This is similar to the answer to merge-colormaps-in-matplotlib, just with the two points being almost equal.
import numpy as np
import matplotlib.pyplot as plt
class StretchOutNormalize(plt.Normalize):
def __init__(self, vmin=None, vmax=None, low=None, up=None, clip=False):
self.low = low
self.up = up
plt.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
x, y = [self.vmin, self.low, self.up, self.vmax], [0, 0.5-1e-9, 0.5+1e-9, 1]
return np.ma.masked_array(np.interp(value, x, y))
norm=StretchOutNormalize(vmin=-6, vmax=6, low=-1.5, up=0.5)
plt.imshow(np.random.rand(10,10)*12-6, cmap="seismic", norm=norm)
plt.colorbar()
plt.show()
In both cases the result is the same:
