【问题标题】:Implementing an iterator in Julia for an animation with PyPlot在 Julia 中使用 PyPlot 为动画实现迭代器
【发布时间】:2016-05-10 14:13:43
【问题描述】:

我只是想在 Matplotlib 中重现这个简单的 example 动画,但在 Julia 中使用 PyPlot。我在定义传递给函数 funcAnimation 的迭代器 simData() 时遇到困难,因为 PyPlot 似乎无法识别我在 Julia 中定义的迭代器(通过 Task)。

这是我定义相同函数simData()的方法:

function simData()

    t_max = 10.0
    dt = 0.05
    x = 0.0
    t = 0.0

    function it()
        while t < t_max
            x = sin(pi*t)
            t = t+dt
            produce(x,t)
        end
    end
    Task(it)
end

如您所见,这种迭代器理论上产生的值与示例中的 python simData() 生成器相同(尝试例如 collect(simData())。但是,当我尝试制作动画时出现此错误

LoadError: PyError (:PyObject_Call) <type 'exceptions.TypeError'>
TypeError('PyCall.jlwrap object is not an iterator',)
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/animation.py", line 1067, in __init__
    TimedAnimation.__init__(self, fig, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/animation.py", line 913, in __init__
    *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/animation.py", line 591, in __init__
    self._init_draw()
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/animation.py", line 1092, in _init_draw
    self._draw_frame(next(self.new_frame_seq()))

while loading In[5], in expression starting on line 42

 in pyerr_check at /home/diegotap/.julia/v0.4/PyCall/src/exception.jl:56
 [inlined code] from /home/diegotap/.julia/v0.4/PyCall/src/exception.jl:81
 in pycall at /home/diegotap/.julia/v0.4/PyCall/src/PyCall.jl:402
 in call at /home/diegotap/.julia/v0.4/PyCall/src/PyCall.jl:429

正如我所提到的,我认为问题在于 Python 无法识别 Julia 迭代器。你知道如何解决这个问题吗?

PS:Here 是一个 Jupyter notebook,里面有我用来做动画的完整代码。

【问题讨论】:

    标签: python animation matplotlib julia


    【解决方案1】:

    在您的代码中,您可以这样调用FuncAnimation()

    ani = anim.FuncAnimation(fig, simPoints, simData, blit = false, interval=10, repeat= true)
    

    在原始代码中,simData() 是一个生成器,但在您的代码中它不是,它返回一个生成器,所以我希望您的代码以这种方式调用它:

    ani = anim.FuncAnimation(fig, simPoints, simData(), blit = false, interval=10, repeat= true)
    

    让我们完成这个问题——因为我们无法让 Python 将 simData() 的返回值识别为迭代器,我们将忽略该功能并让 simPoints() 调用 simData() 来启动任务,然后返回一个函数让 Python 动画化:

    using PyCall
    using PyPlot
    pygui(true)
    
    @pyimport matplotlib.animation as animation
    
    function simData()
        t_max = 10.0
        dt = 0.05
        x = 0.0
        t = -dt
    
        function it()
            while t < t_max
                x = sin(pi * t)
                t = t + dt
                produce(x, t)
            end
        end
    
        Task(it)
    end
    
    function simPoints()
        task = simData()
    
        function points(frame_number)
            x, t = consume(task)
            line[:set_data](t, x)
            return(line, "")
        end
    
        points
    end
    
    figure = plt[:figure]()
    axis = figure[:add_subplot](111)
    line = axis[:plot]([], [], "bo", ms = 10)[1]
    axis[:set_ylim](-1, 1)
    axis[:set_xlim](0, 10)
    
    ani = animation.FuncAnimation(figure, simPoints(), blit=false, interval=10, frames=200, repeat=false)
    
    plt[:show]()
    

    这适用于弹跳球在图形上的一次传球,并在它击中右边缘时停止(与重复的原始 Python 不同)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-22
      • 2016-02-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多