napari / napari-animation

A napari plugin for making animations
https://napari.github.io/napari-animation/
Other
74 stars 27 forks source link

Saving gif animations broken. TypeError: The keyword `fps` is no longer supported #174

Closed Cardinal3844 closed 9 months ago

Cardinal3844 commented 1 year ago

I get an error when running this minimal example:

import napari
import numpy as np
from napari_animation import Animation

# Generate some example data
image_stack = np.random.rand(10, 64, 64)

# Create a napari viewer 
viewer = napari.Viewer()
viewer.add_image(image_stack)

# Create an animation object and add frames to it
animation = Animation(viewer)

# Iterate over each frame and add it to the animation
for i in range(image_stack.shape[0]):
  viewer.dims.set_current_step(0, i)  # Set the current timepoint
  animation.capture_keyframe()

# Specify the output file name and save the animation as a GIF
output_filename = r'C:\Temp\animation.gif'
animation.animate(output_filename, fps=20, canvas_only=True)

Error:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\projects\napari\napari-animation\napari_animation\animation.py", line 232, in animate
    writer.append_data(image)
  File "c:\projects\virtual_envs\test_venv\lib\site-packages\imageio\v2.py", line 215, in append_data
  File "c:\projects\virtual_envs\test_venv\lib\site-packages\imageio\plugins\pillow.py", line 354, in write
TypeError: The keyword `fps` is no longer supported. Use `duration`(in ms) instead, e.g. `fps=50` == `duration=20` (1000 * 1/50).

Seems like the imagio package was updated but napari-animation is still using the old API?

My module versions:

>pip list --format "freeze"
alabaster==0.7.13
app-model==0.1.4
appdirs==1.4.4
asttokens==2.2.1
attrs==23.1.0
Babel==2.12.1
backcall==0.2.0
build==0.10.0
cachey==0.2.1
certifi==2023.5.7
charset-normalizer==3.1.0
click==8.1.3
cloudpickle==2.2.1
colorama==0.4.6
comm==0.1.3
dask==2023.5.0
debugpy==1.6.7
decorator==5.1.1
docstring-parser==0.15
docutils==0.17.1
executing==1.2.0
freetype-py==2.4.0
fsspec==2023.5.0
HeapDict==1.0.1
hsluv==5.0.3
idna==3.4
imageio==2.28.1
imageio-ffmpeg==0.4.8
imagesize==1.4.1
importlib-metadata==6.6.0
in-n-out==0.1.7
ipykernel==6.23.1
ipython==8.13.2
ipython-genutils==0.2.0
jedi==0.18.2
Jinja2==3.1.2
jsonschema==4.17.3
jupyter_client==8.2.0
jupyter_core==5.3.0
kiwisolver==1.4.4
lazy_loader==0.2
locket==1.0.0
magicgui==0.7.2
markdown-it-py==2.2.0
MarkupSafe==2.1.2
matplotlib-inline==0.1.6
mdurl==0.1.2
mypy-extensions==1.0.0
napari==0.4.17
napari-animation==0.0.6
napari-console==0.0.8
napari-plugin-engine==0.2.0
napari-svg==0.1.6
nest-asyncio==1.5.6
networkx==3.1
npe2==0.7.0
numpy==1.24.3
numpydoc==1.5.0
packaging==23.1
pandas==2.0.1
parso==0.8.3
partd==1.4.0
pickleshare==0.7.5
Pillow==9.5.0
Pint==0.21
pip==23.1.2
platformdirs==3.5.1
pooch==1.7.0
prompt-toolkit==3.0.38
psutil==5.9.5
psygnal==0.9.0
pure-eval==0.2.2
pydantic==1.10.7
Pygments==2.15.1
PyOpenGL==3.1.6
pyproject_hooks==1.0.0
PyQt5==5.15.9
PyQt5-Qt5==5.15.2
PyQt5-sip==12.12.1
pyrsistent==0.19.3
python-dateutil==2.8.2
pytomlpp==1.0.13
pytz==2023.3
PyWavelets==1.4.1
pywin32==306
PyYAML==6.0
pyzmq==25.0.2
qtconsole==5.4.3
QtPy==2.3.1
requests==2.30.0
rich==13.3.5
scikit-image==0.20.0
scipy==1.10.1
setuptools==67.7.2
six==1.16.0
snowballstemmer==2.2.0
Sphinx==4.5.0
sphinxcontrib-applehelp==1.0.4
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
stack-data==0.6.2
superqt==0.4.1
tifffile==2023.4.12
tomli==2.0.1
toolz==0.12.0
tornado==6.3.2
tqdm==4.65.0
traitlets==5.9.0
typer==0.9.0
typing_extensions==4.5.0
tzdata==2023.3
urllib3==2.0.2
vispy==0.11.0
wcwidth==0.2.6
wheel==0.40.0
wrapt==1.15.0
zipp==3.15.0
alisterburt commented 1 year ago

hi @Cardinal3844 - thanks for the report and taking the time to make a nice minimal example!

I've whittled it down to a bug in imageio which I've reported at imageio/imageio#992 - in the meantime I would expect that downgrading pillow to some slightly less recent version would solve the issue until an imageio fix is pushed. Does this work for you?

Cardinal3844 commented 1 year ago

Actually I couldn't find a version that worked, can you suggest one? E.g. I tried Pillow==8.3.2 but still the same error. When I go as low as 8.1.0, I get an exception on install taht Python 3.10 is not supported...

alisterburt commented 1 year ago

I don't know when things changed upstream, did you try downgrading imageio?

psobolewskiPhD commented 9 months ago

So this has been fixed upstream -- sort of. the fps is being converted to the new duration, see: https://github.com/imageio/imageio/pull/1039/files (Man is this a UX setback, FPS is easy to grok, while duration per frame in in ms is 🤯 )

I think here I would advocate keeping fps on our user side but then converting and passing duration to the writer so when the conversion is dropped everything will keep working here?

jni commented 9 months ago

I agree 100% with your assessment @psobolewskiPhD, let's keep fps locally and switch between duration and fps depending on the underlying imageio version. Or, just bump the minimum imageio version and always translate to duration. But I agree a lot that fps is better UX.

psobolewskiPhD commented 9 months ago

I did some more testing: fps useage by napari-animation first breaks with imageio 2.29.0 duration works going back to at least 2.13.0 (2 years ago) -- it looks like the old legacy pillow plugin supported/supports both fps and duration. Also there's already a PR to fix this! https://github.com/napari/napari-animation/pull/182 So I will get that over the line