'Line2D' object is not iterable 错误 when blit=true matplotlib FuncAnimation

'Line2D' object is not iterable error when blit=true matplotlib FuncAnimation

我正在尝试使用 FuncAnimation 在 matplotlib 中为一些分形制作动画。 当我将 blit 设置为 False 时,我没有收到任何错误:代码 运行 很好,并为我生成了一个不错的动画。但是,当我将 blit 设置为 True 时,它​​会给我 TypeError: 'Line2D' object is not iterable。有谁知道为什么会发生这种情况以及我该如何解决?

我想利用 blitting 的优势,因为我计划为一大群分形制作动画,而只取其中的一小部分(64 种不同的分形)已经需要很长的计算时间。我有一种快速的方法来生成一个矩阵,其中的列包含不同的分形,所以我知道计算时间花在了试图为一堆图设置动画而不用 blitting 上。

在我的示例中,我只是对生成分形的迭代进行动画处理。这是说明我遇到的错误的一种简短而快速的方法,而不是我实际尝试制作动画的方法,否则我不会关心 blitting。

如果您安装了 ffmpeg,这里是一个应该 运行 在 jupyter notebook 中的最小示例:

import numpy as np
import scipy as sp
import scipy.linalg as la
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib import animation, rc
from IPython.display import HTML
%matplotlib inline
plt.rcParams['figure.figsize'] = [8,8]
plt.rcParams['animation.ffmpeg_path'] = "C:\Program Files\ffmpeg\bin\ffmpeg.exe" #<- CHANGE TO YOUR PATH TO FFMPEG or delete this line if the notebook knows where to find ffmpeg.
class IFS:
    """Represent an iterated function system used to generate a fractal."""
    def __init__(self,start,f1,f2,reversef2=False):
        self.points = start
        self.f1 = f1
        self.f2 = f2
        self.reversef2 = reversef2

    def iterate(self,iterations=1):
        """Perform iterations using the functions"""
        for i in range(0,iterations):
            if self.reversef2: #This is needed for the dragon curve
                self.points = np.append(self.f1(self.points),self.f2(self.points)[::-1])
            else: #However, you do not want to append in reverse when constructing the levyC curve
                self.points = np.append(self.f1(self.points),self.f2(self.points))

    def get_points(self):
        return self.points

def dragon_ifs():
    """Return a dragon fractal generating IFS"""
    def f1(z):
        return (0.5+0.5j)*z
    def f2(z):
        return 1 - (0.5-0.5j)*z
    return IFS(np.array([0,1]),f1,f2,reversef2=True)

#Animation
class UpdateFractal:
    """A class for animating an IFS by slowly iterating it"""
    def __init__(self,ax,ifs):
        self.ifs = ifs
        self.line, = ax.plot([], [], 'k-',lw=2)
        self.ax = ax
        #set parameters
        self.ax.axis([-1,2,-1,2])
    def get_plot_points(self):
        """Get plottable X and Y values from the IFS points"""
        points = self.ifs.get_points()
        X = points.real
        Y = points.imag
        return X,Y
    def init(self):
        X,Y = self.get_plot_points()
        self.line.set_data(X,Y)
        return self.line
    def __call__(self,i):
        self.ifs.iterate()
        X,Y = self.get_plot_points()
        self.line.set_data(X,Y)
        return self.line

fig, ax = plt.subplots()
dragon = dragon_ifs()
uf = UpdateFractal(ax,dragon)
anim = FuncAnimation(fig, uf, frames=np.arange(15), init_func=uf.init,
                     interval=200, blit=True)
#Show animation
HTML(anim.to_html5_video())

旁注:我也看到了这个未回答的问题:FuncAnimation not iterable,我认为他们可能面临类似的问题。我注意到他们将 blit 设置为 True,如果我有足够的声誉,我会评论并询问他们是否将 blit 设置为 False "fixes" 他们的问题。

正如错误提示的那样,动画函数的 return 需要是可迭代的。

将行 return self.line 替换为

return self.line, 

(注意逗号)