matplotlib FuncAnimation очистить график каждого повторяющегося цикла

Приведенный ниже код работает, но я думаю, что исходные точки пересчитываются в каждом цикле повторения. Я хочу, чтобы он начинался с начала, каждый повторяющийся цикл с четким сюжетом. Среди многих подходов к исправлению этого я пытался вставить ax.clear() как в функции инициализации, так и в функции обновления; не эффективны. Я оставил в коде то, что, как я думал, сбросит ln, artist к пустому набору; опять же, это не то решение, которое я ищу. Я был бы признателен за некоторые рекомендации о том, как правильно повторно инициировать каждый цикл в этом игрушечном примере, чтобы при применении к моей более сложной проблеме я не подвергался кумулятивным штрафам. Это отлично работает с точки зрения обновления при передаче массива... Спасибо за любую помощь.

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

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

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,

Напротив, это работает так, как задумано...

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)

Это побудило меня попробовать следующее, отметив, что передача внутреннего (r, theta) внутри update() снаружи требует объявления его как глобальной переменной. С помощью следующего кода график теперь сбрасывает каждый цикл вместо перерисовки. Я чувствую, что это довольно долгий путь вокруг простой процедуры - любые улучшения принимаются с благодарностью.

#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,

person Time Lord    schedule 09.11.2017    source источник


Ответы (1)


Если я понимаю ваш код и ваш вопрос, вы хотите отображать только одну точку в каждом кадре анимации, это правильно?

Если это так, ваша проблема заключается просто в том, что вы добавляете каждую новую точку ко всем предыдущим точкам в функции update(). Вместо этого просто обновите координаты данных, например:

def update(frame):
    r = frame
    theta = 2*np.pi*frame
    ln.set_data(theta, r)
    return ln,

введите описание изображения здесь

ИЗМЕНИТЬ Давайте посмотрим, правильно ли я понял на этот раз.

Вы можете выбрать отображение только последних N точек следующим образом:

N=10
def update(frame):
    r.append(frame)
    theta.append(2*np.pi*frame)
    ln.set_data(theta[-N:], r[-N:])
    return ln,

введите описание изображения здесь

или вы можете добавить N точек к своему массиву, а затем сбросить до пустого массива. Я думаю, это может быть то, что вы пытались сделать. Здесь вы должны быть осторожны. Если вы просто сделаете r = [], вы измените объект, на который ссылается r, и это нарушит анимацию. Что вам нужно сделать, так это изменить содержимое массива с помощью синтаксиса 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,

введите описание изображения здесь

person Diziet Asahi    schedule 09.11.2017
comment
На самом деле нет - я хочу создать увеличивающийся список (или массив), а затем сбрасывать список при каждом цикле повторения. Я пытался сделать это с массивами и с использованием различных конструкций. Когда я попытался вставить некоторую форму условного оператора в длину списка, а затем вернуться к r=[], например, в функции обновления, это останавливает работу функции. Я также пытался играть с блитом True/False, но безуспешно. - person Time Lord; 09.11.2017
comment
Я все еще не уверен на 100%, что вы имеете в виду, но я изменил свой ответ двумя другими возможностями. - person Diziet Asahi; 09.11.2017
comment
Спасибо, объявление, что r[:] = [] производит требуемый сброс глобального r&theta. Взгляните на мою последнюю попытку решения, установка r и theta в качестве глобальных переменных в update() также работает. Я думаю, что проблема заключается в том, как передать функциональные переменные обратно из функции в глобальные переменные, как было изначально установлено. Если читатели попробуют приведенный выше код с каждым вариантом update(), проблема покажется более ясной (надеюсь). Поскольку вставка r[:]=[] работает, ваш ответ будет принят с благодарностью за помощь :) - person Time Lord; 09.11.2017
comment
Я думаю, что происходит то, что r[:] = [] заменяет content r, который остается глобальным (оно было объявлено вне функции). r = [] заменяет объект r, поэтому новый объект больше не является глобальным. Его нужно повторно объявить глобальным, чтобы использовать позже. - person Diziet Asahi; 09.11.2017