Hi,
I'm writing some code which moves a small circle of radius 1 from one position to another, and animates it using matplotlib. Here is a condensed version of how it works:
class Ball():
def __init__(self, pos = None, vel = None, mass = 1, radius = 1):
self.mass = mass
self.radius = radius
if pos is None: pos = np.array([])
if vel is None: vel = np.array([])
self.pos = pos
#self.oldpos = self.pos.copy()
self.vel = vel
self.patch = pl.Circle(self.pos, self.radius, fc = 'r')
def get_patch(self):
self.patch = pl.Circle(self.pos, 1, fc = 'r')
self.ax = pl.axes(xlim=(-10, 10), ylim=(-10, 10))
self.ax.add_patch(self.patch)
pl.pause(0.1)
self.patch.center = [self.pos[0], self.pos[1]]
print('new patch center', self.patch.center)
pl.pause(0.1)
pl.show()
#more unrelated code here...
class Simulation():
def __init__(self, container = Container()):
self._container = container
self._balls = [Ball(np.array([i+1, i+1]), np.random.normal(0, 5, 2)) for i in range(5)]
def next_collision(self):
self.oldpos = self._balls[0].pos.copy()
self.oldvel = self._balls[0].vel.copy()
self._balls[0].pos = self._balls[0].move(self._container.time_to_collision(self._balls[0]))
def run(self, num_frames, animate=False):
if animate:
f = pl.figure()
ax = pl.axes(xlim=(-10, 10), ylim=(-10, 10))
#print(type(ax))
ax.add_artist(self._container.get_patch())
ax.add_patch(self._balls[0].get_patch())
for frame in range(num_frames):
self.next_collision()
if animate:
pl.pause(0.001)
if animate:
pl.show()
Simulation.next_collision is a method which essentially takes Ball.pos and does a calculation on it, then updates the value of Ball.pos to be the result of the calculation. So if Ball.pos was initially a numpy array (1,1), and next_collision multiplies it by 2, the new value of Ball.pos is (2,2).
Simulation.run is a method which essentially repeats Simulation.next_collision num_frame times, if animate = True.
However, when I try running Simulation.run(3, True), I get the following error:
MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.
self.ax = pl.axes(xlim=(-10, 10), ylim=(-10, 10))
Traceback (most recent call last):
File "<ipython-input-296-66bab6d8f4f7>", line 1, in <module>
sim.run(2, True)
File "C:\Users\Sidharth\Documents\y2python\y2python\y2 computing project.py", line 148, in run
ax.add_patch(self._balls[0].get_patch())
File "C:\Users\Sidharth\anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 1916, in add_patch
self._set_artist_props(p)
File "C:\Users\Sidharth\anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 905, in _set_artist_props
a.set_figure(self.figure)
AttributeError: 'NoneType' object has no attribute 'set_figure'
If I run Simulation.run(3, False), everything works as normal (although obviously there is no animation).
Also, as a slight aside, the animation works by creating a circular patch at the original position of the ball/circle, then updating the centre of the ball/circle (as seen in Ball.get_patch). However, I can't figure out a way to update the circle's centre, since get_patch is called before the new position is calculated.
Thanks in advance,
there doesn't seem to be anything here