diff --git a/brainrender/video.py b/brainrender/video.py index ace901d1..aad36fd9 100644 --- a/brainrender/video.py +++ b/brainrender/video.py @@ -106,15 +106,23 @@ def compress(self, temp_name): @not_on_jupyter def make_video( - self, *args, duration=10, fps=30, render_kwargs={}, **kwargs + self, + *args, + duration=10, + fps=30, + fix_camera=False, + render_kwargs={}, + **kwargs, ): """ Creates a video using user defined parameters - :param *args: any extra argument to be bassed to `make_frame_func` - :param duration: float, duratino of the video in seconds + :param *args: any extra argument to be passed to `make_frame_func` + :param duration: float, duration of the video in seconds :param fps: int, frame rate - :param **kwargs: any extra keyword argument to be bassed to `make_frame_func` + :param fix_camera: bool, if True the focal point of the camera is set based on the first frame + :param render_kwargs: dict, any extra keyword argument to be passed to `scene.render` + :param **kwargs: any extra keyword argument to be passed to `make_frame_func` """ logger.debug(f"Saving a video {duration}s long ({fps} fps)") _off = br.settings.OFFSCREEN @@ -122,6 +130,18 @@ def make_video( self.scene.render(interactive=False, **render_kwargs) + if fix_camera: + first_frame = self.keyframes.get(0) + if not first_frame: + logger.error("No keyframes found, can't fix camera") + + # Sets the focal point of the first frame to the centre of mass of the + # full root mesh, since this focal point is set subsequent frames will + # have the same focal point unless a new camera is defined + self.keyframes[0]["camera"][ + "focal_point" + ] = self.scene.root._mesh.center_of_mass() + # cd to folder where the video will be saved curdir = os.getcwd() os.chdir(self.save_fld) @@ -317,7 +337,6 @@ def get_frame_params(self, frame_number): elif frame_number > self.last_keyframe: # check if current frame is past the last keyframe params = self.keyframes[self.last_keyframe] - params["callback"] = None else: # interpolate between two key frames diff --git a/examples/animation_callback.py b/examples/animation_callback.py new file mode 100644 index 00000000..e7ce46e2 --- /dev/null +++ b/examples/animation_callback.py @@ -0,0 +1,39 @@ +from brainrender import Animation, Scene, settings +from pathlib import Path + +settings.SHOW_AXES = False + +scene = Scene(atlas_name="allen_mouse_25um") + +regions = ( + "CTX", + "HPF", + "STR", + "CB", + "MB", + "TH", + "HY", +) +scene.add_brain_region(*regions, silhouette=True) + + +def slc(scene, framen, totframes): + # Get new slicing plane + fact = framen / totframes + shape_um = scene.atlas.shape_um + # Multiply by fact to move the plane, add buffer to go past the brain + point = [(shape_um[0] + 500) * fact, shape_um[1] // 2, shape_um[2] // 2] + plane = scene.atlas.get_plane(pos=point, norm=(1, 0, 0)) + + scene.slice(plane) + + +anim = Animation( + scene, Path.cwd(), "brainrender_animation_callback", size=None +) + +# Specify camera pos and zoom at some key frames` +anim.add_keyframe(0, camera="frontal", zoom=1, callback=slc) + +# Make videos +anim.make_video(duration=5, fps=10, fix_camera=True)