napari / napari-animation

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

Use full layer state #118

Closed brisvag closed 1 year ago

brisvag commented 2 years ago

Simple change to use Layer._get_state instead of Layer._get_base_state. Quick tests locally seem to work! Closes #116 .

alisterburt commented 2 years ago

getting some state interpolation issues

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~/Programming/napari-animation/napari_animation/_qt/animation_widget.py in _on_slider_moved(self=, event=6)
    150         if frame_index  len(self.animation._frames):
    151             with self.animation.key_frames.selection.events.active.blocker():
--> 152                 self.animation.set_movie_frame_index(frame_index)
        self.animation.set_movie_frame_index = >
        frame_index = 6
    153 
    154     def _save_callback(self, event=None):

~/Programming/napari-animation/napari_animation/animation.py in set_movie_frame_index(self=, index=6)
    116                 self.key_frames.selection.active = key_frame
    117 
--> 118             self._frames.set_movie_frame_index(self.viewer, index)
        self._frames.set_movie_frame_index = >
        self.viewer = Viewer(axes=Axes(visible=False, labels=True, colored=True, dashed=False, arrows=True), camera=Camera(center=(63.5, 63.5, 63.5), zoom=3.6382809412126687, angles=(10.407740663429987, -21.591742422259745, 63.95548194645493), perspective=0.0, interactive=True), cursor=Cursor(position=(-22.69257430759626, 160.24064513779757, 151.84652934060108), scaled=True, size=10, style=), dims=Dims(ndim=3, ndisplay=3, last_used=0, range=((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0)), current_step=(64, 64, 64), order=(0, 1, 2), axis_labels=('0', '1', '2')), grid=GridCanvas(stride=1, shape=(-1, -1), enabled=False), layers=[, ], scale_bar=ScaleBar(visible=False, colored=False, ticks=True, position=, font_size=10, unit=None), text_overlay=TextOverlay(visible=False, color=(0.5, 0.5, 0.5, 1.0), font_size=10, position=, text=''), overlays=Overlays(interaction_box=InteractionBox(points=None, show=False, show_handle=False, show_vertices=False, selection_box_drag=None, selection_box_final=None, transform_start=, transform_drag=, transform_final=, transform=, allow_new_selection=True, selected_vertex=None)), help='enter paint or fill mode to edit labels', status='blob ID [-23 160 152]: 0', tooltip=Tooltip(visible=False, text=''), theme='system', title='napari', mouse_move_callbacks=[.mouse_move at 0x7fe9437cc1f0>], mouse_drag_callbacks=[.mouse_drag at 0x7fe942f8e670>], mouse_double_click_callbacks=[], mouse_wheel_callbacks=[], _persisted_mouse_event={}, _mouse_drag_gen={}, _mouse_wheel_gen={}, keymap={'Shift': .hold_to_lock_aspect_ratio at 0x7fe942f8eb80>, 'Control-Shift-R': , 'Control-Shift-A': , 'Alt-F': >, 'Alt-R': >, 'Alt-D': >, 'Alt-A': . at 0x7fe9459b5310>, 'Alt-B': . at 0x7fe9459b53a0>})
        index = 6
    119             self._current_frame = index
    120 

~/Programming/napari-animation/napari_animation/frame_sequence.py in set_movie_frame_index(self=, viewer=Viewer(axes=Axes(visible=False, labels=True, col..._callbacks.. at 0x7fe9459b53a0>}), index=6)
    172 
    173     def set_movie_frame_index(self, viewer: napari.viewer.Viewer, index: int):
