I am just trying to reproduce this simple example of an animation in Matplotlib but using PyPlot in Julia. I am having difficulties with the definition of the iterator simData()
that is passed to the function funcAnimation
, because it seems that PyPlot doesn't recognize the iterator that I defined in Julia (via a Task) as such.
Here is my approach to define the same function 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
As you can check, this kind of iterator yields in theory the same values than the python simData()
generator of the example (try for example collect(simData())
. However, I got this error when I try to do the animation
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
As I mentioned, I think the problem is that the Julia iterator is not recognized as such by Python. Do you have any idea about how to fix that?
PS: Here is a Jupyter notebook with the full code that I used to do the animation.
In your code, you invoke FuncAnimation()
this way:
ani = anim.FuncAnimation(fig, simPoints, simData, blit = false, interval=10, repeat= true)
In the original code, simData()
was a generator, but in your code it isn't, it returns a generator, so I'd expect your code to invoke it this way:
ani = anim.FuncAnimation(fig, simPoints, simData(), blit = false, interval=10, repeat= true)
Let's finish the problem -- since we can't get Python to recognize the return value of simData()
as an iterator, we'll ignore that feature and have simPoints()
call simData()
to launch the task and then return a function for Python to animate:
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]()
This works for one pass of the bouncing ball across the graph and stops when it hits the right edge (unlike the original Python which repeats).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With