I want to run an animation, where one can see a "point" moving and leaving a "trace" behind. After the whole trace is drawn, I want to plot data (axis.scatter) to the background. Right now it plots the scatter plot first and draws the line on top of it.
So this is the moving point with the dark-grey trace:
And after this is finished, I want it to look like this:
figure, axis = plt.subplots()
point, = axis.plot([], [], zorder=3)
trace, = axis.plot([], [], zorder=2)
x_s_reduced = x_s[300::300] # len(x_s) = 5e5
y_s_reduced = y_s[300::300] # len(y_s) = 5e5
sampling_period = sampling_period * 300 # sampling_period = 1e-5
#
maxlen = len(x_s_reduced)
history_x, history_y = deque(maxlen=maxlen), deque(maxlen=maxlen)
def update(i):
if i == 0:
history_x.clear()
history_y.clear()
history_x.appendleft(x_s_reduced[i])
history_y.appendleft(y_s_reduced[i])
point.set_data(x_s_reduced[i], y_s_reduced[i])
trace.set_data(history_x, history_y)
#if i == maxlen:
#scatter = axis.scatter(x_s, y_s, color='lightgrey', zorder=1)
#return point, trace, time_text, scatter
return point, trace, time_text
#
beam_video = animation.FuncAnimation(figure, update, frames=maxlen, interval=0.001, repeat=False, blit=True)
axis.scatter(x_s, y_s, color='lightgrey', zorder=1)
plt.show()
I already tried to add the following to the update function, but it does not work:
...
if i == maxlen:
scatter = axis.scatter(x_s, y_s, color='lightgrey', zorder=1)
return point, trace, time_text, scatter
...
Is there a way to wait for the animation to stop and add the scatterplot afterwards? Or do I have to find a way to incorporate this in the update function?
CodePudding user response:
I found the solution myself:
There are two ways to do this, either with .set_offfsets
or making a line plot with marker="o"
figure, axis = plt.subplots()
point, = axis.plot([], [], marker="o", color="crimson", zorder=3)
trace, = axis.plot([], [], ',-', zorder=2, color='darkgrey', linewidth=1)
# scatter, = axis.plot([], [], marker="o", color='lightgrey', zorder=1)
scatter = axis.scatter([], [], color='lightgrey', zorder=1)
#
filter = 10
x_s_reduced = x_s[filter::filter]
y_s_reduced = y_s[filter::filter]
sampling_period = sampling_period * filter
#
maxlen = len(x_s_reduced)
history_x, history_y = deque(maxlen=maxlen), deque(maxlen=maxlen)
time_template = 'Time = %.6fs'
time_text = axis.text(0.01, 0.95, '', transform=axis.transAxes, fontsize=14)
def update(i):
if i == 0:
history_x.clear()
history_y.clear()
history_x.appendleft(x_s_reduced[i])
history_y.appendleft(y_s_reduced[i])
point.set_data(x_s_reduced[i], y_s_reduced[i])
trace.set_data(history_x, history_y)
time_text.set_text(time_template % (i * sampling_period))
#scatter.set_data([], [])
scatter.set_offsets(np.c_[[], []])
if i == (maxlen-1):
print('END')
#scatter.set_data(x_s, y_s)
scatter.set_offsets(np.c_[x_s, y_s])
return point, trace, time_text, scatter
#
beam_video = animation.FuncAnimation(figure, update, frames=maxlen, interval=0.001, repeat=False, blit=True)
plt.show()