【问题标题】:Animation of pcolormesh() with mpl_toolkit.basemap giving attribute errormpl_toolkit.basemap 的 pcolormesh() 动画给出属性错误
【发布时间】:2014-03-27 22:57:01
【问题描述】:

我正在尝试为basemap 地图上的一些密度数据设置动画。按照 [this SO question][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'

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

任何人都可以阐明我做错了什么,我们将不胜感激。谢谢!

示例代码

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)

【问题讨论】:

    标签: python animation matplotlib-basemap


    【解决方案1】:

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

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

    其他需要注意的问题

    • 如前所述,您还希望在您的FuncAnimation() 调用中设置blit=False

    • 当我将四元组 artist 属性 animated 设置为 True 时,我也遇到了问题。保持不变(即quad.set_animated(False),无论如何都是默认值)。

    • 1234563根据您稍后将在初始调用中设置动画的数据设置它们在我的情况下防止了这个问题。
    • pcolormesh() 获取数据字段的边界位置,在数据数组的 y 和 x 维度上应该是 +1。如果数据数组等于(或大于)位置数据的维度,pcolormesh() 将忽略此边界要求之外的任何数据。我以为我的数据只会出现一个网格单元格的偏移,但在我通过正确的边界位置之前,一切都变得异常糟糕。请参阅我的另一个问题以计算这些HERE

    • matplotlib 的旧版本没有很好的错误报告。如果您愿意,我建议您升级到最新版本。

    一些随机故障排除

    在更新 matplotlibbasemap 并尝试在我现有的绘图例程中实现此功能后,我收到以下错误:

    ValueError: All values in the dash list must be positive
    

    我最初认为这与我的pcolormesh() 对象有关,但我花了很长时间才发现这是由于我之前在m.drawmeridians() 调用dashes=[1,0] 中设置了dash 属性为实心经线。在新版的matplotlibthe handling of dashes was changed给出这个错误。为dash 属性设置实线的新首选方法是dashes=(None,None),我不喜欢。

    生成的动画

    以上输出的代码示例

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 2021-02-11
      • 2013-05-24
      相关资源
      最近更新 更多