Source code for image_analysis_3D.visualization_utils.animation_utils

"""Animation helpers for visualization outputs."""

from typing import Any

from moviepy import VideoFileClip
from napari_animation import Animation
from napari_animation.easing import Easing


[docs] def mp4_to_gif(input_mp4: str, output_gif: str, fps: int = 10) -> str: """Convert an MP4 file to a looping GIF. Parameters ---------- input_mp4 : str Path to the source MP4 file. output_gif : str Path to the output GIF file. fps : int, optional Frames per second for the GIF, by default 10. Returns ------- str The output GIF path. """ clip = VideoFileClip(input_mp4) clip = clip.set_fps(fps) # Reduce FPS to control file size clip.write_gif(output_gif, loop=0) # loop=0 makes it loop forever return output_gif
[docs] def animate_view( viewer: Any, output_path_name: str, steps: int = 30, easing: str = "linear", dim: int = 3, ) -> str: """Animate a napari viewer and save to disk. Parameters ---------- viewer : Any Napari viewer instance to animate. output_path_name : str Output file path for the animation. steps : int, optional Steps per keyframe, by default 30. easing : str, optional Easing style name, by default "linear". dim : int, optional Number of displayed dimensions, by default 3. Returns ------- str The output animation path. """ animation = Animation(viewer) if easing == "linear": ease_style = Easing.LINEAR else: raise ValueError(f"Invalid easing style: {easing}") viewer.dims.ndisplay = dim # rotate around the y-axis viewer.camera.angles = (0.0, 0.0, 90.0) # (z, y, x) axis of rotation animation.capture_keyframe(steps=steps, ease=ease_style) viewer.camera.angles = (0.0, 180.0, 90.0) animation.capture_keyframe(steps=steps, ease=ease_style) viewer.camera.angles = (0.0, 360.0, 90.0) animation.capture_keyframe(steps=steps, ease=ease_style) viewer.camera.angles = (0.0, 0.0, 270.0) animation.capture_keyframe(steps=steps, ease=ease_style) viewer.camera.angles = (0.0, 0.0, 90.0) animation.capture_keyframe(steps=steps, ease=ease_style) animation.animate(output_path_name, canvas_only=True) return output_path_name