Animation pcolormesh () with mpl_toolkit.basemap indicating attribute error

I am trying to animate some density data on a basemap map. Following the approach as it was done in [this SO question] [1], I get the following 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' 

If I instead put the data in init() with zero values โ€‹โ€‹on self.quad.set_array(self.z.ravel()) , I get two graphics cards without animating the data.

Any light that anyone can shed on what I am doing wrong will be greatly appreciated. Thanks!

code example :

 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) 
+3
source share
1 answer

It seems that the set_data method should require ndarray (I don't know why the example I used worked correctly).

So, in the init() function, you should use quad.set_array(np.array([])) , not quad.set_array([]) .

Other issues to know :

  • As mentioned earlier, you also want to set blit=False in your FuncAnimation() call.

  • I also had problems when I set the quad artist animated attribute to True . Leave this (i.e. quad.set_animated(False) , which is the default anyway).

  • If you do not specify boundaries through norm in your first call to pcolormesh() , it will set them according to the data you are passing (in my case null), which results in an empty animation. Setting them in accordance with the data that will be displayed later on the first call prevented this problem in my case.

  • pcolormesh() takes boundary positions in the data field, which should be +1 in the sizes y and x of the data array. If the data array is equal to (or greater than) the size of the location data, pcolormesh() will skip any data outside this boundary requirement. I thought that my data would just be offset by one grid cell, but everything was terrible before I went through the correct boundary positions. Another my question for calculating these is HERE .

  • Older versions of matplotlib do not have very good error reporting. I recommend updating to the latest version if this is an option for you.

Some random errors :

After updating matplotlib and basemap and trying to implement this in my existing basemap program, I got the following error:

 ValueError: All values in the dash list must be positive 

At first I thought it was due to my pcolormesh() objects, but it took me too long to find that it was due to my previous setting of the dash attribute in my call to m.drawmeridians() on dashes=[1,0] for solid meridian. In the new version of matplotlib , dash processing has been changed to get this error. The new preferred method for setting a solid line for the dash attribute is dashes=(None,None) , which I don't like.

Resulting animation :

pcolormesh animation

Sample code for the output above :

 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) 
+4
source

Source: https://habr.com/ru/post/953811/


All Articles