Matplotlib: Как добавить сюжет после остановки FuncAnimation?

#python #matplotlib #animation #scatter-plot

Вопрос:

Я хочу запустить анимацию, в которой можно увидеть, как «точка» движется и оставляет «след» позади. После того, как вся трассировка будет нарисована, я хочу отобразить данные (ось.разброс) на заднем плане. Прямо сейчас он сначала строит диаграмму рассеяния и рисует линию поверх нее.

Итак, это движущаяся точка с темно-серым следом: введите описание изображения здесь

И после того, как это закончится, я хочу, чтобы это выглядело так: введите описание изображения здесь

 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()
 

Я уже пытался добавить следующее в функцию обновления, но это не работает:

 ...
if i == maxlen:
    scatter = axis.scatter(x_s, y_s, color='lightgrey', zorder=1)
    return point, trace, time_text, scatter
...
 

Есть ли способ дождаться остановки анимации и добавить диаграмму рассеяния после этого?
Или мне нужно найти способ включить это в функцию обновления?

Ответ №1:

Я сам нашел решение: есть два способа сделать это: либо с .set_offfsets помощью линейного графика, либо с помощью 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()