0

I was trying to debug some visualization code and when I worked back to ultra-basics, I discovered a confusing behavior that makes me think I'm missing something fundamentally about matplotlib cmaps.

This works as i expect -- printing a range of reds and blues corresponding to randomly generated values between 0,1.

fig = plt.figure()
CMAP =  "seismic"   # blue-white-red colormap
a = np.array(np.random.rand(50,50)/2,).reshape(50,50)
plt.imshow(a, cmap=plt.get_cmap(CMAP))

enter image description here

But if I make the array values homogenous, the plot is always the same dark blue value regardless of what the array's value is.

fig = plt.figure()
CMAP =  "seismic"   # blue-white-red colormap

#either of these two lines gives the same result
a = np.array([0.9]*50*50).reshape(50,50)
a = np.array([0.1]*50*50).reshape(50,50)

enter image description here

As long as the array doesn't have homogenous values, it seems to work as expected, for example

a = np.array([0.1,.9]*25*50).reshape(50,50)

renders with stripes, as I'd guess.

0

1 Answer 1

2

To see what is happening, it is helpful to add a colorbar next to the image:

import numpy as np
import matplotlib.pyplot as plt

cmap =  "seismic"
a = np.random.rand(50,50)/2
plt.imshow(a, cmap=cmap)
plt.colorbar()
plt.show()

imshow random

Note that dark blue corresponds to the value 0 and dark red to 0.5.

The following shows what happens in the other cases:

fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(12, 3))
cmap = "seismic"

a = np.full((50,50), 0.9)
img1 = ax1.imshow(a, cmap=cmap)
plt.colorbar(img1, ax=ax1)

a = np.full((50,50), 0.1)
img2 = ax2.imshow(a, cmap=cmap)
plt.colorbar(img2, ax=ax2)

a = np.repeat([0.1,.9], 25*50).reshape(50,50)
img3 = ax3.imshow(a, cmap=cmap)
plt.colorbar(img3, ax=ax3)

3 subplots

When all data values are 0.9, matplotlib chooses a small range (in this case from 0.825 to 0.975) where the constant value 0.9 now corresponds to white. (Your example code seems to use an older version of matplotlib where the constant value corresponds to the darkest color). Something similar happens for the constant 0.1, with another range.

With half 0.1 and half 0.9, the range is set from 0.1 to 0.9, with 0.1 corresponding to dark blue and 0.9 to dark red.

These values are accessible via parameters, they are called vmin and vmax. When drawing many plots it can be interesting to use the same vmin and vmax for all of them. Here are the same examples, but with imshow(..., vmin=0, vmax=1):

using vmin=0 vmax=1

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

1 Comment

hey thanks for this excellent answer. IT answered my question AND enabled me to solve the trickier deeper problem. Basically the matplotlib axis was rescaling in ways I didn't expect. vmin, vmax fixed it.

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.