In matplotlib, is there a simple way of plotting a figure without interrupting the control flow of the script?
Using pseudocode for clarity, here’s what I’m trying to achieve:
fig1 = figure()
fig1.plot_a_figure(datasets)
for dataset in datasets:
results = analyze(dataset) # this takes several minutes
update(fig1)
pop_up_another_figure(results) # would like to have a look at this one
# while the next dataset is being processed
Of course, I can just savefig() these intermediate figures, but I only need a quick glance at a them and it would be the best to have them just pop up on the screen in real time.
EDIT: A runnable example:
#!/usr/bin/python
import pylab as plb
import matplotlib.pyplot as plt
fig1=plt.figure(1)
ax = fig1.add_subplot(1,1,1)
ax.plot([1,2,3],[4,5,6],'ro-')
#fig1.show() # this does not show a figure if uncommented
plt.show() # until the plot window is closed, the next line is not executed
print "doing something else now"
Am I missing something very very basic?
First things first, don’t forget a simple alternative is to just make new figure windows with
plt.figure(2),plt.figure(3)etc. If you really want to update the existing figure window, you had better keep a handle on your lines object withAnd then later you would be doing something like:
As for the real meat of the question, if you’re still battling with this read on..
You need to enable interactive mode if you want
plt.show()to be non-blocking. To modify your runnable example so that “doing something else now” would print immediately, as opposed to waiting for the figure window to be closed, the following would do:However, this is just scratching the surface of things – there are many complications once you start wanting to do background work while interacting with the plots. This is a natural consequence of painting with what’s essentially a state machine, it doesn’t rub well with threading and programming in an object-oriented environment.
Queueshould be used to pass input data and get results out of the worker functions in a thread-safe way.draw()in the worker thread so you also need to set up a way to schedule a repaint.TkAggseems to be the only one which works 100% (see here).The easiest and best solution is not to use the vanilla python interpreter, but to use
ipython -pylab(as ianalis has rightly suggested), because they have already figured out most of the tricks needed to get interactive stuff working smoothly. It can be done withoutipython/pylabbut it’s a significant amount of extra work.Note: I still often like to farm off worker threads whilst using ipython and pyplot GUI windows, and to get threading working smoothly I also need to use another commandline argument
ipython -pylab -wthread. I’m onpython 2.7.1+withmatplotlib v1.1.0, your mileage may vary. Hope this helps!Note for Ubuntu users: The repositories are still back on v0.99 for quite some time now, it is worth upgrading your
matplotlibbecause there were many improvements coming up to the v1.0 release including a Bugfix marathon, and major changes to the behaviour ofshow().