Reputation: 4763
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?
Upvotes: 1
Views: 1056
Reputation: 339280
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)
Upvotes: 3