编程语言
首页 > 编程语言> > python – 使用mpl_toolkit.basemap给出属性错误的pcolormesh()动画

python – 使用mpl_toolkit.basemap给出属性错误的pcolormesh()动画

作者:互联网

我试图在底图贴图上设置一些密度数据的动画.按照[本SO问题] [1]中的方法,我得到以下错误:

/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'

如果我通过self.quad.set_array(self.z.ravel())将init()中的数据设置为空值,我最终得到两个绘制的地图,没有数据被动画化.

任何人都可以解决我做错的任何亮点都将不胜感激.谢谢!

示例代码:

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)

解决方法:

看起来set_data方法应该需要一个ndarray(不知道为什么我所遵循的例子工作正常).

所以在init()函数中,你应该使用quad.set_array(np.array([]))而不是quad.set_array([]).

其他需要注意的问题:

>如前所述,您还需要在FuncAnimation()调用中设置blit = False.
>当我将quad artist属性设置为True时,我也遇到了问题.保留它(即quad.set_animated(False),这是默认值).
>如果你没有在你的第一个pcolormesh()调用中通过norm指定边界,它将根据你传递的数据(在我的情况下为null)设置它们,这导致我得到空白动画.根据您在初始调用中稍后设置的数据进行设置可以防止出现此问题.
> pcolormesh()将边界位置带到数据字段,数据字段的y和x维度应为1.如果数据数组等于(或大于)位置数据的维度,则pcolormesh()将省略此边界要求之外的任何数据.我认为我的数据只会被一个网格单元偏移,但在我通过正确的边界位置之前,一切都很糟糕.查看我的另一个问题来计算这些HERE.
>较旧版本的matplotlib没有非常好的错误报告.我建议升级到最新版本,如果这是一个选项.

一些随机的故障排除:

在更新matplotlib和底图并尝试在我现有的绘图例程中实现它之后,我收到以下错误:

ValueError: All values in the dash list must be positive

我首先想到它与我的pcolormesh()对象有关,但是我花了太长时间才发现它是由于我之前在m.drawmeridians()调用dashes = [1,0为了一个坚实的子午线.在新版本的matplotlib the handling of dashes was changed中给出了这个错误.为dash属性设置实线的新首选方法是破折号=(无,无),我不喜欢.

结果动画:

以上输出的代码示例:

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)

标签:matplotlib-basemap,python,animation
来源: https://codeday.me/bug/20190830/1771759.html