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

Proposal: Transition matplotlib-pyodide to Maintenance-Only Mode #65

Open
ryanking13 opened this issue Nov 30, 2024 · 15 comments
Open

Proposal: Transition matplotlib-pyodide to Maintenance-Only Mode #65

ryanking13 opened this issue Nov 30, 2024 · 15 comments
Labels
help wanted Extra attention is needed request for comment Inviting voices by users, contributors, maintainers, and anyone else interested to express thoughts

Comments

@ryanking13
Copy link
Member

Background

matplotlib is a critical library for Python users, and many want to use it with Pyodide. To meet this demand, matplotlib-pyodide was introduced early in Pyodide's history (originating in the predecessor project, Iodide).

The project benefited initially from @ mdboom (not linking intentionally as he doesn't work at Pyodide anymore), Pyodide creator and Matplotlib contributor, who developed a Matplotlib backend for Pyodide. However, the current Pyodide core team lacks the deep Matplotlib expertise required to maintain this backend effectively.

This lack of expertise has become a bottleneck, especially during major updates like upgrading NumPy v2. For example, while @agriyakhetarpal has made significant progress on this upgrade, updating and testing matplotlib-pyodide remains a significant challenge.

Proposal

I propose moving matplotlib-pyodide to maintenance-only mode, with the following changes:

Limit New Features:

Only address critical compatibility issues with Matplotlib (e.g., #15). No new feature additions.

Remove Non-Essential, Unmaintainable Features:

  • Font support: Currently relies on bundling a separate .ttf file in the Pyodide distribution, which is problematic without a clear solution.
  • html5_canvas_backend: Developed during a GSoC project (details here), but it is no longer actively developed or well-understood. The default wasm_backend will remain. (cc: @madhur-tandon)

By removing these features, we aim to reduce maintenance costs. Alternatively, we could exclude these features from the test suite to avoid blocking releases due to broken tests.

Revisit Maintenance Mode if a Maintainer Emerges:

If a reliable maintainer with sufficient expertise volunteers, we can revoke maintenance-only status.

Additional Context

Tools using the IPython kernel (e.g., JupyterLite) typically use their own Matplotlib backend and do not depend on matplotlib-pyodide. So I believe it would not affect users who use matplotlib in Jupyter-like kernels.

WDYT?

@agriyakhetarpal
Copy link
Member

Thanks for opening this proposal! I've pinned the issue for higher visibility and to invite more comments by users. A few points from my side:

  • I wasn't aware that the WASM backend existed prior to the HTML5 one (if I understand it correctly).
  • Also, I wasn't aware either that JupyterLite does not rely on matplotlib-pyodide.
  • Much of the code makes me feel to some extent that the backends need to be rewritten in a more modern way, not only to fulfill Matplotlib's requirements, but also to clear the list of twenty open issues, out of which most are valid when considered as bugs and feature requests (such as Make output figures resizable #15, that you've mentioned).
  • There is a chance I could perform the rewrite and we get to maintain the package again, but that does require a concerted effort from me and a study of matplotlib's internals (of perhaps the length of a GSoC project or longer) which I can't commit to at this time.

and perhaps a naïve question:

  • Is there any way we can understand the i. size of the user base, and ii. use cases, for Matplotlib outside of JupyterLite but within Pyodide? That is, if hardly anyone is using it and most people and projects are using Pyodide's Matplotlib in Jupyter-based interfaces, this wouldn't be breaking for anyone at all, since we can't display plots in the console (Matplotlib does not work #7) and we don't have a canvas to render to with Node.js. Though, I do think saving and loading plots as images should remain supported (however, that, I guess, uses the WASM backend and not the HTML5 backend).

@agriyakhetarpal agriyakhetarpal added help wanted Extra attention is needed request for comment Inviting voices by users, contributors, maintainers, and anyone else interested to express thoughts labels Nov 30, 2024
@ryanking13
Copy link
Member Author

I wasn't aware that the WASM backend existed prior to the HTML5 one (if I understand it correctly).

That's correct.

I wasn't aware either that JupyterLite does not rely on matplotlib-pyodide.

matplotlib_inline backend is default for jupyterlite.

image

Is there any way we can understand the i. size of the user base, and ii. use cases, for Matplotlib outside of JupyterLite but within Pyodide?

I am not sure to be honest. If people download matplotlib-pyodide from PyPI, we could find some PyPI download stats, but it is not available for us.

@hoodmane
Copy link
Member

hoodmane commented Dec 1, 2024

From JsDelivr it looks like matplotlib_pyodide gets about 50,000 downloads per week.

@ryanking13
Copy link
Member Author

From JsDelivr it looks like matplotlib_pyodide gets about 50,000 downloads per week.

We set matplotlib-pyodide as a dependency of matplotlib, so even if a user does not use matplotlib-pyodide it will be downloaded when a user installs matplotlib. So I think we cannot trust that number.

@hoodmane
Copy link
Member

hoodmane commented Dec 2, 2024

Maybe we could start by removing the dependency?

@ryanking13
Copy link
Member Author

Maybe we could start by removing the dependency?

Sounds fine to me. It would be a breaking change, but I think it worth to do so.

@ianthomas23
Copy link

I think I may be able to help here. There is an existing backend in Matplotlib called WebAgg that serves Matplotlib figures using tornado as PNGs via websockets to some frontend JS and CSS code. It is probably not used by many people but it has been around for ~10 years and is part of the main codebase and is under CI. It is fully interactive and figures can be resized. I think it might be possible to replace the two backends in this repo with a patched version of WebAgg. The "frontend" JS and CSS could stay pretty much as they are but with mocked websockets, the "backend" would need use of tornado replaced with something simpler, and also mock websockets so that they are direct functions calls. The latter is something we do in JupyterLite.

Normally I would do some preliminary work to see how feasible this sort of thing is before sticking my neck out, but I realise that you are close to giving up on this so time is of the essence!

Assuming it is feasible and that you happy to eventually drop two backends in this repo, a possible work sequence could be:

  1. Keep this repo alive but drop the problematic backend as you have already discussed, making "html5_canvas_backend" a synonym for "wasm_backend".
  2. Continue with Update matplotlib to 3.8.4 pyodide#4510.
  3. Me: write the required patches in the pyodide matplotlib recipe to use WebAgg.
  4. Me: use item 3 in the pyodide matplotlib tests.
  5. When 3 and 4 are robust, this repo can be archived. The two backend names "html5_canvas_backend" and "wasm_backend" can be made synonyms for "webagg" so no end users suffer loss of functionality, but their results will be visually different of course. The two backend names could be deprecated, but that is a detail at this stage.
  6. Me: refactor of WebAgg code in Matplotlib to separate out the code that is (a) common to both normal python and pyodide use, and (b) specific to either normal python or pyodide. We probably cannot upstream all the patches from item 3 into the Matplotlib codebase, but we should be able to make the patches as simple as possible.

I've joined the pyodide Discord in case that helps.

Oh, who am I? I'm a Matplotlib maintainer and my day job is mostly working on JupyterLite and Emscripten-forge. My use of pyodide and Matplotlib together is restricted to JupyterLite so I don't have particular interest in pyodide outside of JupyterLite, but I see that I am probably in a good position to help here. I'm certainly interested in helping to break down any barriers that have inadvertently appeared between different sections of the python wasm community.

@agriyakhetarpal
Copy link
Member

Hi @ianthomas23, thank you so much for reaching out! Yes, as a part of pyodide/pyodide#4510, we've been able to get the WASM backend to work, and the HTML5 backend is also close to working (seemingly). I would largely agree with the work sequence you have proposed. Still, as a part of (2), I would also say that since the Pyodide release has been delayed by a bit of time already, maybe it would make sense to either get #64 towards completion or patch the code here to use the WebAgg backend if the latter doesn't take too much time for an initial implementation. The Pyodide release is still going to take around a week after pyodide/pyodide#4925 gets merged because we might need to add some remaining niceties and clear the backlog of small but unreviewed PRs, so we do have some some time if you wish to hack things up and experiment with (3). Shall we decide to archive this repository, (5) could also be taken up with matplotlib/matplotlib#29093 and (6) would then be split up into longer-term changes.

My summary on the plan of action would be that for now, a review based on the current state of #64 (which is what is being patched into pyodide/pyodide#4510) and some attempts to make it work completely would be beneficial for the release so as to not let that effort go in vain; I've tried to hack around the Canvas API there over the past week, but I am no expert with Matplotlib, of course. Then, your proposed work sequence sounds like the way to go.

@ryanking13
Copy link
Member Author

@ianthomas23 Thanks for reaching out, and I am really happy that matplotlib developers are interested in this issue.

It is fully interactive and figures can be resized. I think it might be possible to replace the two backends in this repo with a patched version of WebAgg.

We'll need to investigate whether we can make it compatible with Pyodide, but I am +1 on replacing our wasm_backend and HTML5 backend with WebAgg if possible.

Me: refactor of WebAgg code in Matplotlib to separate out the code that is (a) common to both normal python and pyodide use, and (b) specific to either normal python or pyodide. We probably cannot upstream all the patches from item 3 into the Matplotlib codebase, but we should be able to make the patches as simple as possible.

This would be ideal for us. I also don't think we can fully upstream the patches, but keeping it minimal would reduce our maintenance burden.

@ianthomas23
Copy link

@agriyakhetarpal Please don't hold off pyodide/pyodide#4510 hoping for a modified WebAgg backend to be available soon. Given the limited time I have to spend on this it is more likely to be a few months before I complete that rather than a few days. Also, starting with Matplotlib 3.8 will be much easier for me than with 3.5. And as @ryanking13 says, I must investigate if WebAgg can be made compatible with Pyodide, at the moment this is a hope a not a guarantee.

@jsclass42
Copy link

I agree it is a good idea to remove the dependency, and to not break things, simply replace it with the minimum bare bone implementation, like print out a informational message in the implementation FigureManager show() method, saying something like, For displaying figures, you may want to explicit use a desired backend, such as, matplotlib.use("module://matplotlib_pyodide.wasm_backend"). This way, we don't have to bear the overhead of loading the lib if we don't use it. And I don't know if it will also help to not load font files -- currently, we always get a message like Matplotlib is building the font cache; this may take a moment. -- I don't know if removing the dependency will also remove this step/message. Font support could be a separate load-on-demand package?

Thank you all!

@ryanking13
Copy link
Member Author

Thanks for the suggestion.

And I don't know if it will also help to not load font files -- currently, we always get a message like Matplotlib is building the font cache; this may take a moment. -- I don't know if removing the dependency will also remove this step/message. Font support could be a separate load-on-demand package?

I am not sure if this is related to matplotlib-pyodide. I think we don't do anything about font cache, maybe something has changed in the recent matplotlib versions.

@ianthomas23
Copy link

I wanted to give a quick update. I've started working on patching the Matplotlib webagg backend for use in pyodide and I am progressing well. Hopefully I'll have something to share in a couple of weeks or so.

@agriyakhetarpal
Copy link
Member

Thanks for sharing, @ianthomas23!

@agriyakhetarpal
Copy link
Member

currently, we always get a message like Matplotlib is building the font cache; this may take a moment. -- I don't know if removing the dependency will also remove this step/message.

Sorry, I missed this comment, @jsclass42. This message comes from Matplotlib, and not from matplotlib-pyodide. Please feel free to patch it away in https://github.com/pyodide/pyodide/tree/main/packages/matplotlib – I think it is being removed in matplotlib/matplotlib#29093, too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed request for comment Inviting voices by users, contributors, maintainers, and anyone else interested to express thoughts
Projects
None yet
Development

No branches or pull requests

5 participants