plotting lines without blocking execution - python

I am using matplotlib to draw charts and graphs.
When I plot the chart using the command show() my code blocks at this command.
I would like to refresh my list of values with new data , and than refresh the image on the background. How to do that without closing each time the window with the graph?
Below is the code I am using
import pylab
a = (1,2,3,4)
pylab.plot(a)
pylab.show() # blocks here

In IPython started with -pylab it should not block.
Otherwise:
With ion() you turn the interactive mode on. show() does not block your system
anymore. Every draw() or plot(x, y) updated your plot.
ioff() turns interactive mode off. Useful if you add lots of data and don't
want to update every little detail.
See also: http://www.scipy.org/Cookbook/Matplotlib/Animations

If you are not using the IPython shell but instead running a program, you probably want to do:
pyplot.draw()
after a plot(), possibly followed by
raw_input("Press enter when done...")
so as to wait for the user before plotting something else.
If you do pyplot.ion() at the beginning of your program, doing draw() can often even be skipped.
pyplot.show() is actually an infinite loop that handles events in the main plotting window (such as zooming, panning, etc.).

On MacOS X i had the problem that unblocking only produced a white screen. In the end #tyleha's suggestion using %pylab directly in the note book helped.
In fact it's suggested when using the deprecated the -pylab flag:
bash:~/Projects/plyground $ python -m IPython notebook -pylab
WARNING: `-pylab` flag has been deprecated.
Use `--matplotlib <backend>` and import pylab manually.
[E 21:09:05.446 NotebookApp] Support for specifying --pylab on the command line has been removed.
[E 21:09:05.447 NotebookApp] Please use `%pylab` or `%matplotlib` in the notebook itself.

This works by invoking Ipython with the -wthread (or the -pylab) option. It will not block on show anymore.

Related

Spyder: refresh existing plot window instead of opening a new one

I want to show plots in a separate window. Currently I have the IPython graphics backend set to "automatic".
When I re-run the code (or plot another figure), Spyder opens a new plot window. Is it possible to refresh the figure in the window that is already opened instead of opening a new one?
The GUI window that opens when you call plt.show() is bound to a figure. You cannot change the figure inside it. (Well, to be precise, there might be an option of obtaining a handle from the operating system and manipulating its content, but I assume this is not worth the effort.)
Re-running the code actually means that you produce a new figure since the code does not know that it's been run before.
So, exchanging the figure or reusing the window to plot a different figure is not possible.
What is possible however is to use the figure and manipulate the figure while it's open. This is done via plt.ion(). After calling this command in IPython you can adapt the figure, e.g. adding new lines to it etc.
See this example:
At IN [6] the window opens and when IN [7] is executed, the figure stays open and the content changes.
Sure, it is possible with Spyder while in the same running kernel. Try the following example using num as parameter to plt.figure(), where num will always refer to the same figure and refresh it if already opened. Also works with plt.subplots().
import matplotlib.pyplot as plt
from scipy import *
t = linspace(0, 0.1,1000)
w = rand(1)*60*2*pi
fig = plt.figure(num=10, clear=True, figsize = [10,8])
plt.plot(t,cos(w*t))
plt.plot(t,cos(w*t-2*pi/3))
plt.plot(t,cos(w*t-4*pi/3))

PyDev Seaborn in Eclipse: "QPixmap: It is not safe to use pixmaps outside the GUI thread" on PyDev autocompletion popup

I'm getting the error
QPixmap: It is not safe to use pixmaps outside the GUI thread
when manually entering the following statements in Seaborn in the ipython-shell using PyDev in Eclipse:
import matplotlib.pyplot as mpl
import seaborn as sns
import pandas as pd
import numpy as np
# Turn interactive mode off:
mpl.ioff()
# Create some example Data:
df = pd.DataFrame({'A':np.random.rand(20),'B':np.random.rand(20)})
# Create seaborn PairGrid instance:
pg = sns.PairGrid(df)
At this point when I continue the last statement with a dot to e.g. chain a map()-method, like this:
pg = sns.PairGrid(df).
then Eclipse is trying to show a popup of all possible completions but that popup is immediatly getting closed and the console is getting filled with the aforementioned error, 42 lines of it to be precise.
I can continue and do this without problem:
gp = sns.PairGrid(df).map(mpl.scatter)
gp.fig.show()
And I get my plot just fine.
The same happens when doing sns.JointGrid(df.A,df.B). and sns.FacetGrid(df).
While playing around earlier I also got into situations where the console was actually killed by this error, I just can't replicate the steps that lead to this anymore.
Researching on this site it looked like it has to do with threading which I'm not using at all. Does Seaborn use it?
I want to create my plots by first creating a Grid/Figure and doing the plotting later, but this error suggests that this isn't a safe way to do things though the Seaborn doc says it's fine to do it like that:
https://seaborn.github.io/generated/seaborn.FacetGrid.html
EDIT:
When doing the same thing in Spyder I'm not getting the error but this warning when doing gp.fig.show():
C:\Anaconda2\lib\site-packages\matplotlib\figure.py:397: UserWarning:
matplotlib is currently using a non-GUI backend, so cannot show the figure
"matplotlib is currently using a non-GUI backend, "
When interactive mode is off I'm not seeing any graphic. With interactive mode on I'm still seeing the warning but get the graphic inline.
No popup in either case though. In Eclipse I'm getting both the error and the popup.
EDIT 2:
Running the whole thing as a script in Eclipse does not produce any error, only the manual entering like described above does.
I took a look at https://github.com/fabioz/Pydev/blob/master/plugins/org.python.pydev/pysrc/pydevconsole.py and the issue is that the code-completion on PyDev is being triggered in a secondary thread, not in the main (UI) thread.
I.e.: the code completion in the interactive console is not expecting that it'll touch code that'll actually interact with the gui.
For this to work, the completion command has to be queued for the main thread (as the regular commands are queued) and the thread has to wait for it to finish to then return its value.
Please report this as an issue in the PyDev tracker: https://www.brainwy.com/tracker/PyDev/ (i.e.: code-completion in the interactive console should happen in the UI thread).

