Подтвердить что ты не робот

Реализация итератора в Julia для анимации с PyPlot

Я просто пытаюсь воспроизвести этот простой пример анимации в Matplotlib, но используя PyPlot в Julia. У меня возникают трудности с определением итератора 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

Как вы можете проверить, этот тип итератора теоретически дает те же значения, что и генератор 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

Как я уже говорил, проблема в том, что итератор Julia не распознается Python как таковой. У вас есть какое-то представление о том, как это исправить?

PS: Здесь - ноутбук Jupyter с полным кодом, который я использовал для создания анимации.

4b9b3361

Ответ 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, который повторяется).