2010-11-04 15 views
80

Tengo problemas para volver a dibujar la figura aquí. Permito al usuario especificar las unidades en la escala de tiempo (eje x) y luego recalculo y llamo a esta función plots(). Quiero que el argumento simplemente actualice, no agregue otro diagrama a la figura.¿Cómo actualizar una parcela en matplotlib?

def plots(): 
    global vlgaBuffSorted 
    cntr() 

    result = collections.defaultdict(list) 
    for d in vlgaBuffSorted: 
     result[d['event']].append(d) 

    result_list = result.values() 

    f = Figure() 
    graph1 = f.add_subplot(211) 
    graph2 = f.add_subplot(212,sharex=graph1) 

    for item in result_list: 
     tL = [] 
     vgsL = [] 
     vdsL = [] 
     isubL = [] 
     for dict in item: 
      tL.append(dict['time']) 
      vgsL.append(dict['vgs']) 
      vdsL.append(dict['vds']) 
      isubL.append(dict['isub']) 
     graph1.plot(tL,vdsL,'bo',label='a') 
     graph1.plot(tL,vgsL,'rp',label='b') 
     graph2.plot(tL,isubL,'b-',label='c') 

    plotCanvas = FigureCanvasTkAgg(f, pltFrame) 
    toolbar = NavigationToolbar2TkAgg(plotCanvas, pltFrame) 
    toolbar.pack(side=BOTTOM) 
    plotCanvas.get_tk_widget().pack(side=TOP) 
+0

