Notebook: Not able to have multiple interactive figures (matplotlib) in a single notebook

Created on 28 Feb 2016  Â·  8Comments  Â·  Source: jupyter/notebook

Hi,

Not sure if this issue is a matplotlib one or Jupyter one, please let me know if I post in the wrong place.

When I plot multiple figures in different cells (for instance 2 cells, each one doing a figure plot), if I do not close the interactive view (top right button on the graph) after having plotted the graph from the first cell, when I run the second cell to plot its graph, it does not show up below the second cell, as expected, but replaces the graph from the first cell.

This is only happening when using %matplotlib notebook, with the interactive JS plotter.

See screenshot below for an example:
2016-02-28-161336

Most helpful comment

You are inherently using matplotlib in the "wrong" way to have multiple figures.

it does not show up below the second cell, as expected, but replaces the graph from the first cell.

Actually it is expected to plot on the first cell.

Either you use the statefull pyplot interface (what you are doing), which implicitly plot on the currently open window/fig/axes ; here the one in the first cell.
(%matplotlib inline is a specific case where this is not visually the case for memory leak reasons.)

The idiomatic way to plot using matplotlib is to create a couple of fig/axes using plt.subplots, and then use the plot methods of these axes:

%matplotlib notebook

import matplotlib.pyplot as plt
fig, axes = plt.subplots()
axes.plot(range(10))
#figure one
fig, axes = plt.subplots()
axes.plot(range(10))
#figure two

This is in general much more flexible and reusable than using the statefull interface. And here as you are plotting on an explicit axis you canhave multiple opened plotter. It is also necessary when for example you get a 2 by 2 grid of figures to plot on the right one, try for example:

fig, ((a,b),(c,d)) = plt.subplots(2,2)
a.plot(x, sin(x))
b.plot(x, cos(x))
c.plot(x, tan(x))
d.plot(x, tanh(x))

I'm closing the issue as this is not a bug, and is expected, but feel free to continue asking question.

All 8 comments

You are inherently using matplotlib in the "wrong" way to have multiple figures.

it does not show up below the second cell, as expected, but replaces the graph from the first cell.

Actually it is expected to plot on the first cell.

Either you use the statefull pyplot interface (what you are doing), which implicitly plot on the currently open window/fig/axes ; here the one in the first cell.
(%matplotlib inline is a specific case where this is not visually the case for memory leak reasons.)

The idiomatic way to plot using matplotlib is to create a couple of fig/axes using plt.subplots, and then use the plot methods of these axes:

%matplotlib notebook

import matplotlib.pyplot as plt
fig, axes = plt.subplots()
axes.plot(range(10))
#figure one
fig, axes = plt.subplots()
axes.plot(range(10))
#figure two

This is in general much more flexible and reusable than using the statefull interface. And here as you are plotting on an explicit axis you canhave multiple opened plotter. It is also necessary when for example you get a 2 by 2 grid of figures to plot on the right one, try for example:

fig, ((a,b),(c,d)) = plt.subplots(2,2)
a.plot(x, sin(x))
b.plot(x, cos(x))
c.plot(x, tan(x))
d.plot(x, tanh(x))

I'm closing the issue as this is not a bug, and is expected, but feel free to continue asking question.

@Carreau thanks a lot for these explanations. I recently switched from %matplotlib inline to %matplotlib notebook and was used to having different figures even with the stateful pyplot interface, and came across many notebooks using matplotlib the wrong way, but it was actually working due to this memory leak "feature".

Sorry for the noise…

No problem, feel free to ask if you have any more questions.

You can also close the figures programmatically at the end of each cell - this is what the inline backend does by default. I haven't tried it, but something like plt.gcf().close() should do it.

This behavior forces you to use one of two valid MPL APIs, and if you're calling an external function that uses the plt one, you're out of luck. Both APIs are awkward, but the fig, ax one required to make the notebook backend work is verbose and requires boilerplate.

the correct way to close the figure programmatically within the Notebook seems to be plt.close()
At least for matplotlib==2.0.1

I agree with David: there should at least be some config option to permit using the stateful API with the notebook backend (e.g. implicitly calling plt.close() before executing cell contents whenever a cell is evaluated). The whole point of me using the stateful API is to avoid boilerplate (vs the OO API), and having to manually close a plot every time I make a new one is counterproductive to that end.

(fwiw I don't see why this wouldn't be justifiable for the notebook backend if InlineBackend.close_figures = True is a valid configuration option for inline)

ItS a FeAtUre NoT a BuG

Was this page helpful?
0 / 5 - 0 ratings

Related issues

toasteez picture toasteez  Â·  3Comments

fonnesbeck picture fonnesbeck  Â·  3Comments

Foadsf picture Foadsf  Â·  3Comments

cmesro picture cmesro  Â·  3Comments

ehossain1982 picture ehossain1982  Â·  3Comments