Matplotlib window appears at the back? - python

Whenever I call show() in matplotlib the plot window appears behind all other windows and I have to minimize everything to see it. Is there any way I can prevent this or programmatically bring it to the front. On OSX Lion. Python 2.7

Well. This answer is presented in the comments to the accepted answer but I think it deserves to have a place as a separate one as it solves the issue nicely. Besides the author's problem I additionally had the problem that matplotlib window wasn't in the tray of active windows so I couldn't switch to it by <Alt>+<Tab>.
Changing of the matplotlib's default backend macosx solved everything. You can try immediately in your code like this:
import matplotlib
matplotlib.use("Qt5agg")
Qt5agg might not be presented in your system then please pick the one that is. You can find them:
import matplotlib.rcsetup as rcsetup
print(rcsetup.all_backends)
If it helped then you might want to change your backend in the configuration. For that locate it first:
import matplotlib
matplotlib.matplotlib_fname()
Then change backend: value:
backend : macosx
to your backend. I used in the end:
backend : TkAgg

Not exactly an answer to your question, but I'm using ipython instead of the default python console. When launched it with ipython --pylab I can plot e.g. by typing
>> plot([1,3,2])
and have the plot pop up in front. It also has some other very nice features ;)

Matplotlib developer's seem to be aware of this issue. But looking into https://github.com/matplotlib/matplotlib/issues/596 it looks like it's going to be a while until getting a solution, apparently because some people find it annoying that figure.show() "steals" screen space.

It may be OS-specific, but using interactive plotting (which plots as soon as you instruct) causes figures to come up in the foreground as soon as they're made on Ubuntu:
import pylab as P
P.ion()
P.figure(1)
P.plot([1,2,3],[1,4,9])

I have the same set-up as nickponline. What works for me is:
from pylab import get_current_fig_manager()
get_current_fig_manager().window.raise_()
If you have multiple figures, this only raises the currently active one. For that case, I found that the following works:
fig1=figure(1)
cfm1=get_current_fig_manager().window
fig2=figure(2)
cfm2=get_current_fig_manager().window
...
cfm1.activateWindow()
cfm1._raise()
pause(.1) # or something else that uses up some time
cfm2.activateWindow()
cfm2.raise_()

Related

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 show window as the active one

I'm plotting some graphs and then I interact with them using the canvas.mpl_connect commands. So when I show the plot, I want the window to be the active one since the beginning.
At the moment, when the script is run, the plot pops up but it's not the active window, the terminal still is (i.e. if I type a key, that is written in the Terminal, and not interpreted by the plot-window). I need to click on the plot-window to make it the active one and then I'm able to interact with the graphs. It would be way nicer if it was already active the first time it pops up.
Working on MacOSX 10.10.3 with python 2.7.5 and matplotlib 1.3.1
EDIT
I don't just need to bring the window in front, I want to be able to interact with the window without having to click on it. So if I type some keys, the graph will respond and not the terminal.
You can set the order windows are displayed in using canvas manager but it only works with some graphical backends. The following example uses the TkAgg backend which works but the same idea won't work the macosx backend.
import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt
from pylab import get_current_fig_manager
fig1 = plt.figure()
fig2 = plt.figure()
fig1.canvas.manager.window.attributes('-topmost', 1)
plt.show()
Figure 1 should show up on top of figure 2.
So, I've finally found a solution here https://github.com/matplotlib/matplotlib/pull/663
Apparently a work around is to import
from AppKit import NSApplication
and issuing just before show():
NSApplication.sharedApplication().activateIgnoringOtherApps_(True)
I'm not really sure what it does, and apparently it works just in non-interactive mode, but that worked perfectly for me.
You might also want to check here
https://github.com/matplotlib/matplotlib/issues/665/

reliably show matplotlib (0.99 to 1.3.1) figures without blocking

