Skip to content
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

Fading out image not working #152

Closed
kolibril13 opened this issue Mar 2, 2023 · 5 comments · Fixed by #189 or napari/napari#6498
Closed

Fading out image not working #152

kolibril13 opened this issue Mar 2, 2023 · 5 comments · Fixed by #189 or napari/napari#6498
Labels
bug Something isn't working good first issue Good for newcomers

Comments

@kolibril13
Copy link
Contributor

In the below example,

img.opacity = 0
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

should fade out the cell image, but just disappears suddenly.
Afterwards it should fade in again, and works perfectly for the fade in.

img.opacity =1
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

Any idea what is causing this fadeout bug? Thanks for reading this issue! :)

from napari_animation import Animation
from napari_animation.easing import Easing

import napari
from skimage import data

viewer = napari.view_image(data.cells3d(), channel_axis=1, ndisplay=3)


img = viewer.layers[1]
img.opacity =1
viewer.camera.angles = (0, 0, 90)

animation = Animation(viewer)
viewer.camera.zoom = 1
animation.capture_keyframe(steps=30)

viewer.camera.zoom = 2
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)


viewer.camera.angles = (20, -25, 140)
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

img.opacity = 0 # <- why is this not fading out, but disappearing suddenly?
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

img.opacity =1
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)


viewer.camera.zoom = 1
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

viewer.camera.angles = (0, 0, 90)
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)


animation.animate("hello.mp4", canvas_only=True, fps=60)
napari_video@2023-03-02@12-50-57.mp4
@alisterburt
Copy link
Collaborator

hey! interpolation is type based in napari-animation, I assume you are setting integers and napari is not coercing them to floats, could you check if this is indeed the root cause? Would ideally be fixed upstream in napari

@kolibril13
Copy link
Contributor Author

kolibril13 commented Mar 2, 2023

Good idea!
I just tried

viewer.camera.angles = (20, -25, 140)
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

img.opacity = 0.0
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

img.opacity = 1.0
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

but that did not solve the problem.
In the first example, both values were ints.
And there the fadeout did not work, but the fade in works.
So ints are maybe not the problem.

Just tested again a new script, here I only set the opacity to 0.5, but it completely removes it.
Is there maybe something happening internally that sets the opacity to 0 ?
If yes, then this might be the same bug as #149

from napari_animation import Animation
from napari_animation.easing import Easing

img = viewer.layers[1]
img.opacity =1
viewer.camera.angles = (0, 0, 90)

animation = Animation(viewer)

img.opacity = 1
animation.capture_keyframe(steps=60)

animation.capture_keyframe(steps=120)


img.opacity = 0.5 # <- here, the opacity is set to zero I guess
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)

img.opacity = 1.0
animation.capture_keyframe(steps=60, ease=Easing.QUADRATIC)
napari_video@2023-03-02@13-59-08.mp4

@alisterburt
Copy link
Collaborator

Thanks for spelunking - I'll have to dig properly to figure this out but the reproducible example is a super useful starting point

@alisterburt alisterburt added the good first issue Good for newcomers label Mar 2, 2023
@psobolewskiPhD
Copy link
Member

I can reproduce this too. It does seem related to #149
Again the viewer_state of key_frames is correct, so I assume it's an interpolation issue with decreasing values.

@psobolewskiPhD
Copy link
Member

Ok, here the snippets are the problem actaully. @alisterburt was on the right track with typing issue.
So the snippet has img.opacity=1 This makes starting opacity an int:

In [2]: viewer.layers[-1]._get_state()
Out[2]: 
{'name': 'Image [1]',
 'metadata': {},
 '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],
 'affine': array([[1., 0., 0., 0.],
        [0., 1., 0., 0.],
        [0., 0., 1., 0.],
        [0., 0., 0., 1.]]),
 'opacity': 1,

This is then stored in the viewer_state and when interpolation is performed, the wrong interpolation is chosen here because the initial value (a) is an int:

def interpolate_num(a: Number, b: Number, fraction: float) -> Number:
"""Linear interpolation for numeric types.
Parameters
----------
a : Number
initial value
b : Number
final value
fraction : float
fraction to interpolate to between a and b.
Returns
----------
: numeric type
Interpolated value between a and b at fraction.
"""
number_cls = type(a)
return number_cls(a + (b - a) * fraction)

So you need to set opacity as a float currently, but this should probably be coerced on the napari side?

@psobolewskiPhD psobolewskiPhD added the bug Something isn't working label Nov 27, 2023
jni pushed a commit to napari/napari that referenced this issue Nov 28, 2023
# References and relevant issues

At present, despite docstrings stating that gamma and opacity are floats
are not enforced by napari. Worse yet, we set the default in a number of
places to `1` and not `1.0`.
Downstream, vispy does coerce gamma to float so it's not so obvious, but
it creeps up if you interrogate the layer state using either
`viewer.layers[0].gamma` or `viewer.layers[0]._get_state()` which will
return `1` and a type of `int`
See: napari/napari-animation#149
Closes: napari/napari-animation#149
Same can happen to opacity, but it's more subtle because of the way the
slider value is used.
Closes: napari/napari-animation#152

# Description

In this PR I set gamma and opacity defaults to `1.0` where they had been
previously set to `1` and in the `gamma.setter` and `opacity.setter` I
coerce to float so that the user doesn't shoot themselves in the foot
accidentally.
psobolewskiPhD added a commit that referenced this issue Dec 14, 2023
This PR changes `interpolate_num`behaviour to fallback to float like a
number if the first argument is Interger and the second one is Real.

closes #149 
closes #152

---------

Co-authored-by: Peter Sobolewski <76622105+psobolewskiPhD@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers
Projects
None yet
3 participants