Automatic Detection of Display Availability with Matplotlib

Automatic detection of display availability with matplotlib

You can detect directly if you have a display with the OS module in python.
in my case it's

>>> import os
>>> os.environ["DISPLAY"]
':0.0'

Why does this solve the 'no $DISPLAY environment' issue with matplotlib?

X11 follows a client/server model, where the X server accepts requests for graphical output from client applications (e.g. interactive matplotlib sessions), and sends back user input from the keyboard, mouse etc. In order for this model to work, client applications need to know which X server to send their requests to. This is controlled by the $DISPLAY environment variable. In the case where you are connecting to a remote X session (for example over an SSH connection), the $DISPLAY variable in your remote session needs to point to your local X server.

The $DISPLAY variable is structured like this:

hostname:displaynumber.screennumber

Not all parts may be present - the hostname is usually omitted for local sessions, and the screen number is also omitted if there is only one screen. In a local terminal session on laptop, my $DISPLAY looks like this:

alistair@laptop:~$ echo $DISPLAY
:0

Provided that the remote server also supports X11, it's possible to open graphical windows on the remote machine and have them appear on your local machine using X11 forwarding. For an SSH connection you do this by passing the -X (or -Y) flag.

For example:

alistair@laptop:~$ ssh -X alistair@workstation.address.co.uk
alistair@workstation:~$ echo $DISPLAY
localhost:10.0

The remote SSH server should take care of setting the $DISPLAY variable appropriately when you open the connection. In this particular case, localhost:10.0 is actually a 'proxy' X11 server running on the remote machine that listens on display 10 and relays commands to your local X server over the SSH connection (take a look at this if you're interested in the details).

Now you should be able to start a remote IPython session, import matplotlib using an interactive backend, and create plot windows which will then appear on your local machine. Since your keyboard/mouse input and the display output are now passing over an encrypted network connection, the plot windows will be less responsive than you're used to for a local session.

Another word of warning: if you have an IPython session open with an interactive matplotlib session running it is impossible to close the SSH connection without killing the IPython process. I also sometimes call matplotlib.use("Agg") before I start a long-running process that imports matplotlib - that way I can disconnect from the remote server without killing the process.

Generating matplotlib graphs without a running X server

@Neil's answer is one (perfectly valid!) way of doing it, but you can also simply call matplotlib.use('Agg') before importing matplotlib.pyplot, and then continue as normal.

E.g.

import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
fig.savefig('temp.png')

You don't have to use the Agg backend, as well. The pdf, ps, svg, agg, cairo, and gdk backends can all be used without an X-server. However, only the Agg backend will be built by default (I think?), so there's a good chance that the other backends may not be enabled on your particular install.

Alternately, you can just set the backend parameter in your .matplotlibrc file to automatically have matplotlib.pyplot use the given renderer.

UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure. when plotting figure with pyplot on Pycharm

Solution 1: is to install the GUI backend tk

I found a solution to my problem (thanks to the help of ImportanceOfBeingErnest).

All I had to do was to install tkinter through the Linux bash terminal using the following command:

sudo apt-get install python3-tk

instead of installing it with pip or directly in the virtual environment in Pycharm.

Solution 2: install any of the matplotlib supported GUI backends

  • solution 1 works fine because you get a GUI backend... in this case the TkAgg
  • however you can also fix the issue by installing any of the matplolib GUI backends like Qt5Agg, GTKAgg, Qt4Agg, etc
    • for example pip install pyqt5 will fix the issue also

NOTE:

  • usually this error appears when you pip install matplotlib and you are trying to display a plot in a GUI window and you do not have a python module for GUI display.
  • The authors of matplotlib made the pypi software deps not depend on any GUI backend because some people need matplotlib without any GUI backend.

In python, determine if display support only text or if graphics are available

I've put together a small function to detect if a graphic card exists on windows or linux, i.e.:

import subprocess, os

def gc_available():
if os.name == 'nt': # Windows
import wmi
try:
wmi.WMI().computer.Win32_VideoController()[0] # Tested on Windows 10
return 1
except:
pass

elif os.name == 'posix': # Linux
out = subprocess.getoutput('sudo lshw -c video | grep configuration') # Tested on CENTOS 7 and Ubuntu
if out:
return 1

Usage:

if gc_available():
print("VideoController available")
else:
print("VideoController Not available")

How do I check if I'm running on Windows in Python?

Python os module

Specifically for Python 3.6/3.7:

os.name: The name of the operating
system dependent module imported. The
following names have currently been
registered: 'posix', 'nt', 'java'.

In your case, you want to check for 'nt' as os.name output:

import os

if os.name == 'nt':
...

There is also a note on os.name:

See also sys.platform has a finer granularity. os.uname() gives
system-dependent version information.

The platform module provides
detailed checks for the system’s identity.

How do I get monitor resolution in Python?

On Windows:

from win32api import GetSystemMetrics

print("Width =", GetSystemMetrics(0))
print("Height =", GetSystemMetrics(1))

If you are working with high resolution screen, make sure your python interpreter is HIGHDPIAWARE.

Based on this post.



Related Topics



Leave a reply



Submit