Animación de pcolormesh () con mpl_toolkit.basemap que da error de atributo

Estoy tratando de animar algunos datos de densidad en un basemap mapa basemap . Siguiendo un enfoque como se hizo en [esta pregunta SO] [1], obtengo el siguiente error:

 /usr/local/lib/python2.7/dist-packages/matplotlib/collections.pyc in update_scalarmappable(self) 627 if self._A is None: 628 return --> 629 if self._A.ndim > 1: 630 raise ValueError('Collections can only map rank 1 arrays') 631 if not self.check_update("array"): AttributeError: 'list' object has no attribute 'ndim' 

Si, por el contrario, configuro los datos en init() con valores nulos de self.quad.set_array(self.z.ravel()) , self.quad.set_array(self.z.ravel()) con dos mapas trazados sin datos animados.

Cualquier luz que alguien pueda arrojar sobre lo que estoy haciendo mal sería muy apreciada. ¡Gracias!

código de ejemplo :

 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 self.ydim, self.xdim = lons.shape self.z = np.zeros((self.ydim-1,self.xdim-1)) x, y = self.m(lons, lats) self.quad = ax.pcolormesh(x, y, self.z, cmap=plt.cm.Reds) def init(self): print 'update init' self.quad.set_array([]) return self.quad def __call__(self,i): data = np.zeros((self.ydim-1,self.xdim-1)) for i in range(self.ydim-1): for j in range(self.xdim-1): data[i,j]=random.random()+4 self.quad.set_array(data.ravel()) return self.quad fig = plt.figure() ax = fig.add_axes([0.1,0.1,0.8,0.8]) 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) plt.show() 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 lons = np.linspace(-5.,25., num = 25)[:50] lats = np.linspace(56., 71., num = 25)[:50] lons,lats = np.meshgrid(lons,lats) plot_pcolor(lons,lats) 

Parece que el método set_data debería requerir un ndarray (no estoy seguro de por qué el ejemplo que había seguido funcionaba correctamente).

Así que en la función init() , debe usar quad.set_array(np.array([])) lugar de quad.set_array([]) .

Otros problemas a tener en cuenta :

  • Como se mencionó anteriormente, también desea establecer blit=False en su llamada a FuncAnimation() .

  • También estaba experimentando problemas cuando establecí el atributo de artist cuádruple animated en True . Deje que sea (es decir, quad.set_animated(False) , que es el valor predeterminado de todos modos).

  • Si no especifica los límites a través de la norm en su primera llamada a pcolormesh() , los establecerá de acuerdo con los datos que pase (en mi caso, nulo), lo que provocó que las animaciones queden en blanco. Configurarlos de acuerdo con los datos que animará más adelante en la llamada inicial, evitó este problema en mi caso.

  • pcolormesh() toma las posiciones de límite en el campo de datos, que debería ser +1 en la dimensión y y x de la matriz de datos. Si la matriz de datos es igual (o mayor que) las dimensiones de los datos de posición, pcolormesh() omitirá cualquier dato fuera de este requisito de límite. Pensé que mis datos solo aparecerían compensados ​​por una celda de la cuadrícula, pero todo estaba loco antes de que pasara las posiciones de los límites correctos. Vea otra pregunta mía para calcular esto AQUÍ .

  • Las versiones anteriores de matplotlib no tienen muy buenos informes de errores. Recomiendo actualizar a la última versión si esa es una opción para usted.

Algunos al azar de resolución de problemas :

Después de actualizar matplotlib y el basemap e intentar implementar esto en mi rutina de trazado existente, recibí el siguiente error:

 ValueError: All values in the dash list must be positive 

Primero pensé que tenía que ver con mis objetos pcolormesh() , pero pcolormesh() demasiado en descubrir que se debía a mi configuración anterior del atributo de dash en mi llamada m.drawmeridians() a dashes=[1,0] para un meridiano sólido. En la nueva versión de matplotlib el manejo de los guiones se cambió para dar este error. El nuevo método preferido para establecer una línea continua para el atributo de dash es dashes=(None,None) , que no me gusta.

Animación resultante :

animación pcolormesh

Ejemplo de código para la salida anterior :

 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)