-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
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
ENH: mpl_gui to main library #29836
Conversation
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)) |
There was a problem hiding this comment.
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.
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:
While I'm generally a proponent of incremental changes, I think we need to have a big picture here. I don't think adding On a side-note: It might be that there is an incremental API-backward compatible alternative approach. One could try to make
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. |
@jklymak The latest commit in my branch at https://github.com/ianthomas23/matplotlib/commits/mpl-gui/ changes this to use the The We'd probably have to make extra changes to support There is some discussion about the failure of |
@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). |
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.
You need to access 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. |
This may be a case where you want to set the git commit details so you avoid the blame not get the credit 🤣 |
|
Is a very breaking change, even if 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 |
A typical example is
and 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. |
I would advocate that the API for If that is the plan, then all we are doing is gently suggesting folks change |
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. |
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 |
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. |
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. )
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 Another approach is to move everything in 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. |
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.
Ok, accepted. It's just a naming thing and mpl_gui has a broader scope than GUIs, so we should name it differently.
Then make
(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.
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"
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. |
I agree that making |
Then you may like creating your Figure fully OO and only registering with pyplot to show it 😀: #29855 |
Just a comment from the peanut gallery: |
The idea of You could have a
and
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. |
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. |
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 |
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. |
I admit that I don't understand at all what Jupyter and ipympl do under the hood, but
work fine with this PR.
does not, but it's just
so I think it is just something that needs to be set properly in |
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. |
Just throwing it out there, but a possible name I've had in mind is
"figlet".
…On Wed, Apr 2, 2025 at 8:15 PM Tim Hoffmann ***@***.***> wrote:
The integration is done through
https://github.com/ipython/matplotlib-inline.
Not how accurate it still is, but ipython/ipython#12190
<ipython/ipython#12190> gives some idea on the
mechanics in the background.
—
Reply to this email directly, view it on GitHub
<#29836 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACHF6ESD2J2BMZGRGLYMNL2XR4TXAVCNFSM6AAAAAB2C75WH6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDONZUGAZDKOBRGU>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
[image: timhoffm]*timhoffm* left a comment (matplotlib/matplotlib#29836)
<#29836 (comment)>
The integration is done through
https://github.com/ipython/matplotlib-inline.
Not how accurate it still is, but ipython/ipython#12190
<ipython/ipython#12190> gives some idea on the
mechanics in the background.
—
Reply to this email directly, view it on GitHub
<#29836 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACHF6ESD2J2BMZGRGLYMNL2XR4TXAVCNFSM6AAAAAB2C75WH6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDONZUGAZDKOBRGU>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Throwing in some more loosely related ideas: (1) It's also an option to have an abbreviated submodule name so that on could do (2) An option for the "grouped" show issue could be: Use
(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 |
OK, here is my stab at our options. They are somewhat annoyingly byzantine but so are our ways of using the library: Notes mpl_guiCurrent state
Pros:
Cons:
Pros:
Cons:
Proposed changes
|
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
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.
Is the current state but promotion could be implemented #29855
I assume, if we really want we can make My impression of mpl_gui is: We start with a clean approach, but then realize that this has limitations ( 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 The problem comes in with long-lived global state through collecting multple figures for a collective show(). 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 |
Thats for inline only. ipympl keeps the figure around. |
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 |
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.
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. |
The notes above are now at matplotlib/mpl-gui#21 |
This hoists @tacaswell mpl-gui (https://github.com/matplotlib/mpl-gui) into the main library.
mpl_gui
is the best name for this? Made sense when it was outside Matplotlib, but inside?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.