matplotlib bwr-colormap, siempre centrado en cero

Estoy tratando de trazar una matriz con números positivos y negativos. Los números estarán en un intervalo de -1 a 1, pero no en el rango completo. Los números a veces podrían estar en el rango de -0.2 a +0.8 por ejemplo (Ver código a continuación). Quiero usar bwr-colormap (blue -> white – red) de modo que el cero siempre esté codificado en color en blanco. -1 debe estar codificado en color en el azul más oscuro posible y +1 debe estar codificado en color en el rojo más oscuro posible. Aquí viene un ejemplo, donde ambas plots solo son distinguibles por su barra de colores.

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() 

La figura creada por este código se puede ver aquí: figura crear con código publicado

Como se indicó anteriormente, estoy buscando una forma de codificar siempre los valores de los colores con los mismos colores, donde -1: azul oscuro, 0: blanco, +1: rojo oscuro. ¿Es esto de una sola línea y me falta algo o tengo que escribir algo para esto?

EDITAR: Después de cavar un poco más, encontré una respuesta satisfactoria para mí mismo, sin tocar el mapa de colores, sino con entradas opcionales para pcolor (ver más abajo). Aún así, no eliminaré la pregunta, ya que no pude encontrar una respuesta en SO hasta que publiqué esta pregunta e hice clic en las preguntas / respuestas relacionadas. Por otro lado, no me importaría si se eliminara, ya que las respuestas a esta pregunta pueden encontrarse en otra parte si uno está buscando las palabras clave adecuadas.

Aparentemente, encontré la respuesta yo mismo después de cavar un poco más. pcolor ofrece la entrada opcional vmin y vmax . Si los pongo a -1 y 1 respectivamente, resuelve exactamente el problema. La encoding de colores parece ser relativa a vmin y vmax, no al mínimo y máximo de los datos, que se trazan. Así que cambiando el comando de la ttwig (y comentarios) a

 # 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() 

Produce una figura como la necesito: figura correcta

Entonces, al configurar vmin=-1, vmax=1 hace el trabajo, no tengo que cambiar las cosas en el mapa de colores en sí.

También puede normalizar los datos con 0 como punto medio con matplotlib.colors , para mejorar los valores máximos y mínimos del gráfico. Para obtener más información en las normas de mapa de colores , puede ver información más detallada.

 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: class MidpointNormalize(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 

Produce esta figura: introduzca la descripción de la imagen aquí