--> 174         self[index].apply(viewer)
        self = 
        index.apply = undefined
        viewer = Viewer(axes=Axes(visible=False, labels=True, colored=True, dashed=False, arrows=True), camera=Camera(center=(63.5, 63.5, 63.5), zoom=3.6382809412126687, angles=(10.407740663429987, -21.591742422259745, 63.95548194645493), perspective=0.0, interactive=True), cursor=Cursor(position=(-22.69257430759626, 160.24064513779757, 151.84652934060108), scaled=True, size=10, style=), dims=Dims(ndim=3, ndisplay=3, last_used=0, range=((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0)), current_step=(64, 64, 64), order=(0, 1, 2), axis_labels=('0', '1', '2')), grid=GridCanvas(stride=1, shape=(-1, -1), enabled=False), layers=[, ], scale_bar=ScaleBar(visible=False, colored=False, ticks=True, position=, font_size=10, unit=None), text_overlay=TextOverlay(visible=False, color=(0.5, 0.5, 0.5, 1.0), font_size=10, position=, text=''), overlays=Overlays(interaction_box=InteractionBox(points=None, show=False, show_handle=False, show_vertices=False, selection_box_drag=None, selection_box_final=None, transform_start=, transform_drag=, transform_final=, transform=, allow_new_selection=True, selected_vertex=None)), help='enter paint or fill mode to edit labels', status='blob ID [-23 160 152]: 0', tooltip=Tooltip(visible=False, text=''), theme='system', title='napari', mouse_move_callbacks=[.mouse_move at 0x7fe9437cc1f0>], mouse_drag_callbacks=[.mouse_drag at 0x7fe942f8e670>], mouse_double_click_callbacks=[], mouse_wheel_callbacks=[], _persisted_mouse_event={}, _mouse_drag_gen={}, _mouse_wheel_gen={}, keymap={'Shift': .hold_to_lock_aspect_ratio at 0x7fe942f8eb80>, 'Control-Shift-R': , 'Control-Shift-A': , 'Alt-F': >, 'Alt-R': >, 'Alt-D': >, 'Alt-A': . at 0x7fe9459b5310>, 'Alt-B': . at 0x7fe9459b53a0>})
    175         self._current_index = index
    176 

~/Programming/napari-animation/napari_animation/frame_sequence.py in __getitem__(self=, key=6)
     99                 self._cache[key] = kf0.viewer_state
    100             else:
