Skip to content

Timeline widget - #261

Open
brisvag wants to merge 27 commits into
napari:mainfrom
brisvag:feature/timeline
Open

Timeline widget#261
brisvag wants to merge 27 commits into
napari:mainfrom
brisvag:feature/timeline

Conversation

@brisvag

@brisvag brisvag commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Description

This adds a widget with tracks and keyframes to give higher control to the animation machinery.

test.mp4

Unfortunately the current code here is very hard-wired around keyframes being full viewer states, so this new animation widget is effectively fully separate.

In my opinion, if we get the api cleaned up, this new widget and backend can be a full replacement of the current code, giving more control over the general structure of the animation, as well as more interactivity to the widget (e.g: already has #100 plus other quality of life things like looping/pingpong and selecting a replay range).

The current behaviour (single keyframe for the whole viewer), which is very simple and intuitive for simple animations, can still be replicated by selecting the viewer track, which interpolates the whole viewer, with the added benefit of being able to interactively move the keyframes and the stuff mentioned above!


Instead of making a a plugin (https://github.com/brisvag/napari-animation-timeline), opening a PR here to see if we can do a proper integration.

Note that this PR includes #260, so the diff looks crazy, but basically I only added 1 file (_qt/timeline_widget.py).

The bulk of the code is napari-agnostic (almost...) and lives here: github.com/brisvag/qt-animation-timeline/

@codecov

codecov Bot commented Apr 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 43.53741% with 83 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.08%. Comparing base (b4ffcf8) to head (cd33a78).
⚠️ Report is 16 commits behind head on main.

Files with missing lines Patch % Lines
src/napari_animation/_qt/timeline_widget.py 43.06% 78 Missing ⚠️
src/napari_animation/_qt/animation_widget.py 0.00% 3 Missing ⚠️
src/napari_animation/_qt/savedialog_widget.py 33.33% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #261      +/-   ##
==========================================
- Coverage   81.72%   76.08%   -5.65%     
==========================================
  Files          20       21       +1     
  Lines         810      949     +139     
==========================================
+ Hits          662      722      +60     
- Misses        148      227      +79     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@willingc

Copy link
Copy Markdown
Contributor

Yikes, this is a big PR. If you are able, it might make sense to split out general cleanup and edits from the widget.

@brisvag

brisvag commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

Merged #260, now it's all nice and clean!

@willingc willingc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A few small things...

@brisvag Looks awesome.

Comment thread src/napari_animation/_qt/timeline_widget.py
Comment thread src/napari_animation/_qt/timeline_widget.py
@psobolewskiPhD

Copy link
Copy Markdown
Member

One concern: your package has a dependency on pyqt6, which would make napari-animation depend on pyqt6, which would break e.g. the bundle. I think napari-animation is very much a flagship plugin -- which doesn't get enough press! -- so this concerns me. Is there a way you can make things work with pyside6?

@brisvag

brisvag commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

Oh, that was just a mistake 🤔 I thought I did everything with qtpy....

Yep indeed everything works. I just put it in the runtime deps by mistake instead of the test ones!

@brisvag

brisvag commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

Updated the qt package on pypi to remove the unnecessary pyqt6 dep and with the links by @psobolewskiPhD!

@willingc

Copy link
Copy Markdown
Contributor

We missed moving the _qt tests out of src in #264 @brisvag

@brisvag

brisvag commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

Move those as well, and now this can both read and write movies and export/import the animation itself as json!

@willingc willingc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looking good @brisvag. A few suggestions on adding small docstrings for IDE tooltips.

Comment thread src/napari_animation/_qt/timeline_widget.py Outdated
Comment thread src/napari_animation/_qt/timeline_widget.py
Comment thread src/napari_animation/_qt/timeline_widget.py
Comment thread src/napari_animation/_qt/timeline_widget.py
Comment thread src/napari_animation/_qt/timeline_widget.py Outdated
@willingc

Copy link
Copy Markdown
Contributor

Let's try pinning Pydantic in tox.ini for 3.10 and pyside2

pydantic<2.11 # psygnal used by napari expects older pydantic internals; avoid breakage on newer pydantic

brisvag and others added 3 commits April 20, 2026 11:51
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
@brisvag

brisvag commented Apr 20, 2026

Copy link
Copy Markdown
Contributor Author

Mmm I think the problem is that qt-animation-timeline uses pydantic>2 stuff, but napari <0.7.0 does not support pydantic v2 properly, so we get conflicts... Though I'm confused about why the errors are so unclear.

@brisvag

brisvag commented May 18, 2026

Copy link
Copy Markdown
Contributor Author

I don't undersdtand this failure, no matter what I try :/

@brisvag

brisvag commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

Yay, finally got tests running an passing! Thanks @Czaki. Now this should be good for a final review/merge!

TimMonko added a commit to napari/docs that referenced this pull request Jun 8, 2026
# References and relevant issues

Closes #680 🥳 🎉 👏 

# Description

## Reproducibility 

napari/napari-animation#261 introduces a timeline-widget to the plugin.
I wanted to both practically review this, and take advantage of the
easily modifiable and saveable json to redo the homepage video. To
accomplish this PR I had to learn quite a bit, including about
napari-animation generally, more about zarrs local vs remote, async, and
video encoding (this was the hardest part!).

This script uses a uv header and is currently pointed at
https://github.com/TimMonko/napari-animation.git@766dbbbcd0ec8607e67f49da0402ad41d4e512fb
because this has Windows patches and webm functionality (because webm
really is 10X smaller in this scenario).

In the future, re-rendering the homepage is just: `uv run
docs/_scripts/homepage_video.py render`
One really cool part of how napari-animation works is that the data can
be remote still, the rendering take a _long_ time (because of that) and
it still is a 1-to-1 rendering compared to having the data locally 😁
This also serves as functional insight into where napari-animation
can/should go.

## Design choices

Some opinionated choices include the following, the I think for all of
them being able to swap with napari-animation mid timeline would be
cool!
1. using the `magma` LUT instead of grayscale. I like this pop of color
and I think it does give a bit of insight into rendering.
2. attenuated_mip rendering only. 
3. the way it spins... this is troublesome because the animation
interpolation wants to only do positive angles so it causes compelte
overrotation in some cases causing these to be quite finnicky
4. the overall length is shorter, and I kind of dislike how it has less
"human pauses" but I've quickly gotten used to it
5. used ndevio to load the image because I knew it would handle the
metadata as I wanted :P can re-evaluate
6. turned the scalebar on to show off our unit aware rendering and
scalebar
7. turned on the axes overlay to better show the dimensionality of the
viewer
8. added axis labels

<img width="1255" height="999" alt="image"
src="https://github.com/user-attachments/assets/f0879633-479d-4fc9-a275-828f871b9f44"
/>

<img width="1258" height="858" alt="image"
src="https://github.com/user-attachments/assets/37e355c6-a908-4486-b464-f81ca53e2f97"
/>


## And more notes

- I used the css for the feature example to add a drop shadow and
rounded corners to the video.
- I overwrote the screenshot -- just noting that the html suggests an
mp4, but I don't see one committed
- This could be a higher resolution, but I opted to keep the filesize
comparable to before. I didn't notice that much difference either
doubling the quality, though it double the filesize to ~16MB.

---------

Co-authored-by: Melissa Weber Mendonça <melissawm@gmail.com>
Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants