73

With old Jupyter notebooks, I could create interactive plots via:

import matplotlib.pyplot as plt
%matplotlib notebook
x = [1,2,3]
y = [4,5,6]
plt.figure()
plt.plot(x,y)

However, in JupyterLab, this gives an error:

JavaScript output is disabled in JupyterLab

I have also tried the magic (with jupyter-matplotlib installed):

%matplotlib ipympl

But that just returns:

FigureCanvasNbAgg()

Inline plots work, but they are not interactive plots:

%matplotlib inline
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Albatross
  • 955
  • 1
  • 7
  • 13
  • 1
    When using Jupyter notebooks, I tend to use > import matplotlib > matplotlib.use('nbagg') to get an interactive plot with pan/zoom functionality. See: https://matplotlib.org/users/prev_whats_new/whats_new_1.4.html#the-nbagg-backend – tda May 03 '18 at 07:48
  • 1
    This is Jupyterlab, however. Using this method also outputs `JavaScript output is disabled in JupyterLab` – Albatross May 03 '18 at 07:51
  • 6
    I had the same problem recently. Try this: https://github.com/matplotlib/jupyter-matplotlib/issues/9#issuecomment-341908855 – Georgy May 03 '18 at 07:54
  • What worked for me: 1.) use `%matplotlib widget` 2.) Make sure that you have Jupyter Lab version > 1.0 and ipywidgets > 7.5 installed, as adviced here: https://github.com/matplotlib/jupyter-matplotlib/issues/133 3.) Open Jupyter Lab from the terminal with the command `jupyter lab`. I was using before a programme that was making for me a short cut, so I don't have to open the terminal – NeStack Aug 03 '19 at 18:43

6 Answers6

93

JupyterLab 3.0+

  1. Install jupyterlab and ipympl.

    For pip users:

    pip install --upgrade jupyterlab ipympl
    

    For conda users:

    conda update -c conda-forge jupyterlab ipympl
    
  2. Restart JupyterLab.

  3. Decorate the cell containing plotting code with the header:

    %matplotlib widget
    
    # plotting code goes here
    

