Matplotlib: display plot on a remote machine - python

I have a python code doing some calculation on a remote machine, named A. I connect on A via ssh from a machine named B.
Is there a way to display the figure on machine B?

Sure, you can enable X11 forwarding. Usually this is done by passing the -X or -Y option to ssh when you connect to the remote computer
ssh -X computerA
Note that the SSH daemon on computer A will also have to be configured to enable X11 forwarding. This is done by putting
X11Forwarding yes
in computer A's sshd_config configuration file.
If computer A's SSH daemon does not have X11 forwarding enabled, you can always have Python write the result of the calculation to a text file, download it to computer B, and use Matplotlib locally.

If you use matplotlib on Mac OS X on the remote machine (B), you must first make sure that you use one of the X11-based display back-ends, since the native Mac OS X back-end cannot export its plots to another display. Selecting a back-end can be achieved with
import matplotlib
matplotlib.use('GTK') # Or any other X11 back-end
The list of supported back-ends can be obtained by giving use() an incorrect back-end name: matplotlib then prints an error message listing the possible back-ends.
ssh X11 forwarding can then be used to display matplotlib plots.

The following worked for me using Mac OS X on the local machine (machine B) and ubuntu on the remote (machine A).
You need X11 server installed on your local machine to do this.
If you're running a recent version of Mac OSX (OS X Mountain Lion or newer), it would NOT have come with X11 pre-installed (see http://support.apple.com/kb/ht5293). Check if you have X11 by opening up Mac terminal, and run command xterm.
If an X11 window opens up, you're all set. If it says command not found, then go to http://xquartz.macosforge.org/landing/ and install X11 server. Then logout and log back in to your mac.
After you log back in, try to run xterm command again. It should open up X11 window.
At this point your $DISPLAY variable should also be set correctly. If it's not set, make sure you've logged in/out since installing X11 from XQuartz.
echo $DISPLAY
/tmp/launch-I9I3aI/org.macosforge.xquartz:0
Then from your local machine, use ssh -X to remote into remote machine A:
ssh -X user#machineA
Then on the remote machine:
python
>>> import matplotlib
>>> matplotlib.use('GTKAgg') #I had to use GTKAgg for this to work, GTK threw errors
>>> import matplotlib.pyplot as plt #... and now do whatever you need...
Make sure you call matplotlib.use BEFORE importing anything else from matplotlib (e.g. matplotlib.pyplot)
Other useful troubleshooting tips on using ssh -X : http://oroborosx.sourceforge.net/remotex.html#usessh

GTK seems impossible to get working on Ubuntu with Python3. Instead, I used tkagg (from this answer):
import matplotlib
matplotlib.use('tkagg')
import matplotlib.pyplot as plt
Test that it's working with this:
import matplotlib
matplotlib.use('tkagg')
import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
plt.show()

I have used IPython to solve the related problem. The steps are as follows:
Step 1: Install IPython and Jupyter in the remote machine (A) locally (assuming no root privilege) using the following commands:
pip install --user ipython
pip install --user jupyter
Update matplotlib:
pip install --user -U matplotlib
Step 2:
Run Jupyter with no browser from the code directory in the remote machine (A):
cd PATH/TO/THE/CODE
jupyter notebook --no-browser --port=8080
After this command, a URL will be given something similar to below:
http://localhost:8080/?token=5528ab1eeb3f621b90b63420f8bbfc510edf71f21437c4e2
Step 3:
Now open another terminal in the local machine (B) and connect to the remote machine (A) using ssh:
ssh -N -L 8080:localhost:8080 user_id#remote.host
The port number has to be same in step 2 and step 3. In this example, the port number is 8080.
Step 4:
Copy and paste the URL in the step 3 to a browser in your local machine (B).
Now, the notebook in the remote machine can be used through the browser and plot can be generated using the data in the remote machine.

export MPLBACKEND="agg" this worked for me.
obviously you can set it via code as well.

if that doesn't work you could also try:
import matplotlib.pyplot as plt
plt.switch_backend('agg')
or
import matplotlib.pyplot as plt
plt.switch_backend('TkAgg')
this seemed to work for me
Yet, if you are trying to get a GUI working I suggest you look at this link: http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

Just wanted to add - if you're on Windows as the local machine, make sure you've set up Xming (an X Windows server) and Putty so you can see the remote Linux graphical applications.
I followed the instructions from here: http://laptops.eng.uci.edu/software-installation/using-linux/how-to-configure-xming-putty to do this. It also sets your display environment and variable so you don't get an error when using tkagg as the backend.

You can use the library I created to solve this problem https://pypi.org/project/remote-plot/.
It uses the exact same API as matplotlib, but it renders the plots in a web browser which you can view from your machine B.
Install by:
pip install remote_plot
And then run in python like this:
from remote_plot import plt
plt.plot([1, 2, 3], [4, 5, 6])
By default it opens the rendering on port 8000 but you can modify this easily. If you are connecting via ssh, don't forget to forward the port by adding the following flag to your ssh command:
ssh YOUR_USER_NAME#YOUR_MACHINE_IP -L 8000:localhost:8000

