Reputation: 13150
The following is a simplified example of my code. The idea behind this class is to show the figure only when the show
method is executed.
# my_module.py
import matplotlib.pyplot as plt
import numpy as np
class Test:
def __init__(self):
self._fig = plt.figure()
self.ax = self._fig.add_subplot(1, 1, 1)
def show(self):
x = np.linspace(0, 10, 100)
y = np.sin(x)
self.ax.plot(x, y)
self._fig.tight_layout()
self._fig.show()
The code works as expected when it is executed from a Python shell or ipython. However, if I run this inside a Jypter Notebook:
from my_module import Test
t = Test()
At this point, an empty figure is visualized on the screen. I don't want that! Now, I tried to insert plt.close(self._fig)
inside __init__
, but then when I run t.show()
I get UserWarning: Matplotlib is currently using module://matplotlib_inline.backend_inline, which is a non-GUI backend, so cannot show the figure.
I also tried to load %matplotlib widget
with the previous edit plt.close(self._fig)
. The pictures is only shown when show
is called, but it is just a picture with no interactive frame.
Another option would be to rewrite the class in such a way that the figure is created inside the show
method. This is far from optimal as I would need to re-adjust my tests.
Are there any other ways to get it working correctly on all shells?
Upvotes: 2
Views: 1950
Reputation: 13150
In the original post I've done two mistakes.
First, the figure was instantiated into the __init__
method, then the show
method was called. In an interactive environment, once the figure is created it will be shown on the screen. We could turn off that behaviour with plt.ioff()
, but then two things can happen:
%matplotlib widget
was executed, the figure will show up only once when calling t.show()
.t.show()
.Hence, plt.ioff()
is not a valid solution. Instead, the figure must be instantiated when t.show()
is executed.
The second mistake I did was to use self._fig.show()
. Remember, in a interactive environment the figure is shown as soon as it is instantiated. Then, the previous command shows the figure a second time! Instead, I have to use plt.show()
, which only display the figure once.
Here is the correct code example:
import matplotlib.pyplot as plt
import numpy as np
class Test:
def __init__(self):
# init some attributes
pass
def show(self):
self._fig = plt.figure()
self.ax = self._fig.add_subplot(1, 1, 1)
x = np.linspace(0, 10, 100)
y = np.sin(x)
self.ax.plot(x, y)
self._fig.tight_layout()
plt.show()
t = Test() # no figure is shown
t.show() # figure is shown
Upvotes: 2