2013-04-20 14 views
6

Próbuję animować fill_between kształt wewnątrz matplotlib i nie wiem jak zaktualizować dane PolyCollection. Weź ten prosty przykład: Mam dwie linie i zawsze je wypełniam. Oczywiście linie się zmieniają i są animowane.Matplotlib animate fill_between shape

Oto fikcyjny przykład:

import matplotlib.pyplot as plt 

# Init plot: 
f_dummy = plt.figure(num=None, figsize=(6, 6)); 
axes_dummy = f_dummy.add_subplot(111); 

# Plotting: 
line1, = axes_dummy.plot(X, line1_data, color = 'k', linestyle = '--', linewidth=2.0, animated=True); 
line2, = axes_dummy.plot(X, line2_data, color = 'Grey', linestyle = '--', linewidth=2.0, animated=True); 
fill_lines = axes_dummy.fill_between(X, line1_data, line2_data, color = '0.2', alpha = 0.5, animated=True); 

f_dummy.show(); 
f_dummy.canvas.draw(); 
dummy_background = f_dummy.canvas.copy_from_bbox(axes_dummy.bbox); 

# [...]  

# Update plot data: 
def update_data(): 
    line1_data = # Do something with data 
    line2_data = # Do something with data 
    f_dummy.canvas.restore_region(dummy_background); 
    line1.set_ydata(line1_data); 
    line2.set_ydata(line2_data); 

    # Update fill data too 

    axes_dummy.draw_artist(line1); 
    axes_dummy.draw_artist(line2); 

    # Draw fill too 

    f_dummy.canvas.blit(axes_dummy.bbox); 

Pytanie jest jak zaktualizować dane fill_between Poly oparciu o line1_data i line2_data każdy update_data czasu() jest wywoływana i wyciągnąć je przed Blit ("# Aktualizacja wypełnienie danych też "&" # Draw fill too "). Próbowałem fill_lines.set_verts() bez powodzenia i nie mogłem znaleźć przykładu ...

Dzięki!

+1

Być może trzeba będzie usunąć i całkowicie ponownie rysować każdą klatkę. Obiekty '* collection' nie ładują się z aktualizacją. Powodem jest to, że wyrzucili wszystkie meta-dane, które pozwolą ci mapować między przestrzenią danych i przestrzenią losowania, i po prostu trzymaj listę tego, co narysować. To jest kompromis, aby szybko je wykonać. – tacaswell

+0

Czy chcesz użyć f_dummy.canvas.draw() wewnątrz pliku update_data?Zacząłem od tego, ale niestety potrzebuję szybkiego kreślenia, ponieważ przetwarzam i odtwarzam sygnał w czasie rzeczywistym i potrzebuję, aby wydruk nie wpłynął na odtwarzanie (wywołanie draw() zatrzymuje odtwarzanie). Jeśli znasz sztuczkę z szybkim gwintem, aby przerysować wszystko podczas odtwarzania dźwięków, byłoby miło - zadzwoniłem do remisu z threading.start (...). Wiem, że istnieją inne szybsze kreślenie bibliotek, ale wolę trzymać się matplotlib i sztuczka przywracania/blit działała wystarczająco szybko dla mnie. – Sebastian

Odpowiedz

3

Ok, jak ktoś zauważył mamy do czynienia z kolekcją tutaj, więc będziemy musieli usunąć i przerysować

dana ta oś obiekt axes_dummy = f_dummy.add_subplot (111);

więc gdzieś w update_data(): będziesz. .

usunąć wszystkie zbiory związane z nim

for coll in (axes_dummy.collections): 
    axes_dummy.collections.remove(coll) 

narysować nową „filled_between” Polycollection

axes_dummy.fill_between(x,y-sigma,y+sigma, 
        facecolor='yellow', alpha=0.5) 

Podobna sztuczka jest wymagany do nakładki niewypełnione konturu działki na górze wypełnionego jednego, ponieważ Niewypełniony kontur jest również kolekcją (linii, jak sądzę?)

+1

Jeśli chcesz usunąć tylko jedną kolekcję, możesz użyć 'coll.get_label()', aby uzyskać właściwą, pod warunkiem, że najpierw oznaczono etykietę kolekcji. – Sardathrion

1

to nie moja odpowiedź, ale uznałem ją za najbardziej użyteczną:

http://matplotlib.1069221.n5.nabble.com/animation-of-a-fill-between-region-td42814.html

Hi Mauricio, obiekty krosowe są nieco trudniejsze niż praca z obiektów liniowych, ponieważ w odróżnieniu obiekty liniowe są krokiem usunięty z danych wejściowych dostarczanych przez użytkownika. Istnieje przykład podobny do tego, co chcesz tutaj zrobić: http://matplotlib.org/examples/animation/histogram.html

Zasadniczo musisz zmodyfikować wierzchołki ścieżki w każdej klatce. Może to wyglądać mniej więcej tak:

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

fig, ax = plt.subplots() 
ax.set_xlim([0,10000]) 

x = np.linspace(6000.,7000., 5) 
y = np.ones_like(x) 

collection = plt.fill_between(x, y) 

def animate(i): 
    path = collection.get_paths()[0] 
    path.vertices[:, 1] *= 0.9 

animation.FuncAnimation(fig, animate, 
         frames=25, interval=30) 

Zobacz, jak są ułożone na stronie path.vertices. nadzieję, że pomoże, Jake

1

Jeśli nie chcesz używać anitmation lub usunąć wszystko z rysunku, aby aktualizować tylko wypełnienie, można użyć mój sposób:

połączenia fill_lines.remove() a następnie zadzwonić ponownie axes_dummy.fill_between() narysować nowe. Pracował dla mnie.