--> 101                 self._cache[key] = self._interpolate_state(
        self._cache = {30: ViewerState(camera={'center': (63.5, 63.5, 63.5), 'zoom': 3.6382809412126687, 'angles': (-129.66942878564012, 47.1247789077326, -35.3139085590186), 'perspective': 0.0, 'interactive': True}, dims={'ndim': 3, 'ndisplay': 3, 'last_used': 0, 'range': ((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0)), 'current_step': (64, 64, 64), 'order': (0, 1, 2), 'axis_labels': ('0', '1', '2')}, layers={'blobs': {'name': 'blobs', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 1.0, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'rgb': False, 'multiscale': False, 'colormap': 'gray', 'contrast_limits': [0.0, 1.0], 'interpolation': 'linear', 'rendering': 'mip', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'iso_threshold': 0.5, 'attenuation': 0.05, 'gamma': 1, 'data':  (128, 128, 128) float64}, 'blob ID': {'name': 'blob ID', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 0.7, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'multiscale': False, 'num_colors': 50, 'properties': {}, 'rendering': 'iso_categorical', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'seed': 0.5, 'data':  (128, 128, 128) int32, 'color': {0:  (4,) float32, None:  (4,) float32}, 'features': Empty DataFrame
Columns: []
Index: []}}), 15: ViewerState(camera={'center': (63.5, 63.5, 63.5), 'zoom': 3.6382809412126687, 'angles': (13.310058859301877, 40.10598519124094, 116.58883744954004), 'perspective': 0.0, 'interactive': True}, dims={'ndim': 3, 'ndisplay': 3, 'last_used': 0, 'range': ((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0)), 'current_step': (64, 64, 64), 'order': (0, 1, 2), 'axis_labels': ('0', '1', '2')}, layers={'blobs': {'name': 'blobs', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 1.0, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'rgb': False, 'multiscale': False, 'colormap': 'gray', 'contrast_limits': [0.0, 1.0], 'interpolation': 'linear', 'rendering': 'mip', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'iso_threshold': 0.5, 'attenuation': 0.05, 'gamma': 1, 'data':  (128, 128, 128) float64}, 'blob ID': {'name': 'blob ID', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 0.7, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'multiscale': False, 'num_colors': 50, 'properties': {}, 'rendering': 'iso_categorical', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'seed': 0.5, 'data':  (128, 128, 128) int32, 'color': {0:  (4,) float32, None:  (4,) float32}, 'features': Empty DataFrame
Columns: []
Index: []}}), 0: ViewerState(camera={'center': (63.5, 63.5, 63.5), 'zoom': 3.6382809412126687, 'angles': (10.407740663429989, -21.591742422259745, 63.955481946454945), 'perspective': 0.0, 'interactive': True}, dims={'ndim': 3, 'ndisplay': 3, 'last_used': 0, 'range': ((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0)), 'current_step': (64, 64, 64), 'order': (0, 1, 2), 'axis_labels': ('0', '1', '2')}, layers={'blobs': {'name': 'blobs', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 1.0, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'rgb': False, 'multiscale': False, 'colormap': 'gray', 'contrast_limits': [0.0, 1.0], 'interpolation': 'linear', 'rendering': 'mip', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'iso_threshold': 0.5, 'attenuation': 0.05, 'gamma': 1, 'data':  (128, 128, 128) float64}, 'blob ID': {'name': 'blob ID', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 0.7, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'multiscale': False, 'num_colors': 50, 'properties': {}, 'rendering': 'iso_categorical', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'seed': 0.5, 'data':  (128, 128, 128) int32, 'color': {0:  (4,) float32, None:  (4,) float32}, 'features': Empty DataFrame
Columns: []
Index: []}})}
        key = 6
        self._interpolate_state = >
        kf0.viewer_state = ViewerState(camera={'center': (63.5, 63.5, 63.5), 'zoom': 3.6382809412126687, 'angles': (10.407740663429989, -21.591742422259745, 63.955481946454945), 'perspective': 0.0, 'interactive': True}, dims={'ndim': 3, 'ndisplay': 3, 'last_used': 0, 'range': ((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0)), 'current_step': (64, 64, 64), 'order': (0, 1, 2), 'axis_labels': ('0', '1', '2')}, layers={'blobs': {'name': 'blobs', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 1.0, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'rgb': False, 'multiscale': False, 'colormap': 'gray', 'contrast_limits': [0.0, 1.0], 'interpolation': 'linear', 'rendering': 'mip', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'iso_threshold': 0.5, 'attenuation': 0.05, 'gamma': 1, 'data':  (128, 128, 128) float64}, 'blob ID': {'name': 'blob ID', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 0.7, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'multiscale': False, 'num_colors': 50, 'properties': {}, 'rendering': 'iso_categorical', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'seed': 0.5, 'data':  (128, 128, 128) int32, 'color': {0:  (4,) float32, None:  (4,) float32}, 'features': Empty DataFrame
Columns: []
Index: []}})
        kf1.viewer_state = ViewerState(camera={'center': (63.5, 63.5, 63.5), 'zoom': 3.6382809412126687, 'angles': (13.310058859301877, 40.10598519124094, 116.58883744954004), 'perspective': 0.0, 'interactive': True}, dims={'ndim': 3, 'ndisplay': 3, 'last_used': 0, 'range': ((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0)), 'current_step': (64, 64, 64), 'order': (0, 1, 2), 'axis_labels': ('0', '1', '2')}, layers={'blobs': {'name': 'blobs', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 1.0, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'rgb': False, 'multiscale': False, 'colormap': 'gray', 'contrast_limits': [0.0, 1.0], 'interpolation': 'linear', 'rendering': 'mip', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'iso_threshold': 0.5, 'attenuation': 0.05, 'gamma': 1, 'data':  (128, 128, 128) float64}, 'blob ID': {'name': 'blob ID', 'scale': [1.0, 1.0, 1.0], 'translate': [0.0, 0.0, 0.0], 'rotate': [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], 'shear': [0.0, 0.0, 0.0], 'opacity': 0.7, 'blending': 'translucent', 'visible': True, 'experimental_clipping_planes': [], 'multiscale': False, 'num_colors': 50, 'properties': {}, 'rendering': 'iso_categorical', 'depiction': 'volume', 'plane': {'normal': (1, 0, 0), 'position': (0, 0, 0), 'thickness': 1.0}, 'seed': 0.5, 'data':  (128, 128, 128) int32, 'color': {0:  (4,) float32, None:  (4,) float32}, 'features': Empty DataFrame
Columns: []
Index: []}})
        frac = 0.4
        self.state_interpolation_map = {'camera.angles': )>, 'camera.zoom': )>}
    102                     kf0.viewer_state,
    103                     kf1.viewer_state,

