2014-07-29 5 views
0

Я пытаюсь создать анимированный полярный график, который, когда радиальный предел зрения увеличивается/уменьшается для размещения радиуса. Якс обновляется просто отлично, если я устанавливаю полярность = False, но он не работает правильно для полярной оси.Matplotlib Анимация: обновление радиального предела просмотра для полярного графика

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

def data_gen(): 
    t = data_gen.t 
    cnt = 0 
    while cnt < 1000: 
     cnt+=1 
     t += 0.05 
     yield t, 1.1 + np.sin(2*np.pi*t) * np.exp(t/10.) 
data_gen.t = 0 

plt.rc ('grid', color='g', lw=1, ls='-') 
plt.rc ('xtick', labelsize=15, color='b') 
plt.rc ('ytick', labelsize=15, color='b') 
fig = plt.figure(figsize=(8,8)) 
ax1 = fig.add_axes([.05, .90, .9, .08], polar=False, axisbg='#BFBFBF', xticks=[], yticks=[]) 
ax2 = fig.add_axes([.05, .05, .9, .8], polar=True, axisbg='k') 
#ax = fig.add_axes([.1,.1,.8,.8], polar=False, axisbg='k') 
line, = ax2.plot([], [], lw=2) 
ax2.set_ylim(0, 2.2) 
ax2.set_xlim(0, 140) 
ax2.grid(1) 
xdata, ydata = [], [] 
title = ax1.text (0.02, 0.5, '', fontsize=14, transform=ax1.transAxes) 

def init(): 
    line.set_data([], []) 
    title.set_text ('') 
    return line, title 

def run(data): 
    # update the data 
    t,y = data 
    xdata.append(t) 
    ydata.append(y) 
    ymin, ymax = ax2.get_ylim() 

    if y >= ymax: 
     ax2.set_ylim (ymin, 2*ymax) 
     ax2.figure.canvas.draw() 

    title.set_text ("time = %.3f, y(t) = 1.1 + sin(2*pi*t) + exp(t/10) = %.3f" % (t, y)) 
    line.set_data(xdata, ydata) 
    return line, title 

ani = animation.FuncAnimation(fig, run, data_gen, init, blit=True, interval=100, repeat=False) 

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

У меня не было этой проблемы, когда я анимировал сюжет по-старому, неоднократно вызывая draw(). Но я предпочел бы сделать это правильно с модулем анимации, поскольку старый способ имел проблемы с производительностью (приведенный выше блок кода предназначен только для демонстрации проблемы и не является той самой программой, которую я пишу).

Следует отметить, что я все еще изучаю MPL, поэтому прошу прощения, если некоторые из моих терминов ошибаются.

+0

Turn bliting прочь. – tacaswell

+0

https://stackoverflow.com/questions/17895698/updating-the-xaxis-values-using-matplotlib-animation/17903145#17903145 <- связанный, но не совсем повторяющийся – tacaswell

+0

https://stackoverflow.com/questions/ 17558096/animated-title-in-matplotlib/17562747 # 17562747 <- также связанный, но не совсем повторяющийся. – tacaswell

ответ

1

Если вы используете blit, фон сохраняется в кэше для быстрого розыгрыша, вы можете очистить кэш, когда диапазон оси изменяется, добавьте ani._blit_cache.clear():

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

def data_gen(): 
    t = data_gen.t 
    cnt = 0 
    while cnt < 1000: 
     cnt+=1 
     t += 0.05 
     yield t, 1.1 + np.sin(2*np.pi*t) * np.exp(t/10.) 
data_gen.t = 0 

plt.rc ('grid', color='g', lw=1, ls='-') 
plt.rc ('xtick', labelsize=15, color='b') 
plt.rc ('ytick', labelsize=15, color='b') 
fig = plt.figure(figsize=(8,8)) 
ax1 = fig.add_axes([.05, .90, .9, .08], polar=False, axisbg='#BFBFBF', xticks=[], yticks=[]) 
ax2 = fig.add_axes([.05, .05, .9, .8], polar=True, axisbg='k') 
#ax = fig.add_axes([.1,.1,.8,.8], polar=False, axisbg='k') 
line, = ax2.plot([], [], lw=2) 
ax2.set_ylim(0, 2.2) 
ax2.set_xlim(0, 140) 
ax2.grid(1) 
xdata, ydata = [], [] 
title = ax1.text (0.02, 0.5, '', fontsize=14, transform=ax1.transAxes) 

def init(): 
    line.set_data([], []) 
    title.set_text ('') 
    return line, title 

def run(data): 
    # update the data 
    t,y = data 
    xdata.append(t) 
    ydata.append(y) 
    ymin, ymax = ax2.get_ylim() 

    if y >= ymax: 
     ax2.set_ylim (ymin, 2*ymax) 
     ani._blit_cache.clear() # <- add to clear background from blit cache 
     title.set_text('') # <- eliminate text artifact in title 
     ax2.figure.canvas.draw() 

    title.set_text ("time = %.3f, y(t) = 1.1 + sin(2*pi*t) + exp(t/10) = %.3f" % (t, y)) 
    line.set_data(xdata, ydata) 
    return line, title 

ani = animation.FuncAnimation(fig, run, data_gen, init, blit=True, interval=100, repeat=False) 
+0

Определенно, взлом, но, возможно, лучшее решение, доступное на данный момент. Любая идея, почему это не нужно делать с прямоугольными осями? Кроме того, у меня была одна проблема с вашим решением. Как вы можете видеть, я редактировал код так, чтобы он имел анимированный заголовок на отдельных осях. После очистки blit cache он оставляет заголовок артефакта под анимированным. Я исправил это, очистив заголовок до перерисовки. Я добавил это к вашему ответу. – orodbhen