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

1

1 Answer 1

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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.