Skip to content

ENH: mpl_gui to main library #29836

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

Closed
wants to merge 2 commits into from
Closed

ENH: mpl_gui to main library #29836

wants to merge 2 commits into from

Conversation

jklymak
Copy link
Member

@jklymak jklymak commented Mar 30, 2025

This hoists @tacaswell mpl-gui (https://github.com/matplotlib/mpl-gui) into the main library.

import matplotlib.mpl_gui as mg

mg.select_gui_toolkit('Qt5Agg'). # also works with "macosx", doesn't work with "tkagg"

fig, ax = mg.subplots()
ax.plot(range(10))
mg.show([fig])
  1. This version partly works. I hacked some in the backend code, and I'm not very clear on everything that code does so this will probably need help (@tacaswell and @ianthomas23 ?). See comments below.
  2. I'm not sure that mpl_gui is the best name for this? Made sense when it was outside Matplotlib, but inside?
  3. No documentation yet other than what was in the standalone tool. My suggestion would be that we soft roll this out and add documentation over the next few releases.
  4. No pypi files, but will add later.

Why versus a standalone library? First there are some hacks that I suspect could be simplified substantially if it was part of main librabr. Second, it would be great to move away from pyplot over all and this would allow us to do so in the documentation.

Comment on lines 95 to 103
backend_name = backend_registry.resolve_gui_or_backend(newbackend)[0]
print(backend_name)
mod = importlib.import_module('matplotlib.backends.backend_' + backend_name)
if hasattr(mod, "Backend"):
orig_class = mod.Backend

else:
class orig_class(matplotlib.backend_bases._Backend):
locals().update(vars(mod))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where I hacked, because mpl_gui was not consistent with the changes made by @ianthomas23 to the backend registry. I somewhat suspect a lot of this file could change, but am uncomfortable enough with all of this that I haven't tried yet. I can try, but maybe it's an easy skim by folks who understand this better.

@jklymak jklymak marked this pull request as draft March 30, 2025 22:52
@timhoffm
Copy link
Member

timhoffm commented Mar 31, 2025

Introducing a new entry point into the library is the most significant change ever done to the library - IMHO this is worth a major version bump to matplotlib 4. We must make sure that we are doing this correctly. Some general thoughts:

  • We only have one chance of getting this right (with an experimental phase of course). But once people have migrated to the new API, it would be prohibitively costly to move again.
  • I'm tempted to put the new API into the top-level namespace. This communicates it's significance and fundamental aspiration. Since we this is a once-in-a-lifetime change (see first bullet point) we can be so bold to use the top-level namespace - no need to reserve it for "something better" in the future.
  • This also means we have the really think hard how the API should look like. My last look at mpl_gui was some time ago and I'd have to refresh it. From a fundamental point of view, I'd like to have one single interface that cares for all use cases (i.e. the case where we control the GUI event loop, the case where someone else controls the GUI event loop and the (non-interactive) case where there's no event loop at all.
  • I would also like to think about the way users should interact with the plot state, i.e. the regularly used objects. We currently have the duality fig, ax, but that's not necessarily the only approach, e.g. one could imagine an interface ax = subplots() and for the relatively rare cases that you need a figure, you could do ax.figure.

While I'm generally a proponent of incremental changes, I think we need to have a big picture here. I don't think adding mpl_gui alone to the core library will solve this. I'm ok with adding it if we see a technical need to better evaluate it's suitability. But I would cleary mark it as experimental. Maybe even some more catious wording, as I anticipate that the eventual solution will have a different API. It's rather "You may try it but it will most likely change" than "We think this is the correct solution, but reserve the right to change if we have overlooked something.


On a side-note: It might be that there is an incremental API-backward compatible alternative approach. One could try to make pyplot lazier. That would need to go in two directions:

  • make pyplot stateful (i.e. track figures) only when needed - for fig, ax = plt.subplots(); ax.plot(...); plt.show() we never use the concept of "current" figure. One could investigate whether only the use of other pyplot functions like plt.plot() manifests the statefulness. This has lifetime implications, possibly touching aspects discussed in [ENH]: Make savefig close plot by default #29782. It'd require careful thinking and design, but I see at least a chance that this could work and would not rule it out based on effort compared with a completely new API.
  • Delay GUI-binding further. We currently resolve the backend on pyplot figure creation because that determines our canvas etc. For savefig we temporarily switch out the canvas. Could we do it also the other way round? i.e. use a backend-independent canvas and only when showing, attach the suitable backend?

These are no easy topics, and some limitations of pyplot will still remain, but before changing the way every user interacts with matplotlib, we should at least have considered whether there are less invasive options and how they compare.

@ianthomas23
Copy link
Member

@jklymak The latest commit in my branch at https://github.com/ianthomas23/matplotlib/commits/mpl-gui/ changes this to use the backend_registry for resolving and loading backends. If you are happy with it you can take it from there, or I could push to this branch if you'd prefer.

The else block at https://github.com/jklymak/matplotlib/blob/11e357af31af63a965c064895d886c788f752378/lib/matplotlib/mpl_gui/_manage_backend.py#L130 might not be valid any more. It looks like it is intended to allow passing an actual Backend class rather than a string backend name which I don't believe is currently supported in pyplot.switch_backend so it may or may not work.

We'd probably have to make extra changes to support ipython and jupyter backends. I can look at those in due course.

There is some discussion about the failure of tk-based backends at matplotlib/mpl-gui#1.

@jklymak
Copy link
Member Author

jklymak commented Mar 31, 2025

@ianthomas23 Thanks for the changes - pushed to this branch (BTW, I've not properly set the authoring bits on any of these, but should do so when done).

@jklymak
Copy link
Member Author

jklymak commented Mar 31, 2025

@timhoffm

I think this is a more incremental change than needing to bump to version 4 or anything like that. The user-facing API is exactly the same as the pyplot API, except it's not in pyplot, and it does not hold a registry of figures by default. (I'm actually not clear why @tacaswell added a registry, but it is not used by default). The only other change is setting the backend, which I agree we should make sure we get right, and frankly is a little confusing.

For sure this should be marked experimental.

Putting at the top level is an interesting idea. OTOH I think that could happen after a soft roll out a level down?

I would advocate for moving this to the main library so it actually gets worked on and devs can start using it day-to-day. Currently it is not compatible with matplotlib main branch and hasn't really been looked at in 2 years.

one could imagine an interface ax = subplots() and for the relatively rare cases that you need a figure, you could do ax.figure.

You need to access fig to add colorbars and to save the figure; it's rare that I do not need fig. If you wanted a new method that didn't return the figure, I'd argue that should get a new name and is somewhat orthogonal to this PR.

Overall I do not consider this to be changing the API at all, but just stripping the figures and axes out of the confusing pyplot registry and allowing us to have a "non-pyplot" experience but still have a GUI.

@tacaswell
Copy link
Member

This may be a case where you want to set the git commit details so you avoid the blame not get the credit 🤣

@tacaswell
Copy link
Member

  • I added the figure registry to replicate the pyplot-like API and experiment with what the "right" level of implicit vs explict is. Although we tend to push towards explicit in new APIs, there is a fluidity to pyplot that it would be sad to lose.
  • I used mpl-gui for a personal project over new years, the main branch of mpl-gui should work with the main brnach of matplotlib
  • baby/toddler time-dilation is real 👶🏻

@timhoffm
Copy link
Member

timhoffm commented Apr 1, 2025

Use import matplotlib.mpl_gui as mg instead of import matplotlib.pyplot as plt

Is a very breaking change, even if mg has exactly the same API as plt. It will not invalidate existing code, but it will out-date basically every code and example. While people don't have to follow the recommendation and can still use pyplot, their code will not adhere to current best practices anymore, we'll have a mixture of old/new way and eventually people should upgrade to be in line with the recommended usage. There's no technical breakage, but a social/constistency pressure to change your code.

I want to do this mess only once to move away from pyplot (and still slightly question whether it's worth it). I don't want to come up with yet a better way to use matplotlib in 2 or 3 years and revise the recommendation again.

I therefore say it's ok to add mpl_gui to the main library, but should not recommend its usage until we're really sure this is the API of the future. "You can try it, but it will likely change".

@timhoffm
Copy link
Member

timhoffm commented Apr 1, 2025

one could imagine an interface ax = subplots() and for the relatively rare cases that you need a figure, you could do ax.figure.

You need to access fig to add colorbars and to save the figure; it's rare that I do not need fig. If you wanted a new method that didn't return the figure, I'd argue that should get a new name and is somewhat orthogonal to this PR.

A typical example is

fig, ax = plt.subplots()
# do stuff on ax
plt.show()

and fig is never used (check our examples how often that happens. I'm not weeded to ax = subplots() plus ax.figure - there other approaches as well. I just claim it's somewhat cumbersome to always have the two concepts as separate variables. Note that, e.g. neither bokeh nor plotly force you to define and carry around two variables. They have different interface concepts - and I mean interface the logical structure of Figure and Axes will remain, but we may want to create / access them differently.

This of course is a separte topic and PR. But when moving away from pyplot (which means people have to touch their code), it is reasonable to recheck whether we can have a better interface. As said above, I don't want to force people to change their way of working more than once concering the high-level API.

@jklymak
Copy link
Member Author

jklymak commented Apr 1, 2025

I would advocate that the API for mpl_gui and pyplot should be as close as possible, and should not drift apart.

If that is the plan, then all we are doing is gently suggesting folks change import matplotlib.pyplot as plt to import matplotlib.gui as mgui (or just use mpl.figure()) if they want a stateless experience.

@timhoffm
Copy link
Member

timhoffm commented Apr 1, 2025

I've understand this and it's a valid approach. Though I think we may give away optimization potential if we just copy the pyplot API (does supporting a stateless way-of-working justify a new entry point into the library / is that separation necessary?). - If the API stays, my current reverse attempt in #29849 is to make the state less intrusive. That would allow a quasi-stateless usage of pyplot, which has the big advantage that people don't have to change the imports. They could use pyplot as if it was stateful or stateless as they see fit.

@jklymak
Copy link
Member Author

jklymak commented Apr 1, 2025

I think the advantage is a clear separation of concerns. pyplot, and keeping track of figures really doesn't have anything to do with creating and showing them. Indeed, a suggested follow up would be to have pyplot just use mpl_gui (or whatever we call it) to create the figures, and pyplot would be higher level and just controls the registry and state tracking.

This change also has clear documentation advantages - the creation of the gui (or non-interactive backend) can be explained properly, separately from the state-based workflow. People looking at example code and asking "what does this pyplot module do"? are met with a whole bunch of stuff 98% of which is not relevant. Asking "what does this mpl_gui module do?" we can just say that it creates figures and attaches them to GUIs.

@timhoffm
Copy link
Member

timhoffm commented Apr 1, 2025

I think the advantage is a clear separation of concerns.

I totally agree on a technical level, and yes, internally pyplot should likely be using something like mpl_gui.

But I disagree for the API: What is better for the user than separated concerns? - No concerns. Users don't care about "attaching to GUIs" or "state tracking". The just want to create a figure, add content, save it and/or show it. If we can make this just work by rewiring in the background as needed, that's much better better than untangling and teaching the the differences between different approaches. - That's also part of my reservation wrt. mpl_gui: It's a specific interface/workflow for creating figures that are attached to a GUI. But what if you don't need a GUI? Do you go back to pyplot? Or do we teach the third approach using standalone Figure()?

@jklymak
Copy link
Member Author

jklymak commented Apr 1, 2025

that's much better better than untangling and teaching the the differences between different approaches.

I'd argue you still have the existing documentation problem - "Q: What is this pyplot?" "A: It's a whole bunch of stuff, but we recommend you ignore 99% of it". (I'd also argue that untangling things is generally a good idea. )

It's a specific interface/workflow for creating figures that are attached to a GUI. But what if you don't need a GUI? Do you go back to pyplot? Or do we teach the third approach using standalone Figure()?

mpl_gui.figure() doesn't attach to a gui on creation. Backend resolution doesn't happen until mpl_gui.show() (https://github.com/matplotlib/matplotlib/pull/29836/files#diff-07c2c7f1663e7eaea6b68718dc16f155be84e25e64b73faa629b35d0be7134f6). So the way mpl_gui is currently:

import matplotlib.gui as mgui

fig, axs = mgui.subplot_mosaic([['a', 'b'], ['c', 'c']])
fig.savefig('boo.pdf')

does not spinup a GUI - its just a passthrough to Figure()

Another approach is to move everything in _creation.py to the top level and then only use mpl_gui if needed:

import matplotlib as mpl
import matplotlib.gui as mgui

fig, axs = mpl.subplot_mosaic([['a', 'b'], ['c', 'c']])
...
mgui.show(fig)

The only issue there is that we now need two imports.

@timhoffm
Copy link
Member

timhoffm commented Apr 1, 2025

I'd argue you still have the existing documentation problem - "Q: What is this pyplot?" "A: It's a whole bunch of stuff, but we recommend you ignore 99% of it". (I'd also argue that untangling things is generally a good idea. )

There is no way you can define the documentation problem away. Even if we recommend something new, pyplot itself and it's API are here to stay. This also means your documentation problem persists and is only slightly rephrased. Instead of the above, you can say "It's a whole bunch of stuff, but we recmommend you to ignore 100% of it and use this other interface." And the question "What is this pyplot" or "Why do you have pyplot and this other thin mpl_gui" will come stronger when you introduce mpl_gui as a dedicated interface. Right now people have mostly accepted that pyplot is the entry point for creating plots, even if they don't understand all the technical implications behind this.

As said, introducing mpl_gui is a valid approach, but it is a major disruption. And therefore, it's equally valid to check which other approaches exist and what advantages disadvantages they have.


It's a specific interface/workflow for creating figures that are attached to a GUI. But what if you don't need a GUI? Do you go back to pyplot? Or do we teach the third approach using standalone Figure()?

mpl_gui.figure() doesn't attach to a gui on creation.

Ok, accepted. It's just a naming thing and mpl_gui has a broader scope than GUIs, so we should name it differently.

import matplotlib as mpl
import matplotlib.gui as mgui

fig, axs = mpl.subplot_mosaic([['a', 'b'], ['c', 'c']])
...
mgui.show(fig)

The only issue there is that we now need two imports.

Then make fig.show() cleverer, trivially

def show(self):
    mgui.show(self)

(it may be slightly more complicated than this, but AFAICS nothing that cannot be done).

@story645
Copy link
Member

story645 commented Apr 1, 2025

(it may be slightly more complicated than this, but AFAICS nothing that cannot be done

I think an extra import just to show things will frustrate most of our users and outright infuriate the crankier ones and so it really should be done if possible.

Or do we teach the third approach using standalone Figure()?

Did that for a PyCon tutorial and it's in a lot of ways cleaner b/c it's pure OO. I'd probably do it as a tutorial of "here's all the nice things you get by using this interface"

They could use pyplot as if it was stateful or stateless as they see fit.

Fully expect most users to stick w/ the pyplot interface unless things stop working, so having this be in it's own namespace while experimental and eventually shimming mpl_gui under pyplot is likely the best bet for getting folks to actually use it if it's the better technical choice.

@jklymak
Copy link
Member Author

jklymak commented Apr 1, 2025

I agree that making fig.show() do the right thing seems like a nice approach and could avoid the extra import. Whether we can do that cleanly would take some experimentation.

@timhoffm
Copy link
Member

timhoffm commented Apr 1, 2025

Did that for a PyCon tutorial and it's in a lot of ways cleaner b/c it's pure OO.

Then you may like creating your Figure fully OO and only registering with pyplot to show it 😀: #29855
On an expansion of this, we could likely make plt.show(fig) for a standalone figure instance work, or then in the spirit above fig.show().

@anntzer
Copy link
Contributor

anntzer commented Apr 2, 2025

Just a comment from the peanut gallery: plt.show(fig) or fig.show() have been discussed elsewhere; there are some issues with blockingness if you have more than one figure (you often want to block on the last show only). The approach you propose in the other PR (plt.figure(fig); plt.show()) has the advantage that registering multiple figures and showing them all at once "should just work". (Well, perhaps an API like plt.figures([fig1, fig2]) would be nice too but that's less important.)

@timhoffm
Copy link
Member

timhoffm commented Apr 2, 2025

plt.show(fig) could be expanded to support plt.show([fig1, fig2]) and thus prevent the blocking issue.

The idea of fig.show() basically is to make showing not depend on an external context, but attach it to the figure to be shown, but that reasonable only works as long as you show single figures.

You could have a fig.show(block=False) with patterns

fig1 = Figure()
...
fig1.show(block=False)
fig2 = Figure()
...
fig2.show()

and

for data in datasets:
    fig = Figure()
    ...
    fig.show(block=False)
fig.show()  # re-show the last figure and block

It's all not very nice (a) because of the asymmetry "not block on the last", (b) because the method would affect other instances. I'd rule that out.

Funamentally, if you want to show multiple figures at once, that function has to come from namespace outside the figure instance.
It could be implicit by collecting state like plt.show() or explicit with any namespace.show([fig1, fig2]), where namespace is ideally the same that is used to create the figure instance to prevent needing an additional import, i.e. plt.show() if using plt.figure(), mpl_gui.show() if using mpl_gui.figure(), Figure.show() if using Figure(). Which ones we'll end up with is basically decided by the namespace we'll want to use for figure creation in the future.

@jklymak
Copy link
Member Author

jklymak commented Apr 2, 2025

Ok now that this came up, I'm pretty sure that this is why @tacaswell added a registry to mpl_gui. I think you have the same issue with Jupyter needing to be able to show the figures that were created in a cell, and Jupyter doesn't require you to use plt.show().

This is all disturbingly like the existing pyplot. I'd still argue it is nicer to separate it from pyplot.

@jklymak
Copy link
Member Author

jklymak commented Apr 2, 2025

Btw I wouldn't be strongly against explicitly asking users to call fig.show(). The blocking asymmetry is a bit of a nuisance for interactive use but not a problem for notebook use. For interactive/script use showing the last figure a second time with a block isn't terrible. Nor is fig.show(list_of_figs) at the end of a loop. But they are relatively large breaks from the current behaviour

@timhoffm
Copy link
Member

timhoffm commented Apr 2, 2025

I think you have the same issue with Jupyter needing to be able to show the figures that were created in a cell, and Jupyter doesn't require you to use plt.show().

Speaking of which, Jupyter relies on the pyplot state to show the figures at the end of the cell. If we move away from pyplot, we need a story how to handle the Jupyter use case.

@jklymak
Copy link
Member Author

jklymak commented Apr 2, 2025

I admit that I don't understand at all what Jupyter and ipympl do under the hood, but

import matplotlib.mpl_gui as mg
%matplotlib ipympl
fig, ax = mg.subplots()
ax.plot(range(10))

fig, ax = mg.subplots()
ax.plot(range(20))

work fine with this PR.

import matplotlib.mpl_gui as mg
%matplotlib inline
...

does not, but it's just

NonGuiException: FigureCanvasAgg is non-interactive, and thus cannot be shown

so I think it is just something that needs to be set properly in mpl_gui._promotion.py

@timhoffm
Copy link
Member

timhoffm commented Apr 3, 2025

The integration is done through https://github.com/ipython/matplotlib-inline.

Not sure how accurate it still is, but ipython/ipython#12190 gives some idea on the mechanics in the background.

@WeatherGod
Copy link
Member

WeatherGod commented Apr 3, 2025 via email

@timhoffm
Copy link
Member

timhoffm commented Apr 3, 2025

Throwing in some more loosely related ideas:

(1) It's also an option to have an abbreviated submodule name so that on could do from matplotlib import mg instead of import matplotlib.mpl_gui as mg. This saves some typing (I personally find import matplotlib.pyplot as plt always annoyingly long). It's still reasonably clear for usage because the import comes from the matplotlib namespace.

(2) An option for the "grouped" show issue could be: Use fig.show() to blocking show single figures. Use a context manager to blocking show multiple figures

with collective_show():
   fig1.show()
   ...
   fig2.show()

(3) Not sure whether it's helpful for the management of state, but a module itself can be made a context manager. So in theory we could do with plt: or with matplotlib:.

@jklymak
Copy link
Member Author

jklymak commented Apr 4, 2025

OK, here is my stab at our options. They are somewhat annoyingly byzantine but so are our ways of using the library:

Notes mpl_gui

Current state

fig, ax = plt.subplots() # and friends

  • To show during interactive use or in a script: plt.show() will show all figures that have been created by pyplot that have note been plt.close()d.
  • plt.show(block=False) will show the current figure, but continue the script.
  • works with inline
  • works with ipympl

Pros:

  • easy to show all plots.

Cons:

  • mixed in with rest of pyplot
  • too many figures open; must manually close the ones we don't want anymore or memory grows. For a large jupyter notebook with cells executed many times, this can actually be substantial.

fig = matplotlib.figure.Figure()

  • cannot do fig.show(), but can do fig.savefig()
  • does not display anything in either inline or ipympl

Pros:

  • fig will be garbage collected because there are no references stored in a registry

Cons:

  • no way to show the figure on a GUI backend (no promotion possible).
  • ugly import.

Proposed changes

mpl_gui

  • import matplotlib.mpl_gui as mg; fig, ax = mg.subplots()
  • Can be shown, but with new mg.show([fig]) (though singleton fig could trivially be added).
  • jupyter: works without show in ipympl; does not (currently) work (at all) with inline.

Pros:

  • no global state - garbage collection on dereferenced figures
  • no connection to pyplot state-based interface

Cons:

  • New import and documentation (inertia relative to pyplot)
  • mg.show() doesn't know what figures to show, so it must be supplied a list of figures.
    • sometimes we create figures in loops, and assigning a different variable name to each figure to stop if from being dereferenced could be cumbersome.

mpl_gui.registry

  • import matplotlib.mpl_gui.registry as mr; fig, ax = mr.subplots()
  • allows mr.show() to be exactly the same as plt.show.

Pros:

  • no connection to pyplot state-based interface
  • exactly same as previous pyplot interface for this type of work.

Cons:

  • figures must be explicitly closed

mpl_gui.FigureContext

This is between the two extremes, where there is no global registry, but a registry is maintained for a series of plots within a context:

with mg.FigureContext() as fc:
    fig, ax = fc.subplots()
    fig, ax = fc.subplot_mosaic('AA\nBC')
    fig = fc.figure

makes three figures and shows them in a blocking manner, and then removes the registry on completion.

Top-level import?

The question arose as to whether these should be top level imports eg fig, ax = mpl.subplots() A choice would need to be made as to whether that is the registry or non-registry version of the new interface.

@timhoffm
Copy link
Member

timhoffm commented Apr 5, 2025

Thanks for summarizing. Would it make sense to create a formal enhancement proposal with this? I feel there are a lot of aspects to consider that are hard to keep track of in discussions. It would make sense to collaboratively define

  • issues with the current pyplot approach
  • intended usage patterns (showing single figure, savefig only, collective show, etc.)
  • possible solutions

too many figures open; must manually close the ones we don't want anymore or memory grows. For a large jupyter notebook with cells executed many times, this can actually be substantial.

Closing is only necessary if you don't show. More precisely: blocking show deregisters on window close. It seems the show-at-end-of-cell also deregisters with matplotlib inline. So even if you're primary intention in a notebook is only savefig, unless you take extra effort, the figure is shown at the end of the cell and then cleaned up. Therefore, collecting unclosed figures is not a serious problem in notebooks.
grafik

fig = matplotlib.figure.Figure()

  • no way to show the figure on a GUI backend (no promotion possible).

Is the current state but promotion could be implemented #29855

  • cannot do fig.show(), but can do fig.savefig()

I assume, if we really want we can make fig.show() call into pyplot/mpl_gui to make this work.


My impression of mpl_gui is: We start with a clean approach, but then realize that this has limitations (mg.show() doesn't know what figures to show) and therefore we add more API mpl_gui.registry / mpl_gui.FigureContext to reintroduce global state, which is closer again to pyplot.

It may also help to distinguish the kinds of global state: There the "current figure" implicit state. That alone could be simple to manage - Imagine a pyplot-like interface that only supports one figure at a time. That would allow simple plt.plot(); plt.title(); plt.show() operations without holding explicit object references. Whenever a new figure is created that gets "current" but the previous one is no longer tracked. Such an interface does not suffer from memory buildup.

The problem comes in with long-lived global state through collecting multple figures for a collective show(). mpl_gui.registry / mpl_gui.FigureContext solve this through introducing additional explicit API.

Fundamentally, we could attach this API also to pyplot and let pyplot not track figures indefinitely by default. Wether that's a good idea in terms of breaking backward compatibility for some use cases would need to be discussed. But introducing the whole new mpl_gui API, including possibly at least one of mpl_gui.registry / mpl_gui.FigureContext is also a major impact in terms of larger API surface and relearning for all usage scenarios.

@jklymak
Copy link
Member Author

jklymak commented Apr 5, 2025

Therefore, collecting unclosed figures is not a serious problem in notebooks.

Thats for inline only. ipympl keeps the figure around.

@jklymak
Copy link
Member Author

jklymak commented Apr 5, 2025

Would it make sense to create a formal enhancement proposal with this? I feel there are a lot of aspects to consider that are hard to keep track of in discussions.

What would be the best venue for this? Happy to move somewhere else. We haven't done a MEP for over a decade I don't think. I'm not sure what the best way to discuss something is, other than quoting and replying. Could put the note above into a markdown file that folks could comment on individual parts which may be the same thing as putting in a MEP

@timhoffm
Copy link
Member

timhoffm commented Apr 5, 2025

Thats for inline only. ipympl keeps the figure around.

Ok good to know. These details need to be spelled out to get a complete picture. In fact, I suspect ipympl is like a non-blocking show and by design you must have all figures of the notebook around to keep them responsive. Though it might be possible to deallocate figures when the respective output cell is cleared (feels similar to a "window close"). Possibly that's on the ipympl side to implement.


Could put the note above into a markdown file that folks could comment on individual parts which may be the same thing as putting in a MEP

That sounds reasonable. Given the complexity of the topic I would like to collaboratively create a document on it, which in the end should contain our shared perspective. It's easier to use PRs with suggestions compared to a discussion thread. I was thinking MEP because that's a reasonable place but I'm fine with any file on any repo/branch.

@jklymak
Copy link
Member Author

jklymak commented Apr 18, 2025

The notes above are now at matplotlib/mpl-gui#21

@jklymak jklymak closed this Apr 18, 2025
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

Successfully merging this pull request may close these issues.

7 participants