Question Comment animer un nuage de points?


J'essaie de faire une animation d'un nuage de points où les couleurs et la taille des points changent à différents stades de l'animation. Pour les données, j'ai deux numpy ndarray avec une valeur x et une valeur y:

data.shape = (ntime, npoint)
x.shape = (npoint)
y.shape = (npoint)

Maintenant, je veux tracer un nuage de points du type

pylab.scatter(x,y,c=data[i,:])

et créer une animation sur l'index i. Comment puis-je faire cela?


35
2018-02-22 19:32


origine


Réponses:


Voici un exemple rapide utilisant le nouveau module d'animation.

C'est un peu plus complexe que cela doit être, mais cela devrait vous donner un cadre pour faire des choses plus sophistiquées.

Si vous êtes sur OSX et que vous utilisez le backend OSX, vous devrez changer blit=True à blit=False dans le FuncAnimation initialisation ci-dessous. Le backend OSX ne supporte pas complètement le blitting. La performance en souffrira, mais l'exemple devrait s'exécuter correctement sur OSX avec blitting désactivé.

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

class AnimatedScatter(object):
    """An animated scatter plot using matplotlib.animations.FuncAnimation."""
    def __init__(self, numpoints=50):
        self.numpoints = numpoints
        self.stream = self.data_stream()

        # Setup the figure and axes...
        self.fig, self.ax = plt.subplots()
        # Then setup FuncAnimation.
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, 
                                           init_func=self.setup_plot, blit=True)

    def setup_plot(self):
        """Initial drawing of the scatter plot."""
        x, y, s, c = next(self.stream)
        self.scat = self.ax.scatter(x, y, c=c, s=s, animated=True)
        self.ax.axis([-10, 10, -10, 10])

        # For FuncAnimation's sake, we need to return the artist we'll be using
        # Note that it expects a sequence of artists, thus the trailing comma.
        return self.scat,

    def data_stream(self):
        """Generate a random walk (brownian motion). Data is scaled to produce
        a soft "flickering" effect."""
        data = np.random.random((4, self.numpoints))
        xy = data[:2, :]
        s, c = data[2:, :]
        xy -= 0.5
        xy *= 10
        while True:
            xy += 0.03 * (np.random.random((2, self.numpoints)) - 0.5)
            s += 0.05 * (np.random.random(self.numpoints) - 0.5)
            c += 0.02 * (np.random.random(self.numpoints) - 0.5)
            yield data

    def update(self, i):
        """Update the scatter plot."""
        data = next(self.stream)

        # Set x and y data...
        self.scat.set_offsets(data[:2, :])
        # Set sizes...
        self.scat._sizes = 300 * abs(data[2])**1.5 + 100
        # Set colors..
        self.scat.set_array(data[3])

        # We need to return the updated artist for FuncAnimation to draw..
        # Note that it expects a sequence of artists, thus the trailing comma.
        return self.scat,

    def show(self):
        plt.show()

if __name__ == '__main__':
    a = AnimatedScatter()
    a.show()

enter image description here

Pour un exemple plus simple, regardez ce qui suit:

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

def main():
    numframes = 100
    numpoints = 10
    color_data = np.random.random((numframes, numpoints))
    x, y, c = np.random.random((3, numpoints))

    fig = plt.figure()
    scat = plt.scatter(x, y, c=c, s=100)

    ani = animation.FuncAnimation(fig, update_plot, frames=xrange(numframes),
                                  fargs=(color_data, scat))
    plt.show()

def update_plot(i, data, scat):
    scat.set_array(data[i])
    return scat,

main()

70
2018-02-23 16:04



Voici la chose. J'ai l'habitude d'un utilisateur de Qt et Matlab et je ne connais pas très bien le système d'animation du matplotlib.

Mais j'ai trouvé un moyen de créer n'importe quel type d'animation, comme dans matlab. C'est vraiment puissant. Pas besoin de vérifier les références du module et vous êtes bon pour tracer tout ce que vous voulez. J'espère donc que cela peut aider.

L'idée de base est d'utiliser l'événement time dans PyQt (je suis sûr que d'autres systèmes d'interface graphique sur Python comme wxPython et TraitUi ont le même mécanisme interne pour faire une réponse à un événement. Mais je ne sais pas comment). Chaque fois qu'un événement PyQt's Timer est appelé, je rafraîchit tout le canevas et redessine toute l'image, je sais que la vitesse et la performance peuvent être lentement influencées, mais ce n'est pas tellement.

Voici un petit exemple:

import sys
from PyQt4 import QtGui

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas

import numpy as np


class Monitor(FigureCanvas):
    def __init__(self):
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)

        FigureCanvas.__init__(self, self.fig)
        self.x = np.linspace(0,5*np.pi,400)
        self.p = 0.0
        self.y = np.sin(self.x+self.p)


        self.line = self.ax.scatter(self.x,self.y)

        self.fig.canvas.draw()

        self.timer = self.startTimer(100)


    def timerEvent(self, evt):
        # update the height of the bars, one liner is easier
        self.p += 0.1
        self.y = np.sin(self.x+self.p)
        self.ax.cla()
        self.line = self.ax.scatter(self.x,self.y)

        self.fig.canvas.draw()



if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    w = Monitor()
    w.setWindowTitle("Convergence")
    w.show()
    sys.exit(app.exec_())

Vous pouvez ajuster la vitesse de rafraîchissement dans le

        self.timer = self.startTimer(100)

Je suis juste comme vous qui voulez utiliser le nuage de points animé pour faire une animation de tri. Mais je ne peux tout simplement pas trouver une fonction dite "set". J'ai donc rafraîchi toute la canva.

J'espère que cela aide..


3
2018-06-14 03:14