2013-02-06 16 views
5

Animasyonlu bir dağılım grafiğini matplotlib ile kaydetmeye çalışıyorum ve animasyonlu bir şekil olarak görüntülemek ve bir kopyasını kaydetmek için tamamen farklı bir kod gerektirmemesini tercih ederim. Şekil, kayıt tamamlandıktan sonra tüm veri noktalarını mükemmel bir şekilde gösterir.Matplotlib ile scatterplot animasyonlarını kaydetme

Bu kod Matplotlib 3D scatter color lost after redraw üzerinde Yann's answer gelen renkler için bir düzeltme ile Animating 3d scatterplot in matplotlib üzerinde Giggi's değiştirilmiş bir versiyonudur (renk Videomda önemli olacaktır çünkü, bu yüzden çalıştıklarından emin olmak istiyoruz).

import matplotlib.pyplot as plt 
import matplotlib.animation as animation 
import numpy as np 
from mpl_toolkits.mplot3d import Axes3D 

FLOOR = -10 
CEILING = 10 

class AnimatedScatter(object): 
    def __init__(self, numpoints=5): 
     self.numpoints = numpoints 
     self.stream = self.data_stream() 
     self.angle = 0 

     self.fig = plt.figure() 
     self.fig.canvas.mpl_connect('draw_event',self.forceUpdate) 
     self.ax = self.fig.add_subplot(111,projection = '3d') 
     self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
             init_func=self.setup_plot, blit=True,frames=20) 

    def change_angle(self): 
     self.angle = (self.angle + 1)%360 

    def forceUpdate(self, event): 
     self.scat.changed() 

    def setup_plot(self): 
     X = next(self.stream) 
     c = ['b', 'r', 'g', 'y', 'm'] 
     self.scat = self.ax.scatter(X[:,0], X[:,1], X[:,2] , c=c, s=200, animated=True) 

     self.ax.set_xlim3d(FLOOR, CEILING) 
     self.ax.set_ylim3d(FLOOR, CEILING) 
     self.ax.set_zlim3d(FLOOR, CEILING) 

     return self.scat, 

    def data_stream(self): 
     data = np.zeros((self.numpoints , 3)) 
     xyz = data[:,:3] 
     while True: 
      xyz += 2 * (np.random.random((self.numpoints,3)) - 0.5) 
      yield data 

    def update(self, i): 
     data = next(self.stream) 
     #data = np.transpose(data) 

     self.scat._offsets3d = (np.ma.ravel(data[:,0]) , np.ma.ravel(data[:,1]) , np.ma.ravel(data[:,2])) 

     plt.draw() 
     return self.scat, 

    def show(self): 
     plt.show() 

if __name__ == '__main__': 
    a = AnimatedScatter() 
    a.ani.save("movie.avi", codec='avi') 
    a.show() 

Mükemmel geçerli .avi bu tarafından oluşturulan, ancak eksenler haricinde dört saniye tümü için boş. Asıl rakam her zaman tam olarak görmek istediğimi gösterir. Kaydetme işlevinin grafiklerini, normal olarak çalışan bir animasyonu doldurduğum şekilde nasıl doldurabilirim veya matplotlib'de mümkün mü?

DÜZENLEME: (in başlatıcısı olarak sınırları ayarlamadan) güncellemede bir dağılım çağrısını kullanma sadece gösterilmediğinden, eksenler veriler her zaman yürütülüyor gittiğine işaret büyüyen göstermek için avi neden olur videonun kendisi. Python 2.7.3 ile matplotlib 1.1.1rc kullanıyorum.

+0

Eğer girintinizi düzeltebilirsiniz: Aşağıda

ben koştum ve beklenen çıkışı film var tam olarak ne? – tacaswell

+0

Whoops. Daha dikkatli kopyalama ve yapıştırma yapmalıyım. Kaynağımın sekmeler yerine boşlukları olsa da, ne olduğunu tam olarak bilmiyorum. – Poik

+0

ve bir şekilde izlerseniz bu iyi görünüyor? Hangi MPL sürümünü kullanıyorsunuz? – tacaswell

cevap

2

FuncAnimation ve animated=True'dan gelen blit=True'u scatter'dan kaldırın ve çalışır. Mantıkla yanlış giden bir şey olduğunu sanıyorum, sadece güncellenmesi gereken sanatçıların çerçeveler arasında (her şeyi yeniden çizmek yerine) güncellendiğinden/yeniden çizildiğinden emin olur.

import matplotlib.pyplot as plt 
import matplotlib.animation as animation 
import numpy as np 
from mpl_toolkits.mplot3d import Axes3D 

FLOOR = -10 
CEILING = 10 

class AnimatedScatter(object): 
    def __init__(self, numpoints=5): 
     self.numpoints = numpoints 
     self.stream = self.data_stream() 
     self.angle = 0 

     self.fig = plt.figure() 
     self.fig.canvas.mpl_connect('draw_event',self.forceUpdate) 
     self.ax = self.fig.add_subplot(111,projection = '3d') 
     self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
             init_func=self.setup_plot, frames=20) 

    def change_angle(self): 
     self.angle = (self.angle + 1)%360 

    def forceUpdate(self, event): 
     self.scat.changed() 

    def setup_plot(self): 
     X = next(self.stream) 
     c = ['b', 'r', 'g', 'y', 'm'] 
     self.scat = self.ax.scatter(X[:,0], X[:,1], X[:,2] , c=c, s=200) 

     self.ax.set_xlim3d(FLOOR, CEILING) 
     self.ax.set_ylim3d(FLOOR, CEILING) 
     self.ax.set_zlim3d(FLOOR, CEILING) 

     return self.scat, 

    def data_stream(self): 
     data = np.zeros((self.numpoints , 3)) 
     xyz = data[:,:3] 
     while True: 
      xyz += 2 * (np.random.random((self.numpoints,3)) - 0.5) 
      yield data 

    def update(self, i): 
     data = next(self.stream) 
     self.scat._offsets3d = (np.ma.ravel(data[:,0]) , np.ma.ravel(data[:,1]) , np.ma.ravel(data[:,2])) 
     return self.scat, 

    def show(self): 
     plt.show() 

if __name__ == '__main__': 
    a = AnimatedScatter() 
    a.ani.save("movie.avi", codec='avi') 
    a.show() 
+0

Bu hile yaptı! Ve benim gerçek projem bu düzeltmeyle çalıştı. Teşekkürler! – Poik

+0

'blit' işlevini kaldırmak, '_draw_next_frame' işlevini çağırırken, animation.save kod kümesinin' blit' false değerini göz önüne alarak yardımcı olur. Anladığımda matplotlib sitesinin sitesine tam hata raporları (veya en azından istek listesi istekleri) ekleyeceğim. – Poik

+0

SciPy 0.12.0, Numpy 1.7.1 ve Matplotlib 1.2.1 ile çalışamıyorum. En iyi ihtimalle yeni noktalar veya boş bir arsa tarafından üzerine çizilen tonlarca eski noktaya sahip bir video oluşturur. Videomda bağlı olan kodu deneyebilirsiniz: https://www.youtube.com/watch?v=dCIOOjJ1Sk0 Sonunda CamStudio kullandım ve daha iyi çalıştı ve daha yüksek kalitede video çıkışı elde ettim. – Demolishun