The code below works, but I think is overplotting the original points each repeat cycle. I want it to start from the origin, each repeat cycle, with a clear plot. Amongst many approaches to fixing this, I have tried inserting ax.clear() in both the init and update functions; not effective. I have left in the code what I thought would reset the ln, artist to having an empty set; again this is not the solution I am looking for. I would appreciate some guidance on what the correct way to reinitiate each cycle is in this toy example so that, when applied to my more complex problem, I don't incur cumulative penalties. This works fine in terms of refreshing if passing an array...Thanks for any help.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, writers
#from basic_units import radians
# # Set up formatting for the movie files
# Writer = writers['ffmpeg']
# writer = Writer(fps=20, metadata=dict(artist='Llew'), bitrate=1800)
#Polar stuff
fig = plt.figure(figsize=(10,8))
ax = plt.subplot(111,polar=True)
ax.set_title("A line plot on a polar axis", va='bottom')
ax.set_rticks([0.5, 1, 1.5, 2]) # fewer radial ticks
ax.set_facecolor(plt.cm.gray(.95))
ax.grid(True)
xT=plt.xticks()[0]
xL=['0',r'$\frac{\pi}{4}$',r'$\frac{\pi}{2}$',r'$\frac{3\pi}{4}$',\
r'$\pi$',r'$\frac{5\pi}{4}$',r'$\frac{3\pi}{2}$',r'$\frac{7\pi}{4}$']
plt.xticks(xT, xL)
r = []
theta = []
# Animation requirements.
ln, = plt.plot([], [], 'r:',
markersize=1.5,
alpha=1,
animated=True)
def init():
ax.set_xlim(0, 2)
ax.set_ylim(0, 2)
return ln,
def update(frame):
r.append(frame)
theta.append(5*np.pi*frame)
ln.set_data(theta, r)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0,2,400),
init_func=init, interval=10, blit=True,repeat=True)
plt.show()
I tried to reset the lists (and with arrays also) using this somewhat crude approach, which wiped the list, but did not re-initiate the cycle.
def update(frame,r,theta):
r.append(frame)
theta.append(5*np.pi*frame)
if len(r)>=400:
r = [0]
theta=[0]
ln.set_data(theta, r)
return ln,
In contrast, this does work as intended...
for i in range(25):
r.append(i)
print('len(r)',len(r), r)
if len(r) >=10:
r = []
print('if r>=10:',r)
print('Post conditional clause r',len(r),r)
This led me to try the following, noting that passing the internal (r,theta) within the update() outside requires declaring it as a global variable. With the following code, the plot now resets each cycle instead of overplotting. My sense is that this is a rather long way around a simple procedure -- any improvements gratefully accepted.
#This solution also works
def update(frame):
r.append(frame)
theta.append(5*np.pi*frame)
if len(r)>=400:
global r
r = []
global theta
theta=[]
ln.set_data(theta, r)
return ln,
If I understand your code and your question, you want to display only one point at each frame of the animation, is that correct?
If so, your problem is simply that you are appending each new point to all previous points in the function update()
. Instead, simply update the data coordinates, like so:
def update(frame):
r = frame
theta = 2*np.pi*frame
ln.set_data(theta, r)
return ln,
EDIT Let's see if I get this right this time around.
You could choose to only show the last N
points like so:
N=10
def update(frame):
r.append(frame)
theta.append(2*np.pi*frame)
ln.set_data(theta[-N:], r[-N:])
return ln,
or you can append N
points to your array, then reset to an empty array. I think that might be what you were trying to do. Here, you have to be careful. If you simply do r = []
then you change which object r
references to, and that breaks the animation. What you need to do is change the content of the array with the syntax r[:] = []
.
def update(frame):
r_ = frame
theta_ = 2*np.pi*frame
if len(r)>N:
r[:] = [r_]
theta[:] = [theta_]
else:
r.append(r_)
theta.append(theta_)
ln.set_data(theta, r)
return ln,
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