Specify where in output matplotlib figures are rendered in jupyter using figure handles

自古美人都是妖i 提交于 2019-12-24 20:08:39

问题


When working with matplotlib, a common pattern for me is to figure in a function, return it, and let the caller decide what t do with it (render to screen, save to file etc...).

In jupyter notebook, I want to call such a function in a loop, and make sure that figure output is in order. In this answer https://stackoverflow.com/a/53450873/4050510 , we learn that plt.show() can help us with randering images. A rewrite of that answer is:

# cell 1
%matplotlib inline
import matplotlib.pyplot as plt
def make_figure(i):
    f = plt.figure(i)
    plt.plot([1,i,3])
    return f
#cell 2
for i in range(3):
    f = make_figure(i)
    print(i)
    plt.show()

The code above indeed works. The problem is that the solution breaks down if I want to create all the figures first, and then render them in chosen order. plt.show() will render all open figures at the same time.

#cell 3
fs = [(i,make_figure(i)) for i in range(3)]
for i,f in fs:
    print(i)
    plt.show()

The natural modification to make is to change the plt.show() into f.show(). Outside of jupyter notebook, that would solve the problem well.

# cell 4
fs = [(i,make_figure(i)) for i in range(3)]
for i,f in fs:
    print(i)
    f.show()

This does not work, raising UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure.

What is the explanation for this difference in behavior? How can I render matplotlib figures in chosen order, given a set of figure handles?


回答1:


figure.show() can only be used in interactive backends with an event loop already running.

In jupyter notebook with the inline backend, you have no event loop. However, similar to Matplotlib - sequence is off when using plt.imshow() and and this answer you can instead just do what the backend would also do, namely call display(figure).

cell 1

%matplotlib inline
import matplotlib.pyplot as plt
from IPython.display import display

def make_figure(i):
    f = plt.figure(i)
    plt.plot([1,i,3])
    return f

cell 2

%%capture

fs = [(i,make_figure(i)) for i in range(3)]

cell 3

for i, f in fs[::-1]:
    display(f)



来源:https://stackoverflow.com/questions/59392951/specify-where-in-output-matplotlib-figures-are-rendered-in-jupyter-using-figure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!