It looks like the set_data
method should require an ndarray (not sure why the example I had followed was working correctly).
So in the init()
function, you should use quad.set_array(np.array([]))
rather than quad.set_array([])
.
Other problems to be aware of:
As mentioned before, you also want set
blit=False
in yourFuncAnimation()
call.I was also experiencing problems when I set the quad
artist
attributeanimated
toTrue
. Leave that be (i.e.quad.set_animated(False)
, which is the default anyway).If you do not specify the bounds via
norm
in your firstpcolormesh()
call, it will set them according to the data you pass (in my case null), which resulting in my getting blank animations. Setting them according to the data you will animate later in the initial call prevented this problem in my case.pcolormesh()
takes the bounding positions to the data field, which should be +1 in the y and x dimension of the data array. If the data array is equal (or greater than) the dimensions of the position data,pcolormesh()
will omit any data outside of this boundary requirement. I thought that my data would just appear offset by one grid cell, but everything was all whacky before I passed the correct boundary positions. See another question of mine for calculating these HERE.Older versions of
matplotlib
do not have very good error reporting. I recommend upgrading to the latest version if that is an option for you.
Some random trouble-shooting:
After updating matplotlib
and basemap
and attempting to implement this in my existing plotting routine, I received the following error:
ValueError: All values in the dash list must be positive
I first thought it had to do with my pcolormesh()
objects, but it took me way too long to discover that it was due to my previous setting of the dash
attribute in my m.drawmeridians()
call to dashes=[1,0]
for a solid meridian. In the new version of matplotlib
the handling of dashes was changed to give this error. The new prefered method for setting a solid line for the dash
attribute is dashes=(None,None)
, which I don't like.
Resulting animation:
Code example for above output:
def plot_pcolor(lons,lats):
class UpdateQuad(object):
def __init__(self,ax, map_object, lons, lats):
self.ax = ax
self.m = map_object
self.lons = lons
self.lats = lats
vmin = 0
vmax = 1
self.ydim, self.xdim = lons.shape
self.z = np.zeros((self.ydim-1,self.xdim-1))
levels = MaxNLocator(nbins=15).tick_values(vmin,vmax)
cmap = plt.cm.cool
norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)
x, y = self.m(lons, lats)
self.quad = self.ax.pcolormesh(x, y, self.z, alpha=0.9,
norm=norm, cmap=cmap,
vmin=vmin, vmax=vmax)
def init(self):
print 'update init'
self.quad.set_array(np.asarray([]))
return self.quad
def __call__(self,i):
for i in range(self.ydim-1):
for j in range(self.xdim-1):
self.z[i,j]=random.random()
self.quad.set_array(self.z.ravel())
return self.quad
fig, ax = plt.subplots()
m = Basemap(width=2000000,height=2000000,
resolution='l', projection='laea',\
lat_ts=10.,\
lat_0=64.,lon_0=10., ax=ax)
m.fillcontinents()
ud = UpdateQuad(ax, m, lons, lats)
anim = animation.FuncAnimation(fig, ud, init_func=ud.init,
frames=20, blit=False)
fig.tight_layout()
plt.show()
return ud.quad
if __name__ == '__main__':
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.basemap import Basemap
import numpy as np
import random
from matplotlib.colors import BoundaryNorm
from matplotlib.ticker import MaxNLocator
lons = np.linspace(-5.,25., num = 25)[:50]
lats = np.linspace(56., 71., num = 25)[:50]
lons,lats = np.meshgrid(lons,lats)
quad = plot_pcolor(lons,lats)