JupyterLab 2.0

  1. Install nodejs, e.g. conda install -c conda-forge nodejs.

  2. Install ipympl, e.g. conda install -c conda-forge ipympl.

  3. [Optional, but recommended.] Update JupyterLab, e.g.
    conda update -c conda-forge jupyterlab==2.2.9==py_0.

  4. [Optional, but recommended.] For a local user installation, run:
    export JUPYTERLAB_DIR="$HOME/.local/share/jupyter/lab".

  5. Install extensions:

     jupyter labextension install @jupyter-widgets/jupyterlab-manager
     jupyter labextension install jupyter-matplotlib
    
  6. Enable widgets: jupyter nbextension enable --py widgetsnbextension.

  7. Restart JupyterLab.

  8. Decorate with %matplotlib widget.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
  • 1
    Mateen, thank you for compiling the steps - why is it necessary to install jupyterlab-manager ? – N.M Jun 14 '19 at 17:32
  • There is an issue with some older jupyter lab versions and the nodejs yarn package (which jupyter uses for its install procedure). In such a case either update/upgrade your jupyter-lab or follow this fix: https://github.com/jupyter-widgets/ipywidgets/issues/2061#issuecomment-397117346 – Simon Streicher Jul 22 '19 at 05:17
  • 2
    I've added two steps that was necessary on my system: (1) upgrade jupyterlab, (2) enable nbextension. – Simon Streicher Jul 22 '19 at 07:08
  • 1
    I had to `conda install widgetsnbextension -c conda-forge` before I could enable widgetsnbextension (but then I ran into other issues with jupyterlab being the wrong version, which is a different story...) – MD004 Aug 22 '19 at 23:25
  • 1
    "restart" was the critical instruction for me. It wasn't enough the quit and start again jupyterlab in the terminal, only after restarting the computer the plots finally worked – NeStack Jan 18 '20 at 11:30
  • Do I have to complete these installation instructions for every new virtual conda environment I create or will the interactive plotting be available for all virtual environments I am using? – NeStack Apr 20 '20 at 17:47
  • Caveat: remember to do plt.figure() before the next plot if you're coming to this from using "inline". – volante Aug 06 '20 at 03:48
  • Step 5 fails with `An error occured. ValueError: Please install nodejs >=12.0.0 before continuing. nodejs may be installed using conda or directly from the nodejs website. See the log file for details: /tmp/jupyterlab-debug-gklm270m.log`. Using pyenv for managing my python installations. – Christoph90 Apr 22 '21 at 08:13
  • @Christoph90 Sounds like you need to install Node.js. – Mateen Ulhaq Apr 22 '21 at 08:57
  • I did all of the above, but I still get the error `Javascript Error: Can't find variable: IPython` – Emy May 05 '21 at 15:39
  • @Emy, what version of JupyterLab are you using? If using v.3.*, see my [answer](https://stackoverflow.com/a/66246240/10705616) below – Paidoo May 06 '21 at 15:56
  • Thanks, I managed to make it work. I did all of the above, restarted the computer, *closed all the servers*, then opened a notebook in a new server and now `%matplotlib widget` is working. – Emy May 06 '21 at 15:59
  • also make sure %matplotlib notebook comes before import matplotlib.pyplot as plt – Stone Sep 14 '21 at 01:21
12

To enable the jupyter-matplotlib backend, use the matplotlib Jupyter magic:

%matplotlib widget
import matplotlib.pyplot as plt
plt.figure()
x = [1,2,3]
y = [4,5,6]
plt.plot(x,y)

More info here jupyter-matplotlib on GitHub

Screenshot Jupyter Lab

John
  • 1,645
  • 2
  • 17
  • 29
  • I am able to plot this figure, the pan-zoom buttons can be pressed but nothing happens. it even tells me "pan with left mouse" but thing happens. How to solve this? – wander95 Jan 15 '19 at 20:03
  • Difficult to say, if you are on Windows, try WinPython_3.6 available at https://sourceforge.net/projects/winpython/files/ as is used for the example shown above. – John Jan 16 '19 at 09:41
  • I was able to solve this by reinstalling things by following the steps in https://github.com/matplotlib/jupyter-matplotlib. Tip: don't mix conda and pip for this. – wander95 Jan 16 '19 at 15:36
  • do you if it is possible to plot without plt.figure() in the beginning. It is possible if we are using inline backend but not with widget or notebook bakend – Namit Juneja Feb 26 '20 at 23:15
10

As per Georgy's suggestion, this was caused by Node.js not being installed.

user
  • 5,370
  • 8
  • 47
  • 75
Albatross
  • 955
  • 1
  • 7
  • 13
9

Steps for JupyterLab 3.*

I had previously used Mateen's answer several times, but when I tried them with JupyterLab 3.0.7 I found that jupyter labextension install @jupyter-widgets/jupyterlab-manager returned an error and I had broken widgets.

After a lot of headaches and googling I thought I would post the solution for anyone else who finds themselves here.

The steps are now simplified, and I was able to get back to working interactive plots with the following:

  1. pip install jupyterlab
  2. pip install ipympl
  3. Decorate with %matplotlib widget

Step 2 will automatically take care of the rest of the dependencies, including the replacements for (the now depreciated?) @jupyter-widgets/jupyterlab-manager

Hope this saves someone else some time!

Paidoo
  • 379
  • 3
  • 13
  • 2
    This comment is the current correct answer if you're installing. On my machine (Jupyterlab3, python3.9) `jupyterlab-manager` actually breaks the widget functionality. – catalogue_number Jun 09 '21 at 08:38
  • what are your versions of jupyterlab and ipympl? with jupyterlab 3.6.1 and ipympl 0.9.2 these steps lets me see the plot and I can resize the window, but I can't click the zoom and move buttons – Linus Feb 14 '23 at 22:19
  • I have mine working with jupyterlab 3.2.1 and ipympl 0.8.2. Do you have your `%matplotlib widget` decoration placed before you `import matplotlib.pyplot as plt`? – Paidoo Feb 15 '23 at 10:45
  • 1
    @paidoo thanks, as an update the zoom/move issue was due to an incompatibility with the latest matplotlib, but it's fixed as of https://github.com/matplotlib/ipympl/issues/516 – Linus Feb 17 '23 at 12:40
3

Summary

In a complex setup, where jupyter-lab process and the Jupyter/IPython kernel process are running in different Python virtual environments, pay attention to Jupyter-related Python package and Jupyter extension (e.g. ipympl, jupyter-matplotlib) versions and their compatibility between the environments.

And even in single Python virtual environment make sure you comply with the ipympl compatibility table.

Example

A couple of examples how to run JupyterLab.

Simple(st)

The simplest cross-platform way to run JupyterLab, I guess, is running it from a Docker container. You can build and run JupyterLab 3 container like this.

docker run --name jupyter -it -p 8888:8888 \
  # This line on a Linux- and non-user-namespaced Docker will "share"
  # the directory between Docker host and container, and run from the user.
  -u 1000 -v $HOME/Documents/notebooks:/tmp/notebooks \
  -e HOME=/tmp/jupyter python:3.8 bash -c "
    mkdir /tmp/jupyter; \
    pip install --user 'jupyterlab < 4' 'ipympl < 0.8' pandas matplotlib; \
    /tmp/jupyter/.local/bin/jupyter lab --ip=0.0.0.0 --port 8888 \
      --no-browser --notebook-dir /tmp/notebooks;
  "

When it finishes (and it'll take a while), the bottommost lines in the terminal should be something like.

    To access the server, open this file in a browser:
    ...
        http://127.0.0.1:8888/lab?token=abcdef...

You can just click on that link and JupyterLab should open in your browser. Once you shut down the JupyterLab instance the container will stop. You can restart it with docker start -ai jupyter.

jupyterlab 3

Complex

This GitHub Gist illustrates the idea how to build a Python virtual environment with JupyterLab 2 and also building all required extensions with Nodejs in the container, without installing Nodejs on host system. With JupyterLab 3 and pre-build extensions this approach gets less relevant.

Context

I was scratching my head today while debugging the %matplotlib widget not working in JupyterLab 2. I have separate pre-built JupyterLab venv (as described above) which powers local JupyterLab as Chromium "app mode" (i.e. c.LabApp.browser = 'chromium-browser --app=%s' in the config), and a few IPython kernels from simple Python venvs with specific dependencies (rarely change) and an application exposing itself as an IPython kernel. The issue with the interactive "widget" mode manifested in different ways.

For instance, having

  • in JupyterLab "host" venv: jupyter-matplotlib v0.7.4 extension and ipympl==0.6.3

  • in the kernel venv: ipympl==0.7.0 and matplotlib==3.4.2

In the browser console I had these errors:

  • Error: Module jupyter-matplotlib, semver range ^0.9.0 is not registered as a widget module
  • Error: Could not create a model.
  • Could not instantiate widget

In the JupyterLab UI:

  • %matplotlib widget succeeds on restart
  • Charts stuck in "Loading widget..."
  • Nothing on re-run of the cell with chart output
  • On previous attempts %matplotlib widget could raise something like KeyError: '97acd0c8fb504a2288834b349003b4ae'

On downgrade of ipympl==0.6.3 in the kernel venv in the browser console:

  • Could not instantiate widget
  • Exception opening new comm
  • Error: Could not create a model.
  • Module jupyter-matplotlib, semver range ^0.8.3 is not registered as a widget module

Once I made the packages/extensions according to ipympl compatibility table:

  • in JupyterLab "host" venv: jupyter-matplotlib v0.8.3 extension, ipympl==0.6.3

  • in the kernel venv: ipympl==0.6.3, matplotlib==3.3.4

It more or less works as expected. Well, there are verious minor glitches like except I put %matplotlib widget per cell with chart, say on restart, the first chart "accumulates" all the contents of all the charts in the notebook. With %matplotlib widget per cell, only one chart is "active" at a time. And on restart only last widget is rendered (but manual re-run of a cell remediates).

saaj
  • 23,253
  • 3
  • 104
  • 105
2

This solution works in jupyterlab

import numpy as np
import matplotlib.pyplot as plt
from IPython.display import clear_output


n = 10
a = np.zeros((n, n))
plt.figure()

for i in range(n):
    plt.imshow(a)
    plt.show()
    a[i, i] = 1
    clear_output(wait=True)
Aray Karjauv
  • 2,679
  • 2
  • 26
  • 44