自动更新 IPython 笔记本中的图像

Automatically update image in IPython notebook

我有一些 png 图像会定期更新,我想将它们包含在 IPython 笔记本中,让它们在笔记本中自动更新。

我认为我可以通过改编以下 matplotlib 示例来做到这一点:

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

%matplotlib inline

plt.ion()

fig = plt.figure()
ax = fig.gca()
fig.show()

for i in range(10):
    mu, sigma = 200, 25
    x = mu + sigma*np.random.normal(loc=2, scale=1, size=50)

    if i == 0:
        barpl = plt.bar(range(len(x)), x)
    else:
        for rect, h in zip(barpl, x):
            rect.set_height(h)
    display.clear_output(wait=True)
    display.display(plt.gcf())
    time.sleep(2)

所以我使用了这个片段:

from IPython import display
import os

timestamp = get_latest_file_ts(directory="figures", file_name="fig1.png", strip_directory=True)

display.Image(os.path.join("figures", "fig1.png"))

while True:
    timestamp = check_if_modified_file(directory="figures", file_name="fig1.png", touched_on=timestamp, sleep_time=1, strip_directory=True)
    display.clear_output(wait=True)
    display.Image(os.path.join("figures", "fig1.png"))

但是没有产生任何输出。显然 Image() 后面的语句会覆盖显示(而且我不确定即使没有发生这种情况也能正常工作)。在上面的代码中,get_latest_file_ts() 获取最新版本图像的时间戳,check_if_modified_file() 不断检查同一个文件是否有更新的时间戳,returns 找到更新的时间戳它。

[更新] 我找到了使用 widgets 执行此操作的部分方法,但我的实现在旧块的末尾创建了一个新的 HTML 块。相反,我想要的是用新的 HTML 块替换旧的块 - 即仅替换内容。

这是将一个 HTML 堆叠在另一个后面的代码:

from IPython.html.widgets import interact, interactive, fixed
from IPython.html import widgets
from IPython.display import clear_output, display, HTML

def show_figs(directory="figures", file_name="fig1.png"):
    s = """<figure>\n\t<img src="%s" alt="The figure" width="304" height="228">\n</figure>""" % os.path.join(directory, file_name)
    display(HTML(s))

timestamp = get_latest_file_ts(directory="figures", file_name="fig1.png", strip_directory=True)
show_figs()
while True:
    timestamp = check_if_modified_file(directory="figures", file_name="fig1.png", touched_on=timestamp, sleep_time=1, strip_directory=True)
    show_figs()

我非常希望有一种方法可以使上面的第二个或第三个代码段正常工作,或者使用其他方法来完成此操作。

您第一次尝试的问题是您只是创建了图像对象 (display.Image),但没有显示它!要显示图像,请使用类似于 python 的打印语句但使用 IPython 显示机制的 display.display 函数。你的电话应该看起来像

display.display(display.Image(os.path.join("figures", "fig1.png")))

一些背景

如果只是创建图像对象,returned对象只有在执行块中的最后一个命令时才会显示->图像对象是"OUT"值。请注意,它位于 Out[x] 提示符旁边。在这种特殊情况下,显示机器会自动显示它。

在你的例子中,你在一个循环中创建图像而不捕获它。它不是执行块中的最后一个命令,因此图像对象不会 return 编辑为 "out" 值并且不会自动显示。后者必须手动完成。

这与任何 python 对象完全相同。如果你想看到它,你必须打印(显示)它或(在 IPython 中)确保它是 return as "OUT".