当blit = true matplotlib FuncAnimation时,'Line2D'对象不是可迭代错误

时间:2018-01-11 05:37:58

标签: python animation matplotlib jupyter-notebook fractals

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

我想利用blitting,因为我计划为一大片分形图设置动画,并且只拍摄一小部分(64种不同的分形)已经占用了明显的计算时间。我有一个快速的方法来生成一个包含不同分形的列的矩阵,所以我知道计算时间花在尝试动画一堆没有blitting的图上。

在我的例子中,我只是动画生成分形的迭代。这是一种简短而快速的方式来说明我得到的错误,而不是我实际上想要制作的动画,因为否则我不会关心blitting。

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

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 to False“修复”他们的问题。

1 个答案:

答案 0 :(得分:2)

正如错误所示,动画函数的返回需要是可迭代的。

将行return self.line替换为

return self.line, 

请注意逗号