Is there any way to show a pyplot figure in Python 2.65, Matplotlib 0.99, without locking everything else?
I have a program with a Pmw GUI running on Python 2.75 with Matplotlib 1.3.1. on Windows (64-bit Winpython).
Everytime a figure is drawn (or everytime something is added to an existing one), the routine calls plt.show().
It is possible to show pyplot figures while allowing the user to keep using the GUI and manipulate the figures, nothing blocks anything, as I want it to be since I need the user to look at the plots when deciding what to do next in the GUI, and to have several plots next to each other for comparison.
Now, I need to make all of this work on a system with Python 2.65 and Matplotlib 0.99. The behaviour now seems to be that nothing is visible unless plt.show() is called, and then it will block everything until the plot window is closed.
I tried using plt.draw() instead but then the figure does not even show up.
Worse: Some routines who draw into existing figures never get a chance because they can't execute while the figure is being shown, and when they can, the figure is gone already. I cannot wait until the last drawing operation because the graphs are meant to build up incremental, adding information to existing graphs which the user needs to be able to see.
I am not allowed to update matplotlib. I am allowed to use non-binary parts of libraries if I make them part of "my" software package.
Ideally, I am looking for code that will work in both environments I'm working in, but at this point I am willing to make compromises...
Update:
I have found some code running in the same environment that is able to do all of these things, where I can remove the plt.show() calls, even run it in IDLE (which according to matplotlib docs has problems in these regards), and it "just works" -- I haven't been able to find any difference in how the two codes handle the task: Both define a figure.axes object, pass it to routines that draw into them (using plt.plot()) and store it for future use.
I've also found that my current code will change its behaviour on the current set of libraries, depending on how I run it: In a "regular" console in Spyder or a system console, all's fine, but on a dedicated console in Spyder, the first plot will lock up the interface
=> I'm beginning to think this isn't about the matplotlib version after all, but have no idea where else to look --is there anything else that changes matplotlib's behaviour, based on how it's launched?
It looks like you are looking for:
plt.show(block=False)
or plt.ion:
plt.ion()
plt.show()
# update figure, calc stuff
plt.pause()
Not really sure if they are available in 0.99.
elyase's answer sent me into the right direction:
import matplotlib
matplotlib.interactive(True)
This at the beginning of a script is what it takes to make sure that matplotlib will always and in all environments create plots in a way that allows scripts to continue running, while allowing the user to manipulate the figure and the code to keep drawing into it.
Matplotlib has two modes of operating: The interactive and the non-interactive, and my script going into the latter mode was the problem.
I have still no idea why this is the default behaviour in some cases and not in others (had believed it was one standard setting per matplotlib installation). Since other scripts are able to run without the above. and there must be something that my script inadvertently does to land in non-interactive mode, but the above code is what will override the setting, come what may; at least in all scenarios I've tried so far: python 2.75, matplotlib 1.3.1 using Spyder's regular and dedicated shells and system shells, and Py 2.65, matplotlib 0.99, using system shells and IDLE.
P.S.:
This does not seem to help on Linux. I tried to run the same skript (Tkinter GUI that opens plots, is able to draw into existing plots) on SuSE 13.1 (current version of python 2.7 and all libraries) and no single plot window pops up until the GUI is closed, and then they all jump at me ... it seems that it's not trivial to make matplotlib behave the same everywhere.

Example matplotlib.org does not work in Canopy

I am trying to make an animation with matplotlib in python (2.7) with 3 subplots. To see how this works I tried to understand the example on matplolib.org:
http://matplotlib.org/examples/animation/subplots.html
However when I run this program I only see one of the three plots displayed. Sometimes its the upper right one, sometimes the lower right one.
In my own code I also only see one of the three displayed. Does anyone know if this is a problem with Enthought Canopy and how to fix this?.
Solved, if you set in canopy: preferences > python > PyLab backend: interactive (wx), for some reason it works.

Matplotlib's GUI doesn't allow typing in save box?

I've been using matplotlib in python for some time now and I've finally gotten around to asking this question about an issue on my mac. When a plot shows up (after the plot() command, draw(), or show()), I have all the functionality I could want; I can move, zoom, etc. that I didn't do in the code.
When I go to save a figure with the view as I desire the save as box opens up and prompts for a filename. Anything I type appears in the terminal I used to execute the command! Selecting X11 and then typing has same result. Nothing seems to put the keyboards output into that box, but I can paste into the box using the mouse->Paste action and I can select files in the menu to overwrite and it works fine.
What's up with this?
Update:
The problem was wonderfully outlined and now has some solutions posted in this post: Why doesn't the save button work on a matplotlib plot?
Just installed matplotlib 0.99.1 on Python 2.6.2 on Snow Leopard and ran the following code:
from pylab import *
plot([1,2,3])
show()
Then, I fiddled around with the plot for a while and clicked the save button. The save dialog box popped up normally and allowed me to save (and type) fine. This was using the TkAgg backend. However, I did get this error:
2009-12-08 00:40:18.772 Python[728:60f] -deltaZ is deprecated for NSEventTypeMagnify. Please use -magnification.
Which seems to be something to do with Snow Leopard changing some APIs.
Sorry for using typing this as a post instead of a comment, but code tags aren't allowed in comments :(

Categories