如何使用JupyterLab循环更新交互式图形

问题描述

我正在尝试使用JupyterLab循环更新交互式matplotlib图形。如果我在与循环不同的单元格中创建图,则可以执行此操作,但是我更愿意在该单元格中创建图并运行循环。

简单代码示例:

import matplotlib.pyplot as plt
import time

%matplotlib widget

fig = plt.figure()

for i in range(5):
    x = list(range(i+2))
    xx = [x**2 for x in x]
    plt.clf()
    plt.plot(x,xx)
    fig.canvas.draw()
    
    time.sleep(1)

如果fig = plt.figure()与循环位于同一单元格中,则直到循环结束,图形才会更新:

Not Dynamically Updating

如果在不同的单元格中创建图形,则会得到动态更新,但如果可能的话,我希望能够在同一单元格中创建图形,因此输出位于循环下方:

Requires extra cell

我在其他问题(hereherehere)中尝试了几种答案,但是,它们似乎不适用于JupyterLab中的交互式图形。我使用jupyter/scipy-notebook码头工人镜像作为我的环境,因此我相信一切都已正确设置。

有什么方法可以在创建图形的同一个单元中获得动态更新?

解决方法

您可以利用IPython事件循环来使用asyncio:

import matplotlib.pyplot as plt
import asyncio
%matplotlib widget
fig = plt.figure()


async def update():
    for i in range(5):
        print(i)
        x = list(range(i + 2))
        xx = [x**2 for x in x]
        plt.clf()
        plt.plot(x,xx)
        fig.canvas.draw()
        await asyncio.sleep(1)


loop = asyncio.get_event_loop()
loop.create_task(update());

gif with a notebook with single cell being run and the animation progressing as expected

,

如果不想使用asyncio,可以使用display(...,display_id=True)获取句柄并在其上使用.update()

import matplotlib.pyplot as plt
import time
%matplotlib widget
fig = plt.figure()

hfig = display(fig,display_id=True)


def update():
    for i in range(5):
        print(i)
        x = list(range(i + 2))
        xx = [x**2 for x in x]
        plt.clf()
        plt.plot(x,xx)
        fig.canvas.draw()
        hfig.update(fig)
        time.sleep(1)

update()

plt.close(fig)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...