问题
I have a number of png
images that get updated somewhat regularly and want to include them in an IPython notebook, having them automatically updated in the notebook.
I thought I could do it by adapting the following matplotlib example:
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)
So I used this snippet:
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"))
But no output is produced. Apparently statements that follow Image()
override the display (and I am unsure this was supposed to work even without this happening). In the above code, get_latest_file_ts()
fetches the timestamp of the latest version of the image, and check_if_modified_file()
keeps checking for a newer timestamp on the same file, and returns the newer timestamp when it finds it.
[UPDATE]
I found a partial way to do this using widgets
, but my implementation creates a new HTML block at the end of the old one. What I want instead, is to replace the old HTML block with the new one -i.e. replace the content only.
Here is the code that stacks one HTML behind the other:
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()
I would really appreciate a way to get the second or third snippets above to work, or some other method to get this done.
回答1:
The problem with your first attempt is that you just create the image object (display.Image
) but not display it! To display the image, use the display.display
function which is similar to python's print statement but uses the IPython display machinery. Your call should look like
display.display(display.Image(os.path.join("figures", "fig1.png")))
Some background
If you just create the image object, the returned object is displayed only if it is the last command in the execution block -> the image object is the "OUT" value. Note, that it is placed next to the Out[x] prompt. In this particular case, the display machinery automatically displays it.
In your case you create the image within a loop without capturing it. It is not the last command in the execution block, thus the image object is not returned as "out" value and not displayed automatically. Latter has to be manually done.
This is totally the same with any python object. If you want to see it you have to print (display) it or (in IPython) make sure it is return as "OUT".
来源:https://stackoverflow.com/questions/30989509/automatically-update-image-in-ipython-notebook