2016-02-01 21 views
19

Sto solo cercando di riprodurre questo semplice example di un'animazione in Matplotlib ma utilizzando PyPlot in Julia. Ho difficoltà con la definizione dell'iteratore simData() passato alla funzione funcAnimation, perché sembra che PyPlot non riconosca l'iteratore che ho definito in Julia (tramite un Task) come tale.Implementazione di un iteratore in Julia per un'animazione con PyPlot

Ecco il mio approccio per definire la stessa funzione 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 

come si può verificare, questo tipo di rendimenti iteratori in teoria gli stessi valori che il generatore di pitone simData() dell'esempio (provate ad esempio collect(simData()) . Tuttavia, ho ottenuto questo errore quando provo a fare l'animazione

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 

come ho detto, penso che il problema è che l'iteratore Julia non è riconosciuta come tale da Python. avete qualche idea ab come risolverlo?

PS: Here è un notebook Jupyter con il codice completo utilizzato per l'animazione.

risposta

7

Nel codice, si richiama FuncAnimation questo modo:

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

Nel codice originale, simData era un generatore, ma nel codice non lo è, restituisce un generatore, quindi mi aspetto il codice per richiamare in questo modo:

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

Finiamo il problema - dal momento che non possiamo ottenere Python a riconoscere il valore di ritorno di simData() come interator, ignoreremo questa caratteristica e hanno SimPoints() chiama simData() per avviare l'attività e quindi restituisce una funzione per Python da animare:

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]() 

questo funziona per un solo passaggio della palla rimbalza attraverso il grafico e si ferma quando colpisce il bordo destro (a differenza del pitone originale che ripete).