2010-01-21 28 views
5

Así que estoy representando una red Token Ring (haciendo la simulación en SimPy), soy totalmente novato en matplotlib, pero me dijeron que sería realmente bueno para representando mi simulación visualmenteMatplotlib en Python - Dibujando formas y animándolas

Así que busqué en Google y descubrí cómo dibujar formas y líneas, usando add_patch y add_line, respectivamente, a los ejes (creo). Así que ahora tengo esta salida que es absolutamente bien:

(No puede enviar imágenes hasta ahora !!) http://img137.imageshack.us/img137/7822/screenshot20100121at120.png

Pero me estoy haciendo esto usando la función pylab.show(), y lo que pienso Lo que quiero es lograr esto usando la función pylab.plot() para poder luego actualizarla a medida que progresa mi simulación usando pylab.draw() luego.

Mi código es el siguiente:

plab.ion() 

plab.axes() 

for circ in self.circleList: 
    plab.gca().add_patch(circ) 

for line in self.lineList: 
    plab.gca().add_line(line) 

plab.axis('scaled') 
plab.show() 

Dónde circleList y LineList son listas con los círculos y las líneas en el diagrama

probablemente estoy algo simple malentendido aquí, pero en realidad no puede encuentre ejemplos que no estén basados ​​abiertamente en gráficos que usen la función plot().


Aclaración:

¿Cómo puedo conseguir que la misma salida, utilizando pylab.plot() en lugar de pylab.show()?

Respuesta

4

Replicar su imagen utilizando el método de la gráfica:

from pylab import * 

points = [] 
points.append((-0.25, -1.0)) 
points.append((0.7, -0.7)) 
points.append((1,0)) 
points.append((0.7,1)) 
points.append((-0.25,1.2)) 
points.append((-1,0.5)) 
points.append((-1,-0.5)) 
points.append((-0.25, -1.0)) 

a_line = plot(*zip(*points))[0] 
a_line.set_color('g') 
a_line.set_marker('o') 
a_line.set_markerfacecolor('b') 
a_line.set_markersize(30) 
axis([-1.5,1.5,-1.5,1.5]) 

show() 

EDITAR basándose en las observaciones

Esto utiliza pitón multiprocesamiento biblioteca para ejecutar la animación matplotlib en un proceso separado. El proceso principal utiliza una cola para pasarle datos que luego actualiza la imagen de la gráfica.

# general imports 
import random, time 
from multiprocessing import Process, Queue 

# for matplotlib 
import random 
import numpy as np 
import matplotlib 
matplotlib.use('GTKAgg') # do this before importing pylab 

import matplotlib.pyplot as plt 
from matplotlib.patches import Circle 


def matplotLibAnimate(q,points): 

    # set up initial plot 
    fig = plt.figure() 
    ax = fig.add_subplot(111) 


    circles = [] 
    for point in points: 
     ax.add_patch(Circle(point,0.1)) 

    a_line, = ax.plot(*zip(*points)) 
    a_line.set_color('g') 
    a_line.set_lw(2) 

    currentNode = None 
    def animate(currentNode = currentNode): 
     while 1: 
      newNode = q.get() 
      if currentNode: currentNode.remove() 
      circle = Circle(newNode,0.1) 
      currentNode = ax.add_patch(circle) 
      circle.set_fc('r') 
      fig.canvas.draw() 

    # start the animation 
    import gobject 
    gobject.idle_add(animate) 
    plt.show() 

#initial points 
points = ((-0.25, -1.0),(0.7, -0.7),(1,0),(0.7,1),(-0.25,1.2),(-1,0.5),(-1,-0.5),(-0.25, -1.0)) 
q = Queue() 
p = Process(target = matplotLibAnimate, args=(q,points,)) 
p.start() 

# feed animation data 
while 1: 
    time.sleep(random.randrange(4)) 
    q.put(random.sample(points,1)[0]) 

Por supuesto, después de hacer esto, creo que estará mejor servido con la solución de imagen de whatnick. Crearía mi propia GUI y no usaría matplotlibs en el widget. Entonces "animé" mi GUI generando PNG e intercambiándolos.

+0

Mark, gracias por toda su ayuda. Para aclarar, para lo que necesito esto es para cambiar el color de los círculos a medida que se mueve un token (es decir, el que tiene el token puede ser rojo y el otro verde), lo maneja una biblioteca de simulación que se ejecuta en tiempo real . Sé que puede volver a dibujar tramas sobre la marcha utilizando el método pylab.draw() cuando el modo interactivo está activado (pylab.ion) pero no puede volver a dibujar una figura producida utilizando pylab.show(), solo una producida por pylab.plot() (¡Creo!) Así que necesito una forma de cambiar los colores del círculo individualmente antes de volver a dibujar. ¡Espero que eso tenga más sentido! Gracias –

+0

@Duncan, pylab.draw() bloquea el resto de la aplicación, para animar con ella pasas una función de devolución de llamada. Cómo se pasa la función depende de tu back-end. Por ejemplo, con la GTK predeterminada, usted llama a gobject.idle_add (animate); plt.show(). Creo que su principal problema es cómo mantener una simulación en ejecución (en un proceso o hilo separado) y actualizar la ventana de GTK al mismo tiempo. Trataré de encontrar un ejemplo. – Mark

+0

@Duncan, ver las ediciones de mi respuesta. – Mark

1

La técnica básica consiste en actualizar los datos de los elementos que se procesan utilizando set_data. Luego llama a draw(). Vea si sus elementos de círculo y línea tienen funciones set_data. De lo contrario, puede usar pyvtk. La otra opción es renderizar y guardar los trazados en archivos png y luego crear una animación a partir de ellos.

+1

para añadir a esta respuesta, poco hice algo como esto: he salvado todos mis parcelas y más tarde construyó una 'película' de ella, usando 'mencoder' –

+0

sé que hay una manera de hacerlo ' on the fly ': al activar el modo interactivo, puede llamar al método pylab.draw(), que redibujará la gráfica cada vez. Tengo una forma de alterar los datos, etc.ya (solo cambio el color de uno de mis círculos) Solo quiero saber, ¿cómo MOSTRAR los círculos y líneas en un diagrama usando pylab.plot(), no sé la sintaxis de pylab.plot() que le permite dibujar un gráfico estándar con algunas formas, sin gráfico ni nada. –

1

Suena como Mark tiene la respuesta que estabas buscando, pero si usted decide ir con el enfoque de whatnick y construir una animación a partir PNG individuales, aquí está el código para implementar la sugerencia de Amit usar mencoder (de http://en.wikibooks.org/wiki/Mplayer):

mencoder mf://*.png -mf w=400:h=400 -ovc lavc -lavcopts vcodec=xvid -of avi -o output.avi