Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Add mpl-playback to widgets gallery examples #23441

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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
Loading
from

Conversation

ianhi
Copy link
Contributor

@ianhi ianhi commented Jul 18, 2022

PR Summary

Start using mpl-playback (docs, github) to automatically generate GIFs of interactions with widgets for sphinx-gallery. This works by:

  1. Recording all the events from a user interaction to a json file
  2. Using a custom sphinx-gallery scraper to turn those json files into gifs when the docs build
    • This falls back to the default scraper when there is no playback file

The built version looks like this: Rendered example and thumbnail in gallery.

I've made a recording of the slider demo for this PR which currently looks like this:
slider_demo_0

This will close: #19222

Discussion!

I'm opening this early to see if this is something that the core devs would be interested in. As it stands I don't think mpl-playback is quite ready for mpl to depend on it. But I'd be happy to put in the work to make sure it is if the consensus would be to go ahead with this. I will note that this is hopefully a very low cost addition, at any point it's a one line change to go back to the default sphinx-gallery behavior.

If this is desirable I'd be interested in hearing what the criteria mpl-playback would need to reach in order to be an acceptable dependency. The main things that I would like to improve on:

  1. Better test coverage
    • The docs build currently captures the playback capability, but record is untested
  2. Explicitly writing out the playback file json schema
    • Potentially adding optional validation with pydantic
  3. Raising errors/warnings if the hash of the python file is different than the file used to record the json file
  4. Add better typing to all methods + mypy checks

