Skip to content Skip to sidebar Skip to footer

Matplotlib Bwr-colormap, Always Centered On Zero

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 ra

Solution 1:

You can use matplotlib.colors.TwoSlopeNorm like this:

# define your scale, with white at zerovmin = -0.2vmax = 0.8norm = 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:

enter image description here

Solution 2:

Apparently, I found the answer myself after digging a little longer. pcolor offers the optional input vmin and vmax. If I set them to -1 and 1 respectively, it exactly solves the problem. The colorcoding then seems to be relative to vmin and vmax, not to the min and max of the data, which is plotted. So changing the plot command (and comments) to

# a plot ranging from -1 to 1, where the value 0 is colorcoded in white
ax = fig.add_subplot(1, 2, 1)
plt.pcolor(X, Y, Z, vmin=-1, vmax=1) # vmin, vmax not needed here
plt.colorbar()

# a plot ranging from -0.2 to 0.8, where the value 0 is colorcoded in white
ax = fig.add_subplot(1, 2, 2)
plt.pcolor(X, Y, Z*0.5 + 0.3, vmin=-1, vmax=1)   # rescaled Z-Data
plt.colorbar()

It produces a figure as I need it:correct figure

So, setting vmin=-1, vmax=1 does the job, i do not have to change stuff on the colormap itself.

Solution 3:

Also you can normalize the data with 0 as a midpoint with matplotlib.colors, for enhence the mimimus and maximums values of the graphic. For more information in Colormap Norms you can see more detailed information.

import matplotlib.colors as colors
# Example of making your own norm.  Also see matplotlib.colors.# From Joe Kington: This one gives two different linear ramps:classMidpointNormalize(colors.Normalize):
    def__init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        self.midpoint = midpoint
        colors.Normalize.__init__(self, vmin, vmax, clip)

    def__call__(self, value, clip=None):
        # I'm ignoring masked values and all kinds of edge cases to make a# simple example...
        x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
        return numpy.ma.masked_array(numpy.interp(value, x, y))
###### 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, norm=MidpointNormalize(midpoint=0))   # Set midpoint as 0
plt.colorbar(extend='min') # To extend colorbar in the min values
plt.subplots_adjust(left=0.125, bottom=0.1, right=0.9, top=0.95, wspace=0.5, hspace=0.1) # to adjust the subplots

It produces this figure: enter image description here

Post a Comment for "Matplotlib Bwr-colormap, Always Centered On Zero"