If you're using a mac as a client machine, try this.
You basically need to make sure two things are working properly.
Using GTK or Cairo as matplotlib's backend.
Forwarding the display.
Using GTK or Cairo as matplotlib's backend
If you're using python3, you must install cairocffi.
pip install cairocffi
Then use the GTK3Agg as a backend of matplotlib.
import matplotlib
matplotlib.use('GTK3Agg')
import matplotlib.pyplot as plt
See following description from matplotlib document for more detail.
Both GTK2 and GTK3 have implicit dependencies on PyCairo regardless of
the specific Matplotlib backend used. Unfortunatly the latest release
of PyCairo for Python3 does not implement the Python wrappers needed
for the GTK3Agg backend. Cairocffi can be used as a replacement which
implements the correct wrapper.
Forwarding the display
Install launch the latest version of XQuartz.
Connect to the remote server using ssh -X. ex) ssh username#ipaddress -X

This is what I did with MacOS and a Linux remote machine.
In ~/.ssh/config I added the following. I add this since it's possible that your machine might not be taking the xauth location properly.
XAuthLocation /opt/X11/bin/xauth
ssh -Y machine_name
Ran the following dummy program:
import matplotlib.pyplot as plt
x = [1,2,3]
y = [2,4,1]
plt.plot(x, y)
plt.show()

Related

Is there any way to show figures in VScode remote ssh (windows)

