-
-
Notifications
You must be signed in to change notification settings - Fork 492
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
Improve interaction with Matplotlib #2553
Conversation
This is a sketch of how to improve the interaction with Matplotlib. The first idea is to directly create `Figure` objects rather than relying on pyplot. This de-couples the UI from the global state that is the pyplot figure registry and ensures that you never get surprise GUI windows popping up (or a memory leak) when pyplot selects a GUI backend. The second suggestion is to have the object return by the context manager be able to create multiple figures (not actually implemented). The third is to support saving the figures as png instead of svg (not actually implemented).
Hi @tacaswell, thanks for the suggestion! |
https://github.com/matplotlib/mpl-gui?tab=readme-ov-file#motivation is a slightly longer explanation, but the core of it is that is a bunch of global state you do not need and runs the risk of starting up a GUI event loop that (may) allocate memory that will only be release when the event loop is run (but you never run the event loop!). The usage would look something like: with MplFigure(fmt='png') as fig_factory:
fig = fig_factory.figure()
ax = fig.subplots()
# ax.....
fig2 = fig_factory.figure()
ax2 = fig2.subpots()
# ax2.... |
Thanks, @tacaswell! Let me comment on the individual ideas:
|
The point of not using pyplot is that If you only ever want to do one figure, then might as well just return it from the context manager (I guess if you want multiple figures in the UI you use multiple context managers?). for 3, you can base64 encode it and set it as a data url (e.g. what is done in jupyternotebooks) https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs . |
I think I didn't get this point yet. What is the benefit of using
Sure, that's possible. |
Put the other way, it is not clear to me what benefit you are getting from |
Oh, I see. I never really thought about the relation between matplotlib and plotly. Just for reference, here's ChatGPT's explanation on this matter:
Now I understand, why it is weird to use a with ui.matplotlib(figsize=(3, 2)) as fig:
ax = fig.gca()
x = np.linspace(0.0, 5.0)
y = np.cos(2 * np.pi * x) * np.exp(-x)
ax.plot(x, y, '-') Or would
Yes, I think so. Directly providing a figure instead of a figure factory simplifies the API quite a bit. |
I just updated the code to reflect the new API with ui.matplotlib(figsize=(3, 2)) as fig:
... There's one issue though: A UI element is supposed to return itself when entering its context. But here we return an MPL figure, which causes a type error. Maybe we need to change it to with ui.matplotlib(figsize=(3, 2)) as mpl:
fig = mpl.figure
... or with ui.matplotlib() as mpl:
fig = mpl.figure(figsize=(3, 2))
... or simply fig = mpl.Figure(figsize=(3, 2))
ui.matplotlib(fig) The latter is more in line with |
@rodja I finished the new Now this is the new usage compared to import numpy as np
from matplotlib import pyplot as plt
from nicegui import ui
x = np.linspace(0.0, 5.0)
y = np.cos(2 * np.pi * x) * np.exp(-x)
with ui.pyplot(figsize=(3, 2)):
plt.plot(x, y, '-')
with ui.matplotlib(figsize=(3, 2)).figure as fig:
fig.gca().plot(x, y, '-') Note how |
Why not with ui.mpl_figure(figsize=(3, 2)) as fig:
fig.gca().plot(x, y, '-') ? |
@tacaswell Here I explained the problem: #2553 (comment) |
Ah, sorry for the noise (and my failure to re-read the full thread). That makes sense. |
This PR is mostly a feature request/suggestion but it was easier to describe it via code that in text. So here is a draft PR (rather than an issue with an inline diff).
This is a sketch of how to improve the interaction with Matplotlib.
The first idea is to directly create
Figure
objects rather than relying on pyplot. This de-couples the UI from the global state that is the pyplot figure registry and ensures that you never get surprise GUI windows popping up (or a memory leak) when pyplot selects a GUI backend.The second suggestion is to have the object return by the context manager be able to create multiple figures (not actually implemented).
The third is to support saving the figures as png instead of svg (not actually implemented).