¿Cómo visualizar datos 2D escalares con Matplotlib?

Así que tengo una malla de malla (matrices X e Y) junto con datos escalares (matriz Z), y necesito visualizar esto. Preferiblemente alguna imagen 2D con colores en los puntos que muestran el valor de Z allí. He investigado un poco pero no he encontrado nada que haga exactamente lo que quiero.

pyplot.imshow (Z) tiene un buen aspecto, pero no toma mis matrices X e Y, por lo que los ejes están equivocados y no puede manejar puntos espaciados no linealmente dados por X e Y.

pyplot.pcolor (X, Y, Z) hace cuadrados de colores con colores correspondientes a los datos en una de sus esquinas, por lo que tergiversa los datos (debe mostrar los datos en su centro o algo así). Además, ignora dos de los bordes de la matriz de datos.

Estoy bastante seguro de que debe existir una mejor manera en algún lugar de Matplotlib, pero la documentación hace que sea difícil obtener una visión general. Entonces estoy preguntando si alguien más sabe de una mejor manera. Bonificación si me permite actualizar la matriz Z para hacer una animación.

Esto se ve bien, pero es ineficiente:

from pylab import * origin = 'lower' delta = 0.025 x = y = arange(-3.0, 3.01, delta) X, Y = meshgrid(x, y) Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1) Z = 10 * (Z1 - Z2) nr, nc = Z.shape CS = contourf( X, Y, Z, levels = linspace(Z.min(), Z.max(), len(x)), ls = '-', cmap=cm.bone, origin=origin) CS1 = contour( CS, levels = linspace(Z.min(), Z.max(), len(x)), ls = '-', cmap=cm.bone, origin=origin) show() 

Si fuera yo, volvería a interpolar (usando scipy.interpolate) los datos a una cuadrícula regular y utilizaría imshow (), estableciendo las extensiones para arreglar los ejes.

buen contorno

Editar (por comentario):

Animar una gráfica de contorno se puede lograr de esta manera, pero, como dije, lo anterior es ineficiente, simplemente el abuso de la función de la gráfica de contorno. La forma más eficiente de hacer lo que quiere es emplear SciPy. ¿Tienes eso instalado?

 import matplotlib matplotlib.use('TkAgg') # do this before importing pylab import time import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) def animate(): origin = 'lower' delta = 0.025 x = y = arange(-3.0, 3.01, delta) X, Y = meshgrid(x, y) Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1) Z = 10 * (Z1 - Z2) CS1 = ax.contourf( X, Y, Z, levels = linspace(Z.min(), Z.max(), 10), cmap=cm.bone, origin=origin) for i in range(10): tempCS1 = contourf( X, Y, Z, levels = linspace(Z.min(), Z.max(), 10), cmap=cm.bone, origin=origin) del tempCS1 fig.canvas.draw() time.sleep(0.1) Z += x/10 win = fig.canvas.manager.window fig.canvas.manager.window.after(100, animate) plt.show() 

Si su meshgrid tiene un espaciado uniforme, podría continuar usando pcolor , pero simplemente cambie X e Y con el fin de centrar los datos en los valores particulares en lugar de en las esquinas.

También puede usar un diagtwig de dispersión para colocar explícitamente puntos de algún tamaño en los puntos X e Y exactos y luego establecer el color en Z:

 x = numpy.arange(10) y = numpy.arange(10) X,Y = numpy.meshgrid(x,y) Z = numpy.arange(100).reshape((10,10)) scatter(X,Y,c=Z,marker='s',s=1500) #I picked a marker size that basically overlapped the symbols at the edges axis('equal') 

o:

 pcolor(X+0.5,Y+0.5,Z) axis('equal') 

o como Paul sugirió, usando una de las funciones de contorno

En caso de que alguien se encuentre con este artículo buscando lo que estaba buscando, tomé el ejemplo anterior y lo modifiqué para usar imshow con una stack de cuadros de entrada, en lugar de generar y usar contornos sobre la marcha. Comenzando con una matriz 3D de imágenes de forma (nBins, nBins, nBins), llamadas frames .

 def animate_frames(frames): nBins = frames.shape[0] frame = frames[0] tempCS1 = plt.imshow(frame, cmap=plt.cm.gray) for k in range(nBins): frame = frames[k] tempCS1 = plt.imshow(frame, cmap=plt.cm.gray) del tempCS1 fig.canvas.draw() #time.sleep(1e-2) #unnecessary, but useful fig.clf() fig = plt.figure() ax = fig.add_subplot(111) win = fig.canvas.manager.window fig.canvas.manager.window.after(100, animate_frames, frames) 

También encontré una forma mucho más sencilla de hacer todo este proceso, aunque menos robusta:

 fig = plt.figure() for k in range(nBins): plt.clf() plt.imshow(frames[k],cmap=plt.cm.gray) fig.canvas.draw() time.sleep(1e-6) #unnecessary, but useful 

Tenga en cuenta que ambos parecen funcionar solo con ipython --pylab=tk , aka backend = TkAgg

Gracias por la ayuda con todo.

La siguiente función crea cajas de la mitad del tamaño en el límite (como se muestra en la imagen adjunta).

 import matplotlib.pyplot as plt import numpy as np from scipy.ndimage.filters import convolve def pcolor_all(X, Y, C, **kwargs): X = np.concatenate([X[0:1,:], X], axis=0) X = np.concatenate([X[:,0:1], X], axis=1) Y = np.concatenate([Y[0:1,:], Y], axis=0) Y = np.concatenate([Y[:,0:1], Y], axis=1) X = convolve(X, [[1,1],[1,1]])/4 Y = convolve(Y, [[1,1],[1,1]])/4 plt.pcolor(X, Y, C, **kwargs) X, Y = np.meshgrid( [-1,-0.5,0,0.5,1], [-2,-1,0,1,2]) C = X**2-Y**2 plt.figure(figsize=(4,4)) pcolor_all(X, Y, C, cmap='gray') plt.savefig('plot.png') 

plot.png