posible duplicado de [tiempo real trazado en bucle while con matplotlib] (http://stackoverflow.com/questions/11874767/real-time-plotting-in-while-loop-with-matplotlib) –

Respuesta

97

Esencialmente tiene dos opciones:

  1. hacer exactamente lo que está haciendo actualmente, pero llaman graph1.clear() y graph2.clear() antes replotting los datos. Esta es la opción más lenta, pero más simple y más robusta.

  2. En lugar de volver a dibujar, puede actualizar los datos de los objetos de trazado. Tendrá que hacer algunos cambios en su código, pero esto debería ser mucho, mucho más rápido que repetir las cosas todo el tiempo. Sin embargo, la forma de los datos que está trazando no puede cambiar, y si el rango de sus datos está cambiando, tendrá que restablecer manualmente los límites del eje xey.

Para dar un ejemplo de la segunda opción:

import matplotlib.pyplot as plt 
import numpy as np 

x = np.linspace(0, 6*np.pi, 100) 
y = np.sin(x) 

# You probably won't need this if you're embedding things in a tkinter plot... 
plt.ion() 

fig = plt.figure() 
ax = fig.add_subplot(111) 
line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma 

for phase in np.linspace(0, 10*np.pi, 500): 
    line1.set_ydata(np.sin(x + phase)) 
    fig.canvas.draw() 
+0

Intenté probar "1" y el resultado fue que, después de volver a dibujar los datos, dibujé otro conjunto de gráficos en mi GUI, por lo que ahora tenía 4 gráficos después del recálculo, al igual que antes. – thenickname

+0

@thenickname - ¿Dónde exactamente en su código está llamando 'clear'? Deberías estar llamando a 'graph1.clear(); graph2.clear() 'dentro de su bucle' for', justo antes de llamar a 'graph1.plot (...)', 'graph2.plot (...)' etc ... –

+0

Ese for loop crea calles graphx. trama (...) N veces y poniendo las declaraciones claras allí solo traza la última. De hecho, he sacado el código del lienzo y lo puse en el ciclo principal del programa junto con el código de la figura y ahora hago que mi función sea llamada por un botón. Por alguna razón, si llamo a la función, las gráficas se actualizan, pero si presiono el botón, las gráficas no se actualizan. Es un comportamiento bastante interesante. Creo que debe ser un error en Tkinter. – thenickname

3

Todo lo anterior puede ser cierto, sin embargo para mí "-actualización en línea" de las cifras sólo funciona con algunos backends, específicamente wx. Tal vez intentes cambiar a esto, p. iniciando ipython/pylab por ipython --pylab=wx! ¡Buena suerte!

+1

Gracias por su mensaje, nunca utilicé el modo interactivo porque nunca funcionó con el motor predeterminado que utilicé. ¡Es mucho más agradable usar el modo interactivo que detener la ejecución cada vez que quieras ver un gráfico! – PierreE

+0

Ninguna de las otras respuestas me ayudó en mi caso. Estoy usando pycharm y el problema fue con el trazado y la interactividad de la consola. Necesitaba agregar From pylab import * y luego ion() en el cuerpo del código para activar interactivo. Funciona sin problemas ahora para mí. – shev72

8

En caso de que alguien viene a través de este artículo en busca de lo que estaba buscando, encontré ejemplos en

How to visualize scalar 2D data with Matplotlib?

y

http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop (on web.archive.org)

luego modificado para utilizar imshow con una pila de entrada de marcos, en lugar de generar y usar contornos sobre la marcha.


A partir de una serie de imágenes en 3D de forma (nBins, nBins, nBins), llamado frames.

def animate_frames(frames): 
    nBins = frames.shape[0] 
    frame = frames[0] 
    tempCS1 = plt.imshow(frame, cmap=plt.cm.gray) 
    for k in range(nBins): 
     frame = frames[k] 
     tempCS1 = plt.imshow(frame, cmap=plt.cm.gray) 
     del tempCS1 
     fig.canvas.draw() 
     #time.sleep(1e-2) #unnecessary, but useful 
     fig.clf() 

fig = plt.figure() 
ax = fig.add_subplot(111) 

win = fig.canvas.manager.window 
fig.canvas.manager.window.after(100, animate_frames, frames) 

También he encontrado una manera mucho más sencilla de ir sobre todo este proceso, aunque menos robusta:

fig = plt.figure() 

for k in range(nBins): 
    plt.clf() 
    plt.imshow(frames[k],cmap=plt.cm.gray) 
    fig.canvas.draw() 
    time.sleep(1e-6) #unnecessary, but useful 

Tenga en cuenta que ambos éstos sólo parecen trabajar con ipython --pylab=tk, también conocido como backend = TkAgg

Gracias por la ayuda con todo.

5

He lanzado un paquete llamado python-drawnow que proporciona la funcionalidad para permitir una actualización de la figura, normalmente llamada dentro de un bucle for, similar al drawnow de Matlab.

Un ejemplo de uso:

from pylab import figure, plot, ion, linspace, arange, sin, pi 
def draw_fig(): 
    # can be arbitrarily complex; just to draw a figure 
    #figure() # don't call! 
    plot(t, x) 
    #show() # don't call! 

N = 1e3 
figure() # call here instead! 
ion() # enable interactivity 
t = linspace(0, 2*pi, num=N) 
for i in arange(100): 
    x = sin(2 * pi * i**2 * t/100.0) 
    drawnow(draw_fig) 

Este paquete funciona con cualquier figura matplotlib y proporciona opciones que esperar después de cada actualización figura o caer en el depurador.

+1

¿Cómo es robusto e inestable al mismo tiempo? – BlueMoon93

+1

Quise decir robusto como en "funciona con cualquier figura matplotlib" e inestable como en "proyecto de fin de semana". He actualizado mi respuesta – Scott

12

Esto funcionó para mí. Repetidamente llama a una función actualizando el gráfico cada vez.

import matplotlib.pyplot as plt 
import matplotlib.animation as anim 

def plot_cont(fun, xmax): 
    y = [] 
    fig = plt.figure() 
    ax = fig.add_subplot(1,1,1) 

    def update(i): 
     yi = fun() 
     y.append(yi) 
     x = range(len(y)) 
     ax.clear() 
     ax.plot(x, y) 
     print i, ': ', yi 

    a = anim.FuncAnimation(fig, update, frames=xmax, repeat=False) 
    plt.show() 

"fun" es una función que devuelve un número entero. FuncAnimation repetidamente llamará "actualizar", hará ese "xmax" veces.

+0

¿Podría dar un ejemplo de cómo llama a esta función (especialmente cómo pasa una función en una llamada a función) y cómo funciona la función fun()? – bjornasm

+1

Claro. "fun()" es cualquier función que devuelve un número entero. Puede pasar la función como argumento a otra como esta: "plot_cont (my_function, 123)". Ahí lo tienes me llama plot_cont en la línea 86: https://github.com/vitobasso/audio-ml/blob/bbb3f633ef3638406912d6f75a8c6a7311aea3fc/src/train_spec.py – Vituel

-1
import csv 
import sys 
import getopt 
import socket 
import time 
import numpy as np 
import matplotlib 
from scipy.misc import imread 
from matplotlib import pyplot as plt 
import warnings 
fig, ax = plt.subplots() 
ax.set_xlim(-158, 553) 
ax.set_ylim(-290, 733) 
im = plt.imread("") 
plt.imshow(img, zorder=0, extent=[0.5, 8.0, 1.0, 7.0]) 

fig.show() 
l_global=[] 
points=[] 
master_tag_csvlink='c:/logfolde.log.csv' 
csvfile=open(master_tag_csvlink, 'r') 
for ainfo in csvfile: 
     line= ainfo 
     l_list= list(line.split('_')) 
     l_local=[] 
     for i in range(int(l_list[0])): 
      l_local.append(list(l_list[i+1].split(','))) 
     function1= lambda x,i: x[i] # return list[n,X] of elements at x 
     c= lambda x,l: [x for i in range(l) if True] 
     for i in range(len(l_local)): 
      l_local[i][1],l_local[i][2]=int(l_local[i][1]),int(l_local[i][2]) 

     if l_global: #In begining l_glocal is empty, so just copy the data in to l_global 
      l_global=l_local[:] 
      for i in range(len(l_global)): 
       points.append(plt.plot(function1(l_global[i],1),function1(l_global[i],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2)))) 



     else: # compare the l_local & l_global for any updates 
      tag_Id=map(function1,l_local,c(0,len(l_local))) #list of list of tagId,x,y TagId is filtered - local 
      mTag_Id=map(fuction1,l_global,c(0,len(l_global))) #list of list of tagId,x,y TagId is filtered - master 

      for i in mTag_Id: 
       if i not in tag_Id: #comparing master tags and tag_Id's 
        index=mTag_Id.index(i) ############### Tags in master list but not in Tag_id 
        copy_point=l_global[index] 
        [removing_point]=points[index]######## means tag is in-active ,turn tag color into red 
        removing_point.remove() 
        del points[index] 

        points.insert(index,plt.plot(function1(l_global[index],1),function1(l_global[index],2),'r',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2)))) 

       elif i in tag_Id: # append the tag into l_global 
        index=mTag_Id.index(i) ############### Tags in master list but not in Tag_id 
        l_global[index]=l_local[index][:] 
        [removing_point]=points[index]######## means tag is active update coordinates 
        removing_point.remove() 
        del points[index] 
        points.insert(index,plt.plot(function1(l_global[index],1),function1(l_global[index],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2)))) 
      for i in Tag_Id: 
       if i not in mTag_Id: 
        index=Tag_Id(i) 
        l_global.append(l_local[index]] 
        points.append(plt.plot(function1(l_global[-1],1),function1(l_global[-1],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2)))) 

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

# x = np.linspace(0, 6*np.pi, 100) 
# y = np.sin(x) 

# # You probably won't need this if you're embedding things in a tkinter plot... 
# plt.ion() 

# fig = plt.figure() 
# ax = fig.add_subplot(11)1 
# line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma 

# for phase in np.linspace(0, 10*np.pi, 500): 
    # line1.set_ydata(np.sin(x + phase)) 
    # fig.canvas.draw() 
+0

¿Esto añade nada a las cinco respuestas que se han publicado ya ? Si es así, sugeriría editarlo para reducir el código al mínimo necesario para mostrarlo. Bienvenido al sitio, por cierto. – user2699

Cuestiones relacionadas