napari / napari-animation

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

Surface rendering throws error (`'dict' object has no attribute 'face'`) #145

Closed jo-mueller closed 1 year ago

jo-mueller commented 1 year ago

Hi napari-animators,

I am receiving an error when using napari-animation to render a 4D surface (25 timepoints), but the rendering usually stops after writing the first one or two frames. I've played a bit with the frames (e.g., different ease values) but to no avail.

This is the full traceback:

File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari_animation\_qt\animation_widget.py", line 163, in _save_callback
    self.animation.animate(**animation_kwargs)
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari_animation\animation.py", line 214, in animate
    for frame_index, image in enumerate(frame_generator):
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari_animation\frame_sequence.py", line 121, in iter_frames
    frame = state.render(viewer, canvas_only=canvas_only)
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari_animation\viewer_state.py", line 79, in render
    self.apply(viewer)
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari_animation\viewer_state.py", line 50, in apply
    viewer.dims.update(self.dims)
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\utils\events\evented_model.py", line 316, in update
    setattr(self, key, value)
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\utils\events\evented_model.py", line 241, in __setattr__
    getattr(self.events, name)(value=after)  # emit event
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\utils\events\event.py", line 757, in __call__
    self._invoke_callback(cb, event if pass_event else None)
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\utils\events\event.py", line 794, in _invoke_callback
    _handle_exception(
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\utils\events\event.py", line 783, in _invoke_callback
    cb()
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\components\viewer_model.py", line 348, in _update_layers
    layer._slice_dims(
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\layers\base\base.py", line 1020, in _slice_dims
    self._update_dims()
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\layers\base\base.py", line 705, in _update_dims
    self.refresh()  # This call is need for invalidate cache of extent in LayerList. If you remove it pleas ad another workaround.
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\layers\base\base.py", line 1210, in refresh
    self.events.set_data()  # refresh is called in _update_dims which means that extent cache is invalidated. Then, base on this event extent cache in layerlist is invalidated.
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\utils\events\event.py", line 757, in __call__
    self._invoke_callback(cb, event if pass_event else None)
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\utils\events\event.py", line 794, in _invoke_callback
    _handle_exception(
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\utils\events\event.py", line 783, in _invoke_callback
    cb()
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\_vispy\layers\surface.py", line 91, in _on_data_change
    self._on_face_normals_change()
  File "C:\Users\myname\Anaconda3\envs\stress\lib\site-packages\napari\_vispy\layers\surface.py", line 140, in _on_face_normals_change
    self.node.face_normals.visible = self.layer.normals.face.visible
AttributeError: 'dict' object has no attribute 'face'

Here's my package information:

napari: 0.4.17
Platform: Windows-10-10.0.19044-SP0
Python: 3.9.13 (main, Aug 25 2022, 23:51:50) [MSC v.1916 64 bit (AMD64)]
Qt: 5.15.2
PyQt5: 5.15.7
NumPy: 1.23.3
SciPy: 1.9.1
Dask: 2022.6.1
VisPy: 0.11.0
magicgui: 0.6.0
superqt: 0.3.8
in-n-out: 0.1.5
app-model: 0.0.9
npe2: 0.6.1

OpenGL:
- GL version: 4.6.0 NVIDIA 517.13
- MAX_TEXTURE_SIZE: 32768

Screens:
- screen 1: resolution 1920x1080, scale 2.0

I'm unfortunately not able to provide the data I used to reproduce :/

jo-mueller commented 1 year ago

Just tried on a different machine where it works. Package configuration:

napari: 0.4.15
Platform: Windows-10-10.0.22000-SP0
Python: 3.9.12 (main, Apr 4 2022, 05:22:27) [MSC v.1916 64 bit (AMD64)]
Qt: 5.12.9
PyQt5: 5.12.3
NumPy: 1.22.4
SciPy: 1.8.1
Dask: 2022.6.1
VisPy: 0.9.6

OpenGL:
- GL version: 4.6.0 - Build 26.20.100.7985
- MAX_TEXTURE_SIZE: 16384

Screens:
- screen 1: resolution 1920x1080, scale 1.0

Plugins:
- console: 0.0.4
- napari-assistant: 0.3.8
- napari-process-points-and-surfaces: 0.3.1
- napari-segment-blobs-and-things-with-membranes: 0.2.22
- napari-stress2: 0.0.15
- napari-time-slicer: 0.4.8
- napari-tools-menu: 0.1.15
- napari_skimage_regionprops1: 0.5.2
- napari_skimage_regionprops2: 0.5.2
- ome-types: 0.3.0
- scikit-image: 0.4.15
- svg: 0.1.6
alisterburt commented 1 year ago

Thanks for the report @jo-mueller interesting! @brisvag might have some insight here - any ideas why the face normals wouldn't always be present on the layer?

brisvag commented 1 year ago

Yup, found the issue: when I added normals tot he surface layer, I allowed setting them by passing either a SurfaceNormals model or a dict. However, I didn't implement the property to autoconvert to SurfaceNormals, so if you pass a dict, you end up with a dict on the layer object... which then breaks when later it is assumed to be a dict :P

Here's a PR with fix: napari/napari#5501

Until this gets merge and released, you may be able to fix it by passing the right object to it:

from napari.layers.surface.normals import SurfaceNormals

my_dict_of_normals = {'face'=...}

viewer.add_surface(..., normals=SurfaceNormals(**my_dict_of_normals))

But I'm not sure if this will fix how napari animation handles it.

kephale commented 1 year ago

FYI, @brisvag 's PR (https://github.com/napari/napari/pull/5501) does resolve this issue with recording animations of Surfaces for me.

brisvag commented 1 year ago

Merged the PR. This will is will be fixed with napari>0.4.17.