(I'd be happy for PRs of course :) )

PR Checklist

Tests and Styling

  • [NA] Has pytest style unit tests (and pytest passes).
  • [NA] Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • [NA] New features are documented, with examples if plot related.
  • [NA] New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • [NA] API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • [ NA Documentation is sphinx and numpydoc compliant (the docs should build without error).

@story645
Copy link
Member

story645 commented Jul 18, 2022

I'm of course 💯 for, but you may want to put this on a call discussion if you can make any of 'em?

ETA: I think typing would be nice, but hasn't been a criteria for dependencies so not sure that should hold things up.

@ianhi
Copy link
Contributor Author

ianhi commented Jul 18, 2022

Rendered example and thumbnail in gallery

ETA: I think typing would be nice, but hasn't been a criteria for dependencies so not sure that should hold things up.

Good point!

but you may want to put this on a call discussion if you can make any of 'em?

For whatever reason Thursday tends to be a really good day for us to run experiments so it's unlikely (though not impossible) that I'll be able to for a few weeks. But then there's also no big rush here


ooh I also might like to improve the rendering of the fake cursor which is currently just a triangle.

@timhoffm
Copy link
Member

I'm +1 on this. Do you have an estimate how log the example generation takes?

@ianhi
Copy link
Contributor Author

ianhi commented Jul 18, 2022

Do you have an estimate how log the example generation takes?

This is dependent on few settings like fps and what writer you use (e.g. ffmpeg vs pillow) but on my laptop with 24 fps the slider demo gif takes 34 seconds to generate of which 30 seconds was image generation and the rest was writer.finish(). However, I think there's a major optimization opportunity here. Currently I throw in a fig.canvas.draw() at the end of every of every time step to make sure I draw the cursor, but this results in double draws in the slider example bc the callback in the example also calls draw. So with blitting for the cursor or doing something clever with delaying draws I think there could be a 2x speedup on image generation.

Those draws are happening here: https://github.com/ianhi/mpl-playback/blob/06a7faf567e487b49d32468767fd90fb5f659ec9/mpl_playback/playback.py#L245-L248

@QuLogic
Copy link
Member

QuLogic commented Jul 21, 2022

As you know of course, I'm in favour of this.

I wonder if we can get away with something like 12 fps, both for speed and size reasons. It's not a full movie, so we might not need a high frame rate.

@timhoffm
Copy link
Member

A naive calculation gives:
16 widget examples x 30s = 8min additional built time for the docs.

That'd be a lot. If we plan to use this in multiple examples, we definitively need to pull in some of the discussed (or other) performance optimizations.

@tacaswell tacaswell added this to the v3.6.0 milestone Jul 21, 2022
@jklymak
Copy link
Member

jklymak commented Jul 22, 2022

Is there a way to make CI build them much more sparsely (maybe even a snapshot) and the deployed builds take the time to make the full-res movie?

@timhoffm
Copy link
Member

Is there a way to make CI build them much more sparsely (maybe even a snapshot) and the deployed builds take the time to make the full-res movie?

One can probably influence the behavior via an environment variable.

@tacaswell
Copy link
Member

You can probably check if the figure is stale right before you grab the frame and if so, only call draw then.

@QuLogic QuLogic modified the milestones: v3.6.0, v3.6.1 Sep 16, 2022
@QuLogic QuLogic modified the milestones: v3.6.1, v3.6.2 Oct 6, 2022
@QuLogic QuLogic modified the milestones: v3.6.2, v3.6.3 Oct 27, 2022
@ianhi
Copy link
Contributor Author

ianhi commented Nov 18, 2022

Current PR status

Quick update for anyone stumbling across this PR.

The next steps involve making performance improvements to mpl-playback. Unfortunately I don't expect to have much time to focus on that for at least several months (trying to finish my graduate program!). That said I would be happy to review and merge PRs with any performance improvements! I made an issue to track and discuss such improvements here: mpl-extensions/mpl-playback#19 thoughts and PRs most welcome.

@QuLogic QuLogic modified the milestones: v3.6.3, v3.7.0 Jan 11, 2023
@jklymak
Copy link
Member

jklymak commented Jan 26, 2023

I'll move to draft, but please consider closing if this will not be done in a finite time window.

@jklymak jklymak marked this pull request as draft January 26, 2023 02:55
@tacaswell tacaswell modified the milestones: v3.7.0, v3.8.0 Feb 9, 2023
@ksunden ksunden modified the milestones: v3.8.0, v3.9.0 Aug 8, 2023
@ianhi
Copy link
Contributor Author

ianhi commented Aug 18, 2023

with mpl-extensions/mpl-playback#20 (inspired by @story645 ) mpl-playback is now ~50% faster. I think that's going to be the largest single improvement. But I htink there is still potential for some large wins by 1. checking if the figure is stale and using a cached version for grab_frame. 2. implementing blitting for the fake mouse cursor

@ianhi
Copy link
Contributor Author

ianhi commented Aug 18, 2023

Whats a reasonable time across the widget examples to aim for?

Also potentially there could be a build flag where this is run only on production builds or certain PRs?

@timhoffm
Copy link
Member

Whats a reasonable time across the widget examples to aim for?

For release builds, the time does not matter. Only size may need to be considered.

Our current CI doc builds take about 30min, which is already far too long and we should look into ways to trim this down. As a rule of thumb, I wouldn't spend much more than one minute on this for CI doc builds. One can achive this through further speedup and/or only selecting few examples.

Also potentially there could be a build flag where this is run only on production builds or certain PRs?

That's certainly useful.

@QuLogic QuLogic modified the milestones: v3.9.0, v3.9.1 May 10, 2024
@QuLogic QuLogic modified the milestones: v3.9.1, v3.9.2, v3.9-doc Jun 26, 2024
@ianhi
Copy link
Contributor Author

ianhi commented Jul 16, 2024

At the scipy sprints @QuLogic and @story645 helped me look at this a bit and we came to following conclusions:

  1. mpl-playback is basically fully optimized - 99% of the time is spent on writer.grab_frame
  2. Reducing the length and the frame rate of the recordings linearly reduces how long the example takes to generate the gif
  3. We can toggle the gif generation to only run on release build
  4. we can not easily introduce a way for the full build to be triggered on a PR. This is because circleCI does not natively know about github pr labels. The only way would be to use the github API

With the speed improvements and thoughtful recordings of examples I suspect we could get to only 5-10 seconds of generation per example. So that leaves the question to be answered as: "Is that fast enough". and/or are we ok with having the gifs build only on release builds (i.e. devdocs)?

@story645
Copy link
Member

story645 commented Jul 16, 2024

As a rule of thumb, I wouldn't spend much more than one minute on this for CI doc builds.

So I think at sprints @ianhi got it down to about 4 minutes, which I think for doc release builds is well worth it for being able to demonstrate the interactivity of the library. ETA: I think only issue there is maybe low bandwidth situations where we'd want to default to thumbnails, but this is also true for animations.

It'd be awesome if we could limit this to only run when files in widget/event or a subset of narrative docs are changed, but I think that could also be a follow up optimization...or maybe a standalone action that just calls sphinx playback w/ changed files & shows the output so that it's available for reviewers? Which I think is a riff on #23441 (comment)

(No idea if that's doable...)

ETA:

The only way would be to use the github API

I think the auto labeler may be doing this? Or it's doing something based on changed files rather than labels: https://github.com/matplotlib/matplotlib/blob/main/.github/labeler.yml

@timhoffm
Copy link
Member

timhoffm commented Jul 17, 2024

So I think at sprints @ianhi got it down to about 4 minutes, which I think for doc release builds is well worth it for being able to demonstrate the interactivity of the library.

👍

ETA: I think only issue there is maybe low bandwidth situations where we'd want to default to thumbnails, but this is also true for animations.

It's less a problem because we have incremental loading of images now. One could try and inject static thumbnails, but that's only half the fun. Separate topic (completely optional just in case anybody is interested): You could detect the speed either through Network Information API (limited support, but if your browser has it, you'd get the benefit of less-volume downloads) or other client-side detection methods.

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

Successfully merging this pull request may close these issues.

Add gifs of usage to widget examples
7 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.