matplotlib close does not close the window

I have noticed that when I run:
import pylab as pl
pl.ion()
# Plot something
pl.show()
pl.close()
The last statement does not fully close the Figure. The figure goes dark, and the contents go away, but the Figure stays on the screen until I exit IPython as shown below
I am using the latest stable version of matplotlib (1.3.1) using an Anaconda distribution, on Linux 64 bit, and I connect remotely using ssh -X.
The backend I am using is below:
backend : QT4Agg
backend.qt4 : PySide
you have to specify wich figure you want to close. In case you want to close all of them:
pl.close('all')
Also, there is a way to just clear but not close a figure:
pl.clf()
Also, seen below from another SO question:
Remember that plt.show() is a blocking function, so in the example code you used above, plt.close() isn't being executed until the window is closed, which makes it redundant.
You can use plt.ion() at the beginning of your code to make it non-blocking, although this has other implications.
You can also use the following lines after your plotting
#Your Plotting function
plt.waitforbuttonpress(0)
plt.close(fig)
The plt.waitforbuttonpress(0) will wait until a user input (Key press) is given. After that it will properly close the matplotlib window properly. It is very important to specify which figure to close.

plt.show() making terminal hang

At the end of the last function I call in one of my programs, I have the following code to plot a simple color plot.
plt.figure()
plt.pcolormesh(X,Y,Z)
plt.colorbar()
plt.show()
Afterwords I return to main and my program is complete. The plot displays as expected, however when I go to close it using the x button in the corner (on ubuntu), my program doesn't end. It just hangs there with a process running. How can I correct this?
your matplotlib might be running in non-interactive mode for some reason.
I am not sure how to prevent that in your local configuration but if you add either this:
plt.ion()
or this:
matplotlib.interactive(True)
somewhere at the beginning of your script, it should change the behaviour of your plots.
For interactive mode, You need this at the head of file:
import matplotlib
matplotlib.use("TkAgg")

Exact semantics of Matplotlib's "interactive mode" (ion(), ioff())?

The documentation for the "interactive mode" in Matplotlib's pyplot reads:
The interactive property of the pyplot interface controls whether a figure canvas is drawn on every pyplot command. If interactive is False, then the figure state is updated on every plot command, but will only be drawn on explicit calls to draw(). When interactive is True, then every pyplot command triggers a draw.
This seems clear enough: when the interactive mode is on, one can do plot() without having to do draw(). However, doing draw() in the following code does not do anything:
from matplotlib import pyplot as pp
# Interactive mode is off by default
pp.plot([10, 20, 50])
pp.draw()
raw_input('Press enter...') # No graph displayed?!!
(on Windows XP, Matplotlib 1.0.1).
Adding ion() at the beginning makes the figure(s) appear, while waiting for the user to type enter (which conveniently closes all the figures):
from matplotlib import pyplot as pp
ion()
pp.plot([10, 20, 50]) # No draw() is necessary
raw_input('Press enter...') # The graph is interactive *and* the terminal responds to enter
Thus, it looks like ion() does more than just adding automatic graph updates after each plotting command, and I unfortunately can't find anything in the documentation. Another, more important problem with the latter program is that ion() makes all plot commands update the graph, which is time consuming when a single graph is updated multiple times.
So, is there a way of:
having the terminal wait for enter, after which all the figures are automatically closed,
having interactive Matplotlib graphs,
… without forcing the interactive mode to be on at the beginning (so as to not force auto-updates of the graphs, which could be time consuming)?
Here is the summary of an interesting discussion on this subject in the Matplotlib mailing list. The executive summary is:
The interactive mode (activated with ion()) automates many things. In particular, pyplot.* commands automatically update on the screen the relevant axes. However, method calls on Matplotlib objects like ax.plot() (ax being an Axes object) do not normally perform automatic updates; in this case, pyplot.draw() performs the necessary update.)
The non-interactive mode is less convenient. draw() does not normally update the figure on screen. The fact that draw() is somewhat "inactive" in non-interactive mode is not mentioned in the current documentation, but will hopefully be included there soon.
In the mean time, more information on the interactive and non-interactive modes can be found in a current branch of Matplotlib. A better documentation for draw(), show() and friends can also be found in the same branch.
I would suggest that you follow the last comment of 'Thomas K'. I remember a similar question on the mailing list, but I couldn't find it after several minutes of searching. Sorry.
I had also this problem and the better easier way for me was/is to use ipython --pylab. I have a much older version of matplotlib installed which have some problems with ion(). Beside this, matplotlib had also some problems with draw() on Windows. Maybe it was fixed in the last versions.
p.s.: Sorry that I couldn't helped you really well.
Best regards.

Categories