I am trying to plot a matrix with positive and negative numbers. The numbers will be in an interval from -1 to 1 but not at the complete range. Numbers could sometimes be in the range from -0.2 to +0.8 for example (See code below). I want to use the bwr-colormap (blue -> white - red) such that zero is always color-coded in white. -1 should be colorcoded in the darkest possible blue and +1 should be colorcoded in the darkest possible red. Here comes an example, where both plots are only distinguishable by their colorbar.
import numpy
from matplotlib import pyplot as plt
# some arbitrary data to plot
x = numpy.linspace(0, 2*numpy.pi, 30)
y = numpy.linspace(0, 2*numpy.pi, 20)
[X, Y] = numpy.meshgrid(x, y)
Z = numpy.sin(X)*numpy.cos(Y)
fig = plt.figure()
plt.ion()
plt.set_cmap('bwr') # a good start: blue to white to red colormap
# a plot ranging from -1 to 1, hence the value 0 (the average) is colorcoded in white
ax = fig.add_subplot(1, 2, 1)
plt.pcolor(X, Y, Z)
plt.colorbar()
# a plot ranging from -0.2 to 0.8 hence 0.3 (the average) is colorcoded in white
ax = fig.add_subplot(1, 2, 2)
plt.pcolor(X, Y, Z*0.5 + 0.3) # rescaled Z-Data
plt.colorbar()
The figure created by this code can be seen here:
As stated above, i am looking for a way to always color-code the values with the same colors, where -1: dark blue, 0: white, +1: dark red. Is this a one-liner and i am missing something or do i have to write something myself for this?
EDIT:
After digging a little bit longer i found a satisfying answer myself, not touching the colormap but rather using optional inputs to pcolor
(see below).
Still, I will not delete the question as i could not find an answer on SO until i posted this question and clicked on the related questions/answers. On the other hand, i wouldn't mind if it got deleted, as answers to exactly this question can be found elsewhere if one is looking for the right keywords.
will map the data in Z linearly from -1 to +1, so Z=0 will give a color at the center of the colormap RdBu_r (white in this case). Matplotlib does this mapping in two steps, with a normalization from the input data to [0, 1] occurring first, and then mapping onto the indices in the colormap.
The colorbar() function in pyplot module of matplotlib adds a colorbar to a plot indicating the color scale.
You can use matplotlib.colors.TwoSlopeNorm like this:
# define your scale, with white at zero
vmin = -0.2
vmax = 0.8
norm = colors.TwoSlopeNorm(vmin=vmin, vcenter=0, vmax=vmax)
In your example would be,
import numpy
from matplotlib import pyplot as plt
# some arbitrary data to plot
x = numpy.linspace(0, 2*numpy.pi, 30)
y = numpy.linspace(0, 2*numpy.pi, 20)
[X, Y] = numpy.meshgrid(x, y)
Z = numpy.sin(X)*numpy.cos(Y)
fig = plt.figure()
plt.ion()
plt.set_cmap('bwr') # a good start: blue to white to red colormap
# a plot ranging from -1 to 1, hence the value 0 (the average) is colorcoded in white
ax = fig.add_subplot(1, 2, 1)
plt.pcolor(X, Y, Z)
plt.colorbar()
# a plot ranging from -0.2 to 0.8 hence 0.3 (the average) is colorcoded in white
ax = fig.add_subplot(1, 2, 2)
# define your scale, with white at zero
vmin = -0.2
vmax = 0.8
norm = colors.TwoSlopeNorm(vmin=vmin, vcenter=0, vmax=vmax)
plt.pcolor(X, Y, Z, vmin=vmin, vmax=vmax, norm=norm)
plt.colorbar()
will give you:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With