在Julia中使用PyPlot实现一个迭代器

dap*_*ias 22 python animation matplotlib julia

我只是想 在Matplotlib中重现这个简单的动画示例,但在Julia中使用PyPlot.我对simData()传递给函数的迭代器的定义有困难funcAnimation,因为似乎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
Run Code Online (Sandbox Code Playgroud)

正如您可以检查的那样,这种迭代器在理论上产生的值simData()与示例中的python 生成器相同(例如尝试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
Run Code Online (Sandbox Code Playgroud)

正如我所提到的,我认为问题在于Python不能识别Julia迭代器.你对如何解决这个问题有任何想法吗?

PS:是一个Jupyter笔记本,里面有我用来制作动画的完整代码.

cdl*_*ane 8

在您的代码中,您以这种方式调用FuncAnimation:

ani = anim.FuncAnimation(fig, simPoints, simData, blit = false, interval=10, repeat= true)
Run Code Online (Sandbox Code Playgroud)

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

ani = anim.FuncAnimation(fig, simPoints, simData(), blit = false, interval=10, repeat= true)
Run Code Online (Sandbox Code Playgroud)

让我们完成这个问题 - 因为我们无法让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]()
Run Code Online (Sandbox Code Playgroud)

这适用于跳过图形的弹跳球的一次通过,并且当它击中右边缘时停止(与重复的原始Python不同).