~/Programming/napari-animation/napari_animation/frame_sequence.py in _interpolate_state(self=, from_state={'camera': {'angles': (10.407740663429989, -21.591742422259745, 63.955481946454945), 'center': (63.5, 63.5, 63.5), 'interactive': True, 'perspective': 0.0, 'zoom': 3.6382809412126687}, 'dims': {'axis_labels': ('0', '1', '2'), 'current_step': (64, 64, 64), 'last_used': 0, 'ndim': 3, 'ndisplay': 3, 'order': (0, 1, 2), 'range': ((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0))}, 'layers': {'blob ID': {'blending': 'translucent', 'color': {0:  (4,) float32, None:  (4,) float32}, 'data':  (128, 128, 128) int32, 'depiction': 'volume', 'experimental_clipping_planes': [], 'features': Empty DataFrame
Columns: []
Index: [], 'multiscale': False, 'name': 'blob ID', 'num_colors': 50, 'opacity': 0.7, ...}, 'blobs': {'attenuation': 0.05, 'blending': 'translucent', 'colormap': 'gray', 'contrast_limits': [0.0, 1.0], 'data':  (128, 128, 128) float64, 'depiction': 'volume', 'experimental_clipping_planes': [], 'gamma': 1, 'interpolation': 'linear', 'iso_threshold': 0.5, ...}}}, to_state={'camera': {'angles': (13.310058859301877, 40.10598519124094, 116.58883744954004), 'center': (63.5, 63.5, 63.5), 'interactive': True, 'perspective': 0.0, 'zoom': 3.6382809412126687}, 'dims': {'axis_labels': ('0', '1', '2'), 'current_step': (64, 64, 64), 'last_used': 0, 'ndim': 3, 'ndisplay': 3, 'order': (0, 1, 2), 'range': ((0.0, 128.0, 1.0), (0.0, 128.0, 1.0), (0.0, 128.0, 1.0))}, 'layers': {'blob ID': {'blending': 'translucent', 'color': {0:  (4,) float32, None:  (4,) float32}, 'data':  (128, 128, 128) int32, 'depiction': 'volume', 'experimental_clipping_planes': [], 'features': Empty DataFrame
Columns: []
Index: [], 'multiscale': False, 'name': 'blob ID', 'num_colors': 50, 'opacity': 0.7, ...}, 'blobs': {'attenuation': 0.05, 'blending': 'translucent', 'colormap': 'gray', 'contrast_limits': [0.0, 1.0], 'data':  (128, 128, 128) float64, 'depiction': 'volume', 'experimental_clipping_planes': [], 'gamma': 1, 'interpolation': 'linear', 'iso_threshold': 0.5, ...}}}, fraction=0.4, state_interpolation_map={'camera.angles': )>, 'camera.zoom': )>})
    149             v1 = nested_get(to_state, keys)
    150 
--> 151             interp_func = interp_map.get(sep.join(keys), Interpolation.DEFAULT)
        interp_func = )>
        interp_map.get = 
        sep.join = 
        keys = ['layers', 'blob ID', 'color', 0]
        global Interpolation.DEFAULT = )>
    152 
    153             nested_set(state, keys, interp_func(v0, v1, fraction))

TypeError: sequence item 3: expected str instance, int found

need to look a bit more closely

alisterburt commented 2 years ago

hah, okay - the way we interpolate state is a bit borked and probably needs to be reworked before we can move forward here

specifically how it's borked:

We should probably interpolate the state more directly, rather than this nested get/set business

JoOkuma commented 2 years ago

Hey @brisvag and @alisterburt , is there anything that I can do to help this issue and #119 get merged?

I was able to hack my implementation to interpolate the state that I needed but I think it would be beneficial to have this merged.

Thanks,

alisterburt commented 2 years ago

Hey @JoOkuma - thanks for popping up!

A review/some testing of #119 would be great - I took a quick look and it seems okay/I remember where I was going with it

Once that's done I think this PR can be merged too!

brisvag commented 2 years ago

I noticed this old unmerged PR in my history. What is the state of things?

JoOkuma commented 2 years ago

The other PR should be done but the windows CI is broken. It happened to some of my plugins before, I can take a look at it soon.

JoOkuma commented 2 years ago

@brisvag I fixed the CI on #120. I think this PR and #119 should be good after merging it.