Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

difference in plt.gca() behaviour between inline and notebook backends #13

Open
petercorke opened this issue Jan 26, 2022 · 2 comments
Open

Comments

@petercorke
Copy link

I have one notebook cell that creates a 3D axes, which I want to plot into in the next cell.

With the inline backend

Screen Shot 2022-01-26 at 3 18 55 pm

we see that the "current plot" has been forgotten, and plt.gca() creates a new 2D plot.

With the notebook backend

The behaviour is different

Screen Shot 2022-01-26 at 3 23 57 pm

and plt.gca() remembers the 3D plot across the cell boundaries.

Expected behaviour

The same in both cases, ideally the remembering the current plot across the cell boundary. I'm not sure which behaviour is "correct" but the difference is a problem when I'm running code in an ipython kernel from a client.

@fperez
Copy link
Member

fperez commented Aug 17, 2022

@petercorke, the issue you're encountering is indeed an inconsistency in behavior between the inline and notebook/ipympl/widget (let's call it widget from now on) backends.

Unfortunately, it's not completely trivial to fix. The problem is that, in order to achieve a "good user experience" in each case, over the years we had to make slightly different decisions:

  • the inline backend tries to make it such that plot(x) "just works" in a cell by itself, giving you a plot you can see immediately, without having to muck around with creating/managing figures, etc. It also tries to make it so that, if in the next cell you type plot(y), you now see y plotted by itself, without x polluting that figure (x and y may be totally unrelated and not make any sense if on the same figure).
  • the widget backend tries to give you a behavior where your figures stay interactive even if you scroll around, and you can come back and play with a previously created figure, move the axes, zoom, etc.

To achieve both of these goals, the inline backend aggressively closes figures once it's done displaying them, so you don't get "cross-cell side effects".

On the other hand, the widget one leaves them alone, for you to manage manually, so you can decide which ones you want to be interactive and which not.

Now, I don't think this state of affairs is ideal, but I've never sat down with enough time to see how to have a better experience across the two (keep in mind, the widget backend didn't exist when the inline behavior was designed, which was pre-jupyter notebook, back in 2010 for the IPython qt console).

It's possible there's a better long-term solution that @tacaswell or others have come up with. I know this is a nag for many, myself included.

But in the meantime, may I suggest you use this pattern instead. For the inline backend, when you need to manage your figures persistently (keep them alive across cells):

fig, ax = plt.subplots(...)
# do what you need with figure and axis objects
#...
fig  # last line to display a figure

and you can use the same code with the widget backend. The only thing you need to do in this case is manually close figures you don't need anymore. But otherwise it's reasonably clean code that, while a bit more verbose, works well for both backends.

I hope this helps!

@fperez
Copy link
Member

fperez commented Aug 18, 2022

BTW @petercorke - there's a longer discussion of this very topic in this issue on the ipympl repo, which you might find useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants