【问题标题】:Matplotlib Animation for custom artist classes自定义艺术家类的 Matplotlib 动画
【发布时间】:2015-07-20 06:20:50
【问题描述】:

目标

嗨, 我正在尝试为具有多个子图的复杂图形制作动画,并已开始使用 artist animationfunction animation 方法进行测试。

目前,我的目标是让左侧的子图显示一条移动的彩色线(不是问题),而右侧的子图显示脑部扫描的更新表示(问题)。静态的,这看起来像这样。

# Imports
import nilearn as nil
from nilearn import plotting as nlp
from matplotlib import pyplot as plt

window = np.arange(0,200-50)

fig = plt.figure(figsize=(7,4))
ax = fig.add_subplot(121)
ax.set_xlim([0, 200])
a = ax.axvspan(window[0], window[0]+50, color='blue', alpha=0.5)

ay = fig.add_subplot(122)
b = nlp.plot_stat_map(nil.image.index_img(s_img, 0), axes=ay, colorbar=False, display_mode='x', cut_coords=(0,))

问题

如您所见,我使用nilearn 绘制大脑图像。出于某种原因,plot_stat_map 中的 nilearn 对象没有 set_visible 属性,这与 axvspan 中的 matplotlib 对象不同。

所以当我尝试像这样的简单动画时:

fig = plt.figure(figsize=(7,4))
ax = fig.add_subplot(121)
ax.set_xlim([0, 200])
ay = fig.add_subplot(122)
iml = list()

for i in np.arange(50):
    a = ax.axvspan(window[i], window[i]+50, color='blue', alpha=0.5)
    b = nlp.plot_stat_map(nil.image.index_img(s_img, i), axes=ay)
    iml.append((a,b))

ani = animation.ArtistAniTruemation(fig, iml, interval=50, blit=False,
    repeat_delay=1000)

它崩溃并出现以下错误:

/home/surchs/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/matplotlib/animation.pyc in _init_draw(self)
    974         for f in self.new_frame_seq():
    975             for artist in f:
--> 976                 artist.set_visible(False)
    977                 # Assemble a list of unique axes that need flushing
    978                 if artist.axes not in axes:

AttributeError: 'OrthoSlicer' object has no attribute 'set_visible'

有道理,nilearn 可能不符合 matplotlibs 的期望。所以我尝试了这样的函数动画方法:

def show_things(i, window, ax, ay):
    ax.axvspan(window[i], window[i]+50, color='blue', alpha=0.5)
    nlp.plot_stat_map(nil.image.index_img(s_img, i), axes=ay, colorbar=False, display_mode='x', cut_coords=(0,))

fig = plt.figure(figsize=(7,4))
ax = fig.add_subplot(121)
ax.set_xlim([0, 200])
ay = fig.add_subplot(122)

ani = animation.FuncAnimation(fig, show_things, interval=10, blit=False, fargs=(window, ax, ay))

虽然我不确定我是否正确使用了这些东西,但这给了我右侧的动画大脑图。然而,左边的情节现在没有更新,只是画了出来。因此,我得到了一个扩展的颜色表面,而不是滑动条。像这样的:

问题

我该怎么做

  • 在使用函数动画方法时,要在每次迭代时更新(而不是覆盖)左侧的图吗? 我已经尝试过 matplotlib 中的 ax.cla() 函数,但由于这也会清除所有轴属性(如 xlim),这对我来说不是解决方案。有替代方案吗?
  • 即使自定义绘图类明显缺少关键属性,也可以使用艺术家动画方法获取右侧的绘图。

另外,我不确定我是否正确地完成了整个实施部分,因此也非常感谢您提供这方面的任何建议。

【问题讨论】:

    标签: python animation matplotlib


    【解决方案1】:

    我怀疑您可能需要使用 ax.cla() 清除绘图之间的 axvspan 轴以获得正确的左侧绘图(注意,可能也应该清除右侧绘图)。为了解决缺少属性的问题,我建议从nlp.plot_stat_map 的返回句柄中提取数据并使用matplotlib pcolormesh(或imshow)进行绘图。另一种可能性是创建一个子类并自己添加此方法。如果应该存在,也可能值得向nilearn 提交错误/功能请求。

    顺便说一句,如果你只追求快速简单的情节,你可以使用交互式情节来制作穷人版的动画,作为一个最小的例子,

    import matplotlib.pyplot as plt
    import numpy as np
    import time
    
    #Interactive plot
    plt.ion()
    
    #Setup figures
    fig = plt.figure(figsize=(7,4))
    ax = fig.add_subplot(121)
    ay = fig.add_subplot(122)
    plt.show()
    
    
    x = np.linspace(0,2*np.pi)
    for i in range(10000):
        print(i)
        #Clear axes
        ax.cla(); ay.cla()
    
        #Update data
        yx = np.sin(x+i*0.1)
        yy = np.sin(2.*(x+i*0.1))
    
        #Replot
        ax.plot(x,yx)
        ay.plot(x,yy)
    
        #Pause to allow redraw
        plt.draw()
        plt.pause(0.01)
    

    【讨论】:

    • 谢谢。我应该澄清 ax.cla 是不需要的,因为它还会在每次重绘时重置轴属性(例如 xlim),从而弄乱绘图。我相信我的问题可以改写为:如何在不丢失轴属性的情况下清除情节?
    • 你不能在动画循环中简单地重新设置轴限制吗?我认为您不能在不清除所有其他属性的情况下清除轴。如果轴必须保持不变,则需要更新/清除显示的数据对象。绘图句柄(ab)应该有 set_data 方法,可用于在不接触轴的情况下更改绘图。例如ax.patches.remove(a) 将删除当前的axvspan 实例。其他原始艺术家对象也会有类似的移除。
    猜你喜欢
    • 2012-07-10
    • 1970-01-01
    • 2017-05-24
    • 1970-01-01
    • 2018-05-05
    • 2017-02-19
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    相关资源
    最近更新 更多