I\'m learning OOP in python and so for a bit of fun I bashed out a GameOfLife simulator this morning. When it starts up it runs at about 20 cycles per second (due to the p
You will see that the images of previous calls are still present by printing the number of images inside the plot
function,
print ( len(plt.gca().images) )
In your case this number will increase steadily, even though you delete the image, because it is still part of the axes and hence get redrawn every iteration.
It would be much better to draw the image once, and then only update its data.
class GoL():
# ...
def __init__(self, width, height, p=0.3):
self.width = width
self.height = height
self.matrix = np.random.choice(a=[1, 0], size=(width, height), p=[p, 1 - p])
self.im = plt.imshow(self.matrix)
# ....
def plot(self):
self.im.set_data(self.matrix)
plt.pause(0.05)
print len(plt.gca().images)
This will result in an animation at constant speed.
matplotlib.animation.FuncAnimation
, as this is much more stable and lets you savely terminate the animation.Full code:
import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage import convolve
import matplotlib.animation as animation
class GoL():
KERNEL = np.array([[1, 1, 1],
[1, 0, 1],
[1, 1, 1]])
def __init__(self, width, height, p=0.3):
self.width = width
self.height = height
self.matrix = np.random.choice(a=[1, 0], size=(width, height), p=[p, 1 - p])
self.im = plt.imshow(self.matrix)
def play(self):
self.plot()
self.ani= animation.FuncAnimation(plt.gcf(), self.cycle, repeat=True, interval=50 )
plt.show()
def cycle(self, n):
c = self.eval()
new = np.zeros_like(self.matrix)
new[c == 3] = 1
new[c < 2] = 0
new[c > 3] = 0
new[(self.matrix == 1) & (c == 2)] = 1
self.matrix = new
self.plot()
def eval(self):
return convolve(self.matrix, self.KERNEL, mode='constant')
def plot(self):
self.im.set_data(self.matrix)
gol = GoL(width=100,height=100)
gol.play()
Before reusing the canvas, you should clear the old figure. You can use matplotlib.pyplot.clf() to clear the current figure (http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.clf):
def plot(self):
plt.clf() # Clear the old figure
im = plt.imshow(self.matrix)
plt.pause(0.05)
Hope this helps! :)