So i have a meshgrid (matrices X and Y) together with scalar data (matrix Z), and i need to visualize this. Preferably some 2D image with colors at the points showing the value of Z there. I've done some research but haven't found anything which does exactly what i want.
pyplot.imshow(Z) has a good look, but it doesn't take my X and Y matrices, so the axes are wrong and it is unable to handle non-linearly spaced points given by X and Y.
pyplot.pcolor(X,Y,Z) makes colored squares with colors corresponding to the data at one of its corners, so it kind of misrepresents the data (it should show the data in its center or something). In addition it ignores two of the edges from the data matrix.
I pretty sure there must exist some better way somewhere in Matplotlib, but the documentation makes it hard to get an overview. So i'm asking if someone else knows of a better way. Bonus if it allows me to refresh the matrix Z to make an animation.
This looks nice, but it's inefficient:
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()
It it were me, I'd re-interpolate (using scipy.interpolate) the data to a regular grid and use imshow(), setting the extents to fix the axes.
Edit (per comment):
Animating a contour plot can be accomplished like this, but, like I said, the above is inefficient just plain abuse of the contour plot function. The most efficient way to do what you want is to employ SciPy. Do you have that installed?
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()
If your meshgrid has uniform spacing, you could continue to use
pcolor, but just shift X and Y for the purposes of centering the data at the particular values rather than at the corners.
You could also use a scatter plot to explicitly place points of some size at the exact X and Y points and then set the color to 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')
or as Paul suggested, using one of the contour functions