Open kolibril13 opened 1 year ago
Hey @kolibril13 - this is cool, it feels like an alternative method for generating a FrameSequence
- I'm not exactly sure of the API in manim but you could...
If we do end up integrating this Animation
might become KeyFrameAnimation
and this could be a ProceduralAnimation
- the render method might need to be moved onto the framesequence in that case
sound reasonable?
write functions for each parameter in terms of t
I'm not a fan of case discrimination (see in example below in zoom_over_time
), but yes, that would work.
I'm not familiar with the FrameSequence
module, but I think key_frame = viewer.screenshot()
is most likely not the object that should be phrased to it.
Therefore, this below example is only a sketch, and won't actually run.
@alisterburt : If you're interested, feel free to test if you can make my prototype code run :)
def angle_over_time(t):
return (0, 30*np.sin((t*np.pi)), 50)
def zoom_over_time(t):
zoom = 0
start_time = 1
if t < start_time:
zoom = 2
# zoom starts for t threshold
elif start_time < t:
zoom = t -1
return zoom
my_key_frames = []
for t in np.linspace(0,4, 300):
viewer.camera.angles = angle_over_time(t)
viewer.camera.zoom = zoom_over_time(t)
key_frame = viewer.screenshot() # <- this should probably be something else.
my_key_frames.append(key_frame)
fs = FrameSequence(key_frames = my_key_frames)
animation = Animation(frame_sequence=fs, viewer=viewer, fps=30) # <- this should probably be something else as well.
# and here should happend the rendering
Procedural animations are animation that are generated automatically via mathematical transformations that occur over time. E.g. manim can produce procedural animations with the
t.add_updater(foo)
function. I just wrote a manim script that is connected to the napari viewer, and it produces the below animation. Note that the camera is panning in a sinusoidal path, while other parameters (zoom, opacity, contrast limits) are changing simultaneously. I think that won't be possible by only using key frames. It would open up more possible animations if napari-animation would support these procedural animations as well.https://user-images.githubusercontent.com/44469195/223225956-2a461fbf-68fc-4f14-92d7-c78daedd4bfe.mp4
Click here to see the script
```python import napari from skimage import data import numpy as np from manim import * viewer = napari.view_image(data.cells3d(), channel_axis=1, ndisplay=3) viewer.camera.angles = (0, 0, 90) class Example(Scene): def construct(self): self.camera.background_color = BLUE_A img = viewer.screenshot(canvas_only=True, flash=False) t = ImageMobject(img) t.time = 0 self.add(t) tr_zoom = ValueTracker(1) contrast_tracker = ValueTracker(65535) # dark limit def foo(mob,dt): mob.time += dt SECOND = 1 def bar(mob): viewer.camera.angles = (0, 30*np.sin((mob.time*PI/11*2)), 50) viewer.camera.zoom = tr_zoom.get_value() viewer.layers[0].contrast_limits = (0, contrast_tracker.get_value()) img = viewer.screenshot(canvas_only=True, flash=False) new_mob = ImageMobject(img) mob.become(new_mob) t.add_updater(foo) t.add_updater(bar) viewer.layers[1].opacity = 1 self.play(tr_zoom.animate.set_value(2), rate_func=smooth, run_time=SECOND) self.play(contrast_tracker.animate.set_value(19500), rate_func=smooth, run_time=SECOND) #bright limit self.wait(SECOND) viewer.layers[1].opacity = 0 self.play(tr_zoom.animate.set_value(4), rate_func=smooth, run_time=SECOND) self.wait(SECOND) self.wait(SECOND) self.play(tr_zoom.animate.set_value(2), rate_func=smooth, run_time=SECOND) self.wait(SECOND) viewer.layers[1].opacity = 1 self.wait(SECOND) self.play(contrast_tracker.animate.set_value( 65535 ), rate_func=smooth, run_time=SECOND) #dark limit self.play(tr_zoom.animate.set_value(1), rate_func=smooth, run_time=SECOND) t.remove_updater(foo) self.wait(SECOND) %manim -v WARNING -qh --disable_caching --progress_bar None Example ```