0

I am trying to create a custom colormap using pyplot for a figure produced using pcolormesh. I would like the colormap to be non-uniform. I want to be able to pick out small changes while grouping larger changes together. Sort of like the idea of a logarithmic colormap, without necessarily being logarithmic.

However, the colors that I expect to show up on the colorbar are not all there. Here is some code to reproduce this:

from matplotlib import pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np

cbins = [-10., -5., -2., -1., -0.5, -0.1, 0.1, 0.5, 1., 2., 5., 10.] # log-ish colormap bins
# cbins = np.arange(-10, 11, 2) # linear colormap bins
colors = [(0.0, 0.0, 0.0), # a terrible grayscale colormap, for illustration
          (0.2, 0.2, 0.2),
          (0.4, 0.4, 0.4),
          (0.6, 0.6, 0.6),
          (0.8, 0.8, 0.8),
          (1.0, 1.0, 1.0),
          (0.8, 0.8, 0.8),
          (0.6, 0.6, 0.6),
          (0.4, 0.4, 0.4),
          (0.2, 0.2, 0.2),
          (0.0, 0.0, 0.0),
          ]

cmap = LinearSegmentedColormap.from_list('test', colors, N=len(cbins)-1) # converted to colormap

x = (np.random.rand(20, 20) * 20) - 10 # array of random values between -10 and +10
p = plt.pcolormesh(x, cmap=cmap, vmin=min(cbins), vmax=max(cbins)) # plotted
plt.colorbar(p, boundaries=cbins, spacing='uniform', ticks=cbins) # ticks and boundaries set

Below is the plot I get as a result.

colorbar with repeated colors at the center and missing colors at the extremes

I would expect white to appear in the central bin (-0.1, 0.1), followed by light gray and so on, with black at the outer bins.

When I uncomment the line with linear colormap bins, it works as expected. See the image below.

colorbar with all expected colors present

Am I missing something obvious? I've searched for a couple hours now without any luck.

I am using python 3.8.12 with matplotlib 3.4.3. Incidentally, the result is somewhat different (worse) with matplotlib 3.5.0... as if the spacing='uniform' does not work.

  • From the [docs](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html): The lookup table is generated using linear interpolation for each primary color, with the 0-1 domain divided into any number of segments. Your mapping is not linear, as the bins are unevenly spaced. [This SO answer](https://stackoverflow.com/a/9708079/2912349) outlines how you can construct a segmented colormap with arbitrary bins. – Paul Brodersen Dec 08 '21 at 10:28
  • Great, thanks @PaulBrodersen. So I guess my problem was assuming that LinearSegmentedColormap would give me a nonlinear colormap. The ListedColormap proposed in that other answer gave me what I wanted. –  Dec 08 '21 at 15:29

0 Answers0