vscode was installed in my windows computer, I use ssh remote service
and when I tried to plot a figure, the figure just did not show up.
e.g.,
the code as follows
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-10,10,100)
y = np.sin(x)
plt.plot(x,y)
plt.show()
when I run the code in the remote ssh, the figure didn't show up.
(ps, the code works in my local computer)
Yes its completely possible, but it requires the x11 Forwarding option.
In your ssh config file, add "ForwardX11 Yes"
Host myHost
Hostname 192.168.1.1
ForwardX11 Yes
Now the tricky part: the remote computer has to allow the forwarding (usually disabled by default).
On the remote host, go to the sshd_config file (usual location is /etc/ssh/sshd_config)
And make sure that the option
X11Forwarding yes
is present and that its NOT commented out.
Now whenever you ssh into that host, you should be able to run any graphical application from your windows computer
Here are two options (which I think require the Jupyter extension to be installed remotely...someone correct me if I'm wrong and I'll edit this answer).
Option 1: Display figures generated by a .py file
Using VScode with the Remote - SSH extension to connect to a remote server, you can right-click in the file text area and select Run Current File in Interactive Window. This will show plots in what looks to me like a iPython or jupyter notebook type window.
For example, if you have basic_plot.py with the following:
import matplotlib.pyplot as plt
x = [i for i in range(100)]
y = [10*i for i in x]
plt.plot(x,y, '-x')
With basic_plot.py open in VScode for editing, right-click & select Run Current File in Interactive Window. This will open a window like below
Option 2: Display pyplot figures by writing code in iypthon/jupyter notebook style interactive window
Open the VScode command palatte (either via the View menu or `Ctrl+Shift+P').
Type "Create Interactive Window" in the command palette.
Select "Jupyter: Create Interactive Window".
An interactive window (like in the pic from option 1 above) will appear where you can write and execute
python code like in ipython or jupyter notebook.
I struggled with the same problem so I created a library to solve this here https://pypi.org/project/remote-plot/.
It doesn't require X11 forwarding / having a display.
It uses the exact same API as matplotlib (and actually uses matplotlib to plot stuff), but it renders the plots in a web browser which you can view from your local machine.
Install by:
pip install remote_plot
And then run in python like this:
from remote_plot import plt
plt.plot([1, 2, 3], [4, 5, 6])
By default it opens the rendering on port 8000 but you can modify this easily. If you are connecting via ssh, don't forget to forward the port by adding the following flag to your ssh command:
ssh YOUR_USER_NAME#YOUR_MACHINE_IP -L 8000:localhost:8000

Configuring macOS PyCharm for X11 Forwarding

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
x = np.linspace(1,1000)
plt.plot(np.linspace(1, 1000))
print("Works")
plt.show()
I am trying to run the simple code above within PyCharm on a remote machine, but showing the plots on my local machine (mac). The plot does not appear. I do have xQuartz X11 Server running.
Pycharm runs the remote interpreter fine.
If I run it from macOS terminal, using
ssh -X pier#129.168.0.181
python test.py
plt.show() works.
I reckon that the missing piece is the -X which enables the X11 to be forwarded to my local machine.
Where do I include this with PyCharm's command to ssh? I'm spending too much time trying to figure this out...
Note: I'm also not able to use PyCharm's Python Console to do plotting. No errors are shown but the plot is not forwarded to my local machine.
Ok, I found I needed to do two things to get it working well enough for me :
(1) Set DISPLAY = localhost:10.0 in the Environment Variables under Build, Execution, Deployment -> Python Console
(2) Right after
import matplotlib
matplotlib.use('Qt5Agg')
With this, I can use the remote interpreter as if it were local.
Building of #Ippiers answer, on windows this works via:
install xming (and have it running)
run a putty session with X11 forwarding enabled
env on the putty session and check the DISPLAY variable, it will probably be localhost:10.0
Set this display variable in pycharms run configuration DISPLAY=localhost:10.0
matplotlib.use('TkAgg') as Qt5 gave me errors

Remote Debugging with Pycharm, Unable plot figure on local machine

My local machine and remote server are both Ubuntu. And I have succeed setting remote debugging in pycharm, all things work well excepting plotting figure.
I tried matplotlib but always failed to install pygtk or gtk package in conda py27 environment.
I also tried ssh -x and it works well in terminal. I can see figures on my local machine. But it is not convenient to work on both pycharm and terminal.. I didn't find where can set '-x' argument in pycharm, is it possible to do that? The codes always broke by errors no 'DISPLAY' Variable.
_tkinter.TclError: no display name and no $DISPLAY environment variable
I have checked "ForwardX11 yes". I tried to add 'DISPLAY' in pycharm environment, by setting "DISPLAY my_local_ip:0.0" but the program just suspend at the plotting step. it seems the figure has been plot somewhere? just not my local machine....
Any one know how to deal with such issues?
Test code:
from __future__ import print_function
import os
print("Display is: %s" % (os.environ['DISPLAY']))
import matplotlib
print("Default backend is: %s",matplotlib.get_backend())
matplotlib.use('TkAgg')
print("Backend is now: %s",matplotlib.get_backend())
from matplotlib import pyplot
pyplot.ioff()
pyplot.plot([1, 2, 3])
pyplot.show()

Matplotlib is hanging when using python3

Matplotlib hangs now that I've upgraded to Sierra.
The behavior is different depending on how I run it.
In a file (running with %run <filename> inside of ipython or python <file name> from the terminal):
The terminal will hang on import (import matplotlib.pyplot as plt) and all I get is the little rocket icon bouncing in my dock.
Directly from ipython:
I can import it and show a plot, but it will hang once I try to close the figure window. Doing this from inside of the basic python shell does not have this problem. So it seems running in interactive mode also causes hanging.
Has anyone experienced something similar?
python version: 3.5.2
matplotlib version: 1.5.1
backend: MacOSX
OSX: 10.12.2
Switching to a TkAgg backend will display the figure window, but it will hang on plotting (in interactive mode).
Note
Setting up a virtual environment to run python 2.7 with a TkAgg backend works as expected
Seems to be a caching issue:
running:
cd ~/.matplotlib
fc-list
fixed the problem (same issue discussed here: import matplotlib.pyplot hangs but the symptoms were a little different)

TclError: no display name and no $DISPLAY environment variable on EC2

I'd like to use iPython on an Amazon EC2 (Linux AMI). I've installed Anaconda and started iPython to test out some scripts I've already created. Right now I am only interested in running it in Terminal (not as Notebook).
At the beginning of my code I always do:
import json
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
However, I tried CTRL + C from my text editor and then using %paste in Terminal I get the error:
TclError: no display name and no $DISPLAY environment variable
If I try to ssh -X name#host as per this suggestion No display name and no $DISPLAY environment variable using tkinter through ssh, I get:
/opt/X11/bin/xauth: file /Users/adrianp/.Xauthority does not exist
Warning: untrusted X11 forwarding setup failed: xauth key data not generated
X11 forwarding request failed on channel 0
To fix that issue I tried https://superuser.com/questions/249045/x11-forwarding-from-amazon-ec2-ami but still got a warning:
Warning: untrusted X11 forwarding setup failed: xauth key data not generated
And the same error:
TclError: no display name and no $DISPLAY environment variable
Per this suggestion Generating a PNG with matplotlib when DISPLAY is undefined (which seems irrelevant but I've tried everything) I did:
import matplotlib
matplotlib.use('Agg')
before importing anything else and still get the same error.
Any ideas on how to solve this problem? I'd really like to use the paste magic function to input functions/etc.
This is more of a linux/X11 issue than a python question. Also, this process will probably be overkill - you'd be better just running ipython locally or launching a web notebook.
Anyway, you should:
install tigervnc
run vncserver (since this is an internet-facing server, use a secure passphrase or block the port in the firewall)
install tk (I think you have already done this)
edit sshd_config (most likely /etc/ssh/sshd_config) and enable
X11Forwarding (X11Forwarding yes).
login to your server passing the -Y option to ssh (ssh -Y user#server)
You should then be able to start ipython and use %paste.

Categories

Resources