Reputation: 9955
I am having trouble with making FuncAnimation work in this code given below
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
%matplotlib notebook
class Simulator:
def __init__(self, timesteps = 1000, ):
self.simulation_time = np.linspace(0, timesteps, 10*(timesteps)+1)
self._theta = np.arange(0,100, 10*(timesteps)+1)
def init_plot(self):
self._p1, = self.axes.plot(self.simulation_time[0], self._theta[0])
return self.fig,
def update_plot(self, i):
self._p1.set_data(self.simulation_time[:i], self._theta[:i])
return self.fig,
def start_simulation(self):
self.fig, self.axes = plt.subplots()
ani=FuncAnimation(fig=self.fig, func=self.update_plot, init_func=self.init_plot,
interval=5, blit=True)
plt.show()
simHandler = Simulator()
simHandler.start_simulation()
All i see after running this code is a blank screen..
But when i run similar code outside the Class as simple functions, the animation runs, any idea as to how to fix this?
Upvotes: 0
Views: 1067
Reputation: 1273
To keep the code as suggested by Diziet Asahi running, following small adjustment where neccessary:
init_func
from the FuncAnimation
-callstart_simulation
-procedure(and furthermore remove the %matplotlib notebook
statement)
the final result (and working for me) is:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
class Simulator:
def __init__(self, timesteps = 1000, ):
self.simulation_time = np.linspace(0, timesteps, 10*(timesteps)+1)
self._theta = np.sin(self.simulation_time) # I've changed this so one could see the plot being drawn
def update_plot(self, i):
self._p1.set_data(self.simulation_time[:i], self._theta[:i])
self.fig.gca().relim()
self.fig.gca().autoscale_view()
return self._p1,
def start_simulation(self):
self.fig, self.axes = plt.subplots()
self._p1, = self.axes.plot(self.simulation_time[0],self._theta[0])
self.ani = FuncAnimation(fig=self.fig,func=self.update_plot,interval=5, blit=True)
simHandler = Simulator()
simHandler.start_simulation()
Upvotes: 0
Reputation: 40747
There are several problem with your code.
The first and most important is that (as per the documentation):
it is critical to keep a reference to the instance object. The animation is advanced by a timer (typically from the host GUI framework) which the Animation object holds the only reference to. If you do not hold a reference to the Animation object, it (and hence the timers), will be garbage collected which will stop the animation.
That means that your class need to keep/return a reference to the animation, otherwise the animation will stop immediately.
The second issue is that, even if you do that, you need to update the xlims and ylims, as those are not scaled automatically when you use Line2D.set_data()
.
Finally, update_plot()
should return a list of updated artists, not the reference to the figure (although that is only necessary if you are using blit=True
)
Corrected code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
%matplotlib notebook
class Simulator:
def __init__(self, timesteps = 1000, ):
self.simulation_time = np.linspace(0, timesteps, 10*(timesteps)+1)
self._theta = np.sin(self.simulation_time) # I've changed this so one could see the plot being drawn
def init_plot(self):
self._p1, = self.axes.plot(self.simulation_time[0], self._theta[0])
return self.fig,
def update_plot(self, i):
self._p1.set_data(self.simulation_time[:i], self._theta[:i])
self.axes.set_xlim(right=self.simulation_time[i])
return self._p1,
def start_simulation(self):
self.fig, self.axes = plt.subplots()
self.ani = FuncAnimation(fig=self.fig, func=self.update_plot, init_func=self.init_plot,
interval=5, blit=True)
simHandler = Simulator()
simHandler.start_simulation()
Upvotes: 1