2015-11-19 4 views
0

Здесь мой код разделился до минимального минимального, чтобы правильно воспроизвести мою проблему.FuncAnimation(): удалить/обновить старые строки

import matplotlib.animation as animation 
import os 
import matplotlib.pyplot as plt 
import numpy as np 
import os.path 

f, ((ax1, ax2)) = plt.subplots(1, 2, figsize=(20,10)) 

def animate(i): 
    chosenEnergy = (0.0 + (i-1)*(0.02)) 
    chosenEnergyLine = ax2.axvline(float(chosenEnergy),0,1, linestyle='dashed') 
    return chosenEnergyLine, 

def init(): 
    chosenEnergyLine = ax2.axvline(0.0,0,1, linestyle='dashed') 
    return chosenEnergyLine, 

ani = animation.FuncAnimation(f, animate, np.arange(1,nE), init_func=init, 
interval=25, blit=False, repeat = False) 

plt.rcParams['animation.ffmpeg_path'] = '/opt/local/bin/ffmpeg' 
FFwriter = animation.FFMpegWriter() 

ani.save('basic_animation.mp4', writer = FFwriter, fps=30, extra_args=['-vcodec', 'libx264']) 
print "finished" 

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

Я нашел аналогичный вопрос (matplotlib circle, animation, how to remove old circle in animation), но, похоже, не применим для моего дела.

Даже если аналогичная функция, используемая в ответе на этот подобный вопрос (set_radius), существует для xvline, я бы предпочел не использовать его. В моем другом подзаголовке (ax1) у меня есть график рассеяния, который нужно будет обновлять каждый раз. Есть ли общий способ очистить сюжет до следующего шага?

Я также не заметил никаких изменений при использовании blit = False или blit = True.

Любое предложение о том, как действовать?

ответ

1

Каждый раз, когда вы звоните animate, вы рисуете новую строку. Вы должны либо удалить старые строки, либо перенести свою линию с помощью set_xdata вместо того, чтобы рисовать новую.

def animate(i,chosenEnergyLine): 
    chosenEnergy = (0.0 + (i-1)*(0.02)) 
    chosenEnergyLine.set_xdata([chosenEnergy, chosenEnergy]) 
    return chosenEnergyLine, 

chosenEnergyLine = ax2.axvline(0.0,0,1, linestyle='dashed') 
ani = animation.FuncAnimation(f, animate, np.arange(1,10), 
     fargs=(chosenEnergyLine,), interval=25, blit=False, repeat = False) 

UPDATE: Это потому, что вы пытаетесь удалить те же глобальные chosenEnergyLine несколько раз (FuncAnimation ловит возвращаемое значение animate, но не обновляет глобальный chosenEnergyLine с ним). Решение заключается в использовании вида статической переменной в анимации для отслеживания последних chosenEnergyLine

def animate(i): 
    chosenEnergy = (0.0 + (i-1)*(0.02)) 
    animate.chosenEnergyLine.remove() 
    animate.chosenEnergyLine = ax2.axvline(float(chosenEnergy),0,1, linestyle='dashed') 
    return animate.chosenEnergyLine, 

animate.chosenEnergyLine = ax2.axvline(0.0,0,1, linestyle='dashed') 

ani = animation.FuncAnimation(f, animate, np.arange(1,10), 
       interval=25, blit=False, repeat = False) 
+0

Я вижу. Благодарю. А как насчет вашего другого предложения: удаление старых строк (или разброс графиков и т. Д.)? Это, наверное, более общее и более полезное для меня, поскольку у меня есть другие части моей фигуры, которые нужно обновлять на каждом шагу ... Я попытался использовать функции 'del' или obj.remove() внутри' animate', но cann «Сделай это. Обычно он жаловался, что объект 'selectedEnergyLine' не существует. – Nigu

+1

@Nigu Я обновил ответ – Azad

+0

Работает как шарм. Благодаря! – Nigu