I'm having issues with redrawing the figure here. I allow the user to specify the units in the time scale (x-axis) and then I recalculate and call this function
plots(). I want the plot to simply update, not append another plot to the figure.
result = collections.defaultdict(list)
for d in vlgaBuffSorted:
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:
plotCanvas = FigureCanvasTkAgg(f, pltFrame)
toolbar = NavigationToolbar2TkAgg(plotCanvas, pltFrame)
You essentially have two options:
Do exactly what you're currently doing, but call
graph2.clear() before replotting the data. This is the slowest, but most simplest and most robust option.
Instead of replotting, you can just update the data of the plot objects. You'll need to make some changes in your code, but this should be much, much faster than replotting things every time. However, the shape of the data that you're plotting can't change, and if the range of your data is changing, you'll need to manually reset the x and y axis limits.
To give an example of the second option:
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()
In case anyone comes across this article looking for what I was looking for, I found examples at
How to visualize scalar 2D data with Matplotlib?
http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop (on web.archive.org)
then modified them to use imshow with an input stack of frames, instead of generating and using contours on the fly.
Starting with a 3D array of images of shape (nBins, nBins, nBins), called
def animate_frames(frames): nBins = frames.shape frame = frames 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)
I also found a much simpler way to go about this whole process, albeit less robust:
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
Note that both of these only seem to work with
ipython --pylab=tk, a.k.a.
backend = TkAgg
Thank you for the help with everything.
This worked for me. Repeatedly calls a function updating the graph every time.
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" is a function that returns an integer. FuncAnimation will repeatedly call "update", it will do that "xmax" times.
All of the above might be true, however for me "online-updating" of figures only works with some backends, specifically
wx. You just might try to change to this, e.g. by starting ipython/pylab by
ipython --pylab=wx! Good luck!
I have released a package called python-drawnow that provides functionality to let a figure update, typically called within a for loop, similar to Matlab's
An example usage:
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)
This package works with any matplotlib figure and provides options to wait after each figure update or drop into the debugger.