Open a Matplotlib figure through SSH tunnel of vscode
Asked Answered
A

6

20

I am setting up a remote workstation to run machine learning related python code from my laptop on another computer that includes a GPU.

I use the SSH remote feature of vscode to remotely run and debug my code and I am very happy with the interface. However, I am not able to generate figures coming from the "matplotlib" library.

I tried to modify some matlplotlib options, but it was unsucessful :

import matplotlib
matplotlib.use('Agg')

As instructed in : _tkinter.TclError: no display name and no $DISPLAY environment variable

In short my problem emerges with the following example code :

import numpy as np
from matplotlib import pyplot as plt 

x = np.linspace(0,1,101)
y = x ** 2

plt.close()
plt.figure()
plt.plot(x,y)
plt.show()
~/vscode$ cd /home/*/vscode ; env PYTHONIOENCODING=UTF-8 PYTHONUNBUFFERED=1 /usr/bin/python3 /home/*/.vscode-server/extensions/ms-python.python-2019.6.24221/pythonFiles/ptvsd_launcher.py --default --client --host localhost --port 39903 /home/*/vscode/test_plot.py 
Traceback (most recent call last):
  File "/home/*/.vscode-server/extensions/ms-python.python-2019.6.24221/pythonFiles/ptvsd_launcher.py", line 43, in <module>
    main(ptvsdArgs)
  File "/home/*/.vscode-server/extensions/ms-python.python-2019.6.24221/pythonFiles/lib/python/ptvsd/__main__.py", line 434, in main
    run()
  File "/home/*/.vscode-server/extensions/ms-python.python-2019.6.24221/pythonFiles/lib/python/ptvsd/__main__.py", line 312, in run_file
    runpy.run_path(target, run_name='__main__')
  File "/usr/lib/python3.6/runpy.py", line 263, in run_path
    pkg_name=pkg_name, script_name=fname)
  File "/usr/lib/python3.6/runpy.py", line 96, in _run_module_code
    mod_name, mod_spec, pkg_name, script_name)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/*/vscode/test_plot.py", line 8, in <module>
    plt.figure()
  File "/usr/lib/python3/dist-packages/matplotlib/pyplot.py", line 539, in figure
    **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/backend_bases.py", line 171, in new_figure_manager
    return cls.new_figure_manager_given_figure(num, fig)
  File "/usr/lib/python3/dist-packages/matplotlib/backends/backend_tkagg.py", line 1049, in new_figure_manager_given_figure
    window = Tk.Tk(className="matplotlib")
  File "/usr/lib/python3.6/tkinter/__init__.py", line 2023, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable

Thanks a lot for helping me !

Anticipant answered 22/7, 2019 at 19:43 Comment(2)
Answers in the linked post may not go into enough detail, so maybe this helps more.Slipway
@Slipway I managed to read several docs starting from your link and my problem seems to be that the ssh -X in the command line of Windows is not setting the $DISPLAY variable. It is very strange since it works all well with Putty but not in the command line and I do not see whyAnticipant
A
15

I managed to solve the problem by running a parallel Putty ssh connection with X11 forwarding enabled and by writing export DISPLAY=localhost:10.0 in the terminal of vscode before launching a python script.

However, I have safety concerns and I wonder why I have to manually do these commands in order for it to work... Any insight would be much appreciated !

Anticipant answered 23/7, 2019 at 14:22 Comment(3)
Note: you should use export DISPLAY=localhost:10.0 instead of export $DISPLAY=loalhost:10.0. When setting env vars, $ is not required and should be avoid.Ongoing
For more details, people should refer to this answer https://mcmap.net/q/662867/-python-plotting-on-remote-server-using-pycharmOngoing
Some similar advice: wiki.ros.org/docker/Tutorials/GUIGatefold
D
16

I found a slight variation of a previous answer to work very well.

Save the plot as .png instead of plotting it.

plt.savefig("dummy_name.png")

The previous answer then suggests moving the file through scp. I instead suggest to open dummy_name.png with Visual Code, no need to write commands and it automatically refreshes the image whenever you plot something else. I tested this from USA with SSH into a server in Europe, the images refreshed in less than half a second.

Detroit answered 24/1, 2020 at 0:37 Comment(1)
this is a helpful comment but not an answer to the questionTeocalli
A
15

I managed to solve the problem by running a parallel Putty ssh connection with X11 forwarding enabled and by writing export DISPLAY=localhost:10.0 in the terminal of vscode before launching a python script.

However, I have safety concerns and I wonder why I have to manually do these commands in order for it to work... Any insight would be much appreciated !

Anticipant answered 23/7, 2019 at 14:22 Comment(3)
Note: you should use export DISPLAY=localhost:10.0 instead of export $DISPLAY=loalhost:10.0. When setting env vars, $ is not required and should be avoid.Ongoing
For more details, people should refer to this answer https://mcmap.net/q/662867/-python-plotting-on-remote-server-using-pycharmOngoing
Some similar advice: wiki.ros.org/docker/Tutorials/GUIGatefold
N
3

For an easy configuration, you have 2 options :

  1. Plot without showing and transfer picture file through SSH

This option consists in replacing plt.show() with

plt.savefig('foo.png')
plt.savefig('foo.pdf')

More information on saving matplotlib plots

After that, you can transfer this figure with scp

scp [email protected]:/path/to/foo.png /local/directory
  1. Use Jupyter Notebook

You can easily plot into a Jupyter Notebook. Here is a tutorial on how to setup a Raspberry Pi through ssh to create a remote server for Jupyter Notebook.

On Jupyter Notebook, you need to add on the first line of your notebook, before importing matplotlib, to plot your image after cell.

%matplotlib inline
Nowt answered 22/7, 2019 at 19:58 Comment(1)
Thanks a lot for your response, writing matplotlib.use('agg') and plt.savefig('foo.png') allows to avoid the error and save the picture. This is a nice temporary fix. For my use, I cannot consider a notebook unfortunately.Anticipant
B
3

Another approach is to use Tensorboard, which is now available via an extension in VS code. You can save your image or plot (as well as other types of data) and immediately view it through the Tensorboard interface in a VS code tab. I use this all the time via ssh. However, you do need Tensorflow or Pytorch to do this.

Here's an example in Pytorch for an image in numpy.array or torch.Tensor format. Make sure to launch your Tensorboard session first.

from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter('log_dir')    

# for some image "im"
writer.add_image('My image', im, 0)
write.close()

Here's an example for matplotlib figures:

def examplePlot(data):
    fig = plt.figure()
    # do some plotting
    return fig

writer.add_figure('My plot', examplePlot(data), 0)
writer.close()

Refresh your Tensorboard and you should see it right away.

Bueno answered 25/8, 2021 at 17:49 Comment(1)
this is a helpful comment but not an answer to the questionTeocalli
L
0

you can also use pickle to dumb the files on the server machine and then replot them on the local one. You can use "SCP" to copy the raw data to your local machine. Sometimes it helps since you can have real-time interaction with the plot. I follow these 2 links:

  1. save draw data python matplotlib save graph as data file
  2. copy using SCP Copying files from server to local computer using SSH
Lemma answered 17/3, 2021 at 13:16 Comment(0)
T
0

For me, the quickest fix is using Jupyter Notebook output from Python scripts. In VSCode, only add #%% at the start of the script. This creates a Jupyter Notebook block to run. To create more blocks, add #%% again at desired places of break. So, your script remains as a .py file, but you can quickly view image outputs and everything else as you would in a normal script :). I find this less cumbersome than what other answers have suggested, e.g. to save the image outputs as .png

Transship answered 28/4, 2023 at 3:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.