I have started reading "Advanced Python Programming", 2nd ed of Quan Nguyen. The code to simulate particles' circular motion is not working for me. But according to the book, it should work: I wonder if I am missing something. I run it on Windows 11, Python 3.8.12 and VScode or JupyterLab. Nothing seems to happen (in vscode) and a warning in JupyterLab.
Here is the code:
# %load simul.py
from matplotlib import pyplot as plt
from matplotlib import animation
from random import uniform
import timeit
import os
os.system('cls' if os.name == 'nt' else 'clear')
class Particle:
__slots__ = ("x", "y", "ang_speed")
def __init__(self, x, y, ang_speed):
self.x = x
self.y = y
self.ang_speed = ang_speed
class ParticleSimulator:
def __init__(self, particles):
self.particles = particles
def evolve(self, dt):
timestep = 0.00001
nsteps = int(dt / timestep)
for i in range(nsteps):
for p in self.particles:
norm = (p.x ** 2 + p.y ** 2) ** 0.5
v_x = (-p.y) / norm
v_y = p.x / norm
d_x = timestep * p.ang_speed * v_x
d_y = timestep * p.ang_speed * v_y
p.x += d_x
p.y += d_y
def visualize(simulator):
X = [p.x for p in simulator.particles]
Y = [p.y for p in simulator.particles]
fig = plt.figure()
ax = plt.subplot(111, aspect="equal")
(line,) = ax.plot(X, Y, "ro")
# Axis limits
plt.xlim(-1, 1)
plt.ylim(-1, 1)
# It will be run when the animation starts
def init():
line.set_data([], [])
return (line,)
def animate(i):
# We let the particle evolve for 0.1 time units
simulator.evolve(0.01)
X = [p.x for p in simulator.particles]
Y = [p.y for p in simulator.particles]
line.set_data(X, Y)
return (line,)
# Call the animate function each 10 ms
anim = animation.FuncAnimation(fig, animate, init_func=init, blit=True, interval=10)
plt.show()
def test_visualize():
particles = [
Particle(0.3, 0.5, +1),
Particle(0.0, -0.5, -1),
Particle(-0.1, -0.4, +3),
]
simulator = ParticleSimulator(particles)
visualize(simulator)
if __name__ == "__main__":
test_visualize()
The code can also be found here.
When run with JupyterLab, I get the following warning:
C:\Users\ephra\AppData\Local\Temp\ipykernel_18360\3786700959.py:71: UserWarning: frames=None which we can infer the length of, did not pass an explicit *save_count* and passed cache_frame_data=True. To avoid a possibly unbounded cache, frame data caching has been disabled. To suppress this warning either pass `cache_frame_data=False` or `save_count=MAX_FRAMES`.
anim = animation.FuncAnimation(fig, animate, init_func=init, blit=True, interval=10)
Am I running it in a wrong way?
that's probably the reason why an explicit value isn't passed. To avoid infinite caching, frame data caching has been disabled. You can turn off cached frame data by passing cache_frame_data=False
or pass a numeric value using save_count=MAX_FRAMES
to prevent this warning from appearing.