3

I want to dynamically update the plot of a cell. I.e. the plot is initialized at the beginning of the cell, and updated in a (computationally heavy) for-loop, showing how the computation is progressing. In jupyter notebook, this can be done using pneumatics solution in What is the currently correct way to dynamically update plots in Jupyter/iPython?

%matplotlib notebook

import numpy as np
import matplotlib.pyplot as plt
import time

def pltsin(ax, colors=['b']):
    x = np.linspace(0,1,100)
    if ax.lines:
        for line in ax.lines:
            line.set_xdata(x)
            y = np.random.random(size=(100,1))
            line.set_ydata(y)
    else:
        for color in colors:
            y = np.random.random(size=(100,1))
            ax.plot(x, y, color)
    fig.canvas.draw()

fig,ax = plt.subplots(1,1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
for f in range(5):
    pltsin(ax, ['b', 'r'])
    time.sleep(1)

I am looking for an equivalent way of doing it in jupyter lab. I tried replacing %matplotlib notebook with %matplotlib widget, using the ipympl library, but that didn't work: The figure only shows once the loop is finished.

What I do not want are solutions like the one proposed by Ziofil in or the one by Paidoo in jupyterlab interactive plot which clear the whole output, as I might print additional things such as e.g. a tqdm progress bar

Hyperplane
  • 1,422
  • 1
  • 14
  • 28
  • Maybe this answer using `IPython.display.display.update` is helpful: https://stackoverflow.com/a/65400882/14396787 – shimeji42 Mar 29 '21 at 18:01

1 Answers1

2

This is a known for matplotlib for which there happily are workarounds. The relevant issues are: https://github.com/matplotlib/matplotlib/issues/18596 and https://github.com/matplotlib/ipympl/issues/258 and probably the longest explanation is https://github.com/matplotlib/ipympl/issues/290#issuecomment-755377055

Both of these workarounds will work with ipympl.

Workaround 1

Use the async ipython event loop following this answer: https://stackoverflow.com/a/63517891/835607

Workaround 2

Split the plt.subplots and the updating plot code into two cells. If you wait for a second or two between executing the cells then the plot will have enough time to set itself up properly and it should all work. That looks like this:

Cell 1:

fig,ax = plt.subplots(1,1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)

wait until the plot shows up then execute: Cell 2:

for f in range(5):
    pltsin(ax, ['b', 'r'])
    time.sleep(1)
Ianhi
  • 2,864
  • 1
  • 25
  • 24