snnlab
API referencesnnlab.viz

snnlab.viz.animation

Complete declared API of the animation module, with signatures, data fields, validation and source.

Back to viz reference

Timeline sampling and backend encoding helpers.

The signatures, defaults, fields, docstrings and implementation excerpts below are generated from the Python source. Annotations are shown as declared; unannotated means the source supplies no type annotation. These pages document callable surfaces, including legacy support utilities, without promising backend support for every declaration.

SymbolKind
FrameTimelineclass
save_animationfunction

FrameTimeline

View source

Explicit source-step sequence with a physical timestep in milliseconds. sample() uniformly selects inclusive steps; compose() supports paced segments, backward ranges and holds. time_ms(frame) maps an animation-frame index to its source simulation time.

Class decorators: dataclass(frozen=True).

Dataclass constructor parameters. Factory defaults are shown as field declarations; omit these arguments to create fresh values per instance:

FrameTimeline(steps: np.ndarray, dt_ms: float)

Declared fields, including fields inherited from local data classes:

FieldAnnotationDefaultMeaning
stepsnp.ndarrayrequiredStored member of this data contract; see the class docstring and serialization methods.
dt_msfloatrequiredSimulation timestep in milliseconds.

FrameTimeline.sample

View source

Decorators: classmethod.

def FrameTimeline.sample(cls, steps: int, *, frames: int, dt_ms: float) -> 'FrameTimeline'

Select frames integer source indices uniformly between zero and steps-1, inclusive. Require 0 < frames <= steps.

ParameterAnnotationDefaultMeaning
stepsintrequiredDefined by the source contract and implementation below.
framesintrequiredNumber of output animation frames.
dt_msfloatrequiredSimulation timestep in milliseconds.

Return annotation: 'FrameTimeline'.

Return expressions (branch-dependent; names refer to the linked implementation):

cls(np.linspace(0, steps - 1, frames, dtype=int), dt_ms)

Explicit exceptions in this implementation; called helpers may raise additional errors:

Explicit exception expression
ValueError('require 0 < frames <= steps')
Implementation
def sample(
        cls, steps: int, *, frames: int, dt_ms: float
    ) -> "FrameTimeline":
        if steps <= 0 or frames <= 0 or frames > steps:
            raise ValueError("require 0 < frames <= steps")
        return cls(np.linspace(0, steps - 1, frames, dtype=int), dt_ms)

FrameTimeline.compose

View source

Decorators: classmethod.

def FrameTimeline.compose(cls, segments: list[tuple[int, int, int]], *, dt_ms: float) -> 'FrameTimeline'

Source docstring:

Compose paced, repeated, or held inclusive step ranges.

Each segment is ``(start_step, end_step, frame_count)``. A reversed
range plays backward and equal endpoints create a hold. This gives a
composition full pacing control without coupling it to a plot type.
ParameterAnnotationDefaultMeaning
segmentslist[tuple[int, int, int]]requiredDefined by the source contract and implementation below.
dt_msfloatrequiredSimulation timestep in milliseconds.

Return annotation: 'FrameTimeline'.

Return expressions (branch-dependent; names refer to the linked implementation):

cls(np.concatenate(sampled), dt_ms)

Explicit exceptions in this implementation; called helpers may raise additional errors:

Explicit exception expression
ValueError('at least one timeline segment is required')
ValueError('timeline steps must be non-negative and frames positive')
Implementation
def compose(
        cls,
        segments: list[tuple[int, int, int]],
        *,
        dt_ms: float,
    ) -> "FrameTimeline":
        """Compose paced, repeated, or held inclusive step ranges.

        Each segment is ``(start_step, end_step, frame_count)``. A reversed
        range plays backward and equal endpoints create a hold. This gives a
        composition full pacing control without coupling it to a plot type.
        """

        if not segments:
            raise ValueError("at least one timeline segment is required")
        sampled = []
        for start, end, frames in segments:
            if start < 0 or end < 0 or frames <= 0:
                raise ValueError("timeline steps must be non-negative and frames positive")
            sampled.append(np.linspace(start, end, frames, dtype=int))
        return cls(np.concatenate(sampled), dt_ms)

FrameTimeline.time_ms

View source

def FrameTimeline.time_ms(self, frame: int) -> float

Return the source step selected for frame multiplied by dt_ms. frame is an animation-frame index, not a simulation step.

ParameterAnnotationDefaultMeaning
frameintrequiredDefined by the source contract and implementation below.

Return annotation: float.

Return expressions (branch-dependent; names refer to the linked implementation):

float(self.steps[frame] * self.dt_ms)
Implementation
def time_ms(self, frame: int) -> float:
        return float(self.steps[frame] * self.dt_ms)
Complete class implementation
class FrameTimeline:
    steps: np.ndarray
    dt_ms: float

    @classmethod
    def sample(
        cls, steps: int, *, frames: int, dt_ms: float
    ) -> "FrameTimeline":
        if steps <= 0 or frames <= 0 or frames > steps:
            raise ValueError("require 0 < frames <= steps")
        return cls(np.linspace(0, steps - 1, frames, dtype=int), dt_ms)

    @classmethod
    def compose(
        cls,
        segments: list[tuple[int, int, int]],
        *,
        dt_ms: float,
    ) -> "FrameTimeline":
        """Compose paced, repeated, or held inclusive step ranges.

        Each segment is ``(start_step, end_step, frame_count)``. A reversed
        range plays backward and equal endpoints create a hold. This gives a
        composition full pacing control without coupling it to a plot type.
        """

        if not segments:
            raise ValueError("at least one timeline segment is required")
        sampled = []
        for start, end, frames in segments:
            if start < 0 or end < 0 or frames <= 0:
                raise ValueError("timeline steps must be non-negative and frames positive")
            sampled.append(np.linspace(start, end, frames, dtype=int))
        return cls(np.concatenate(sampled), dt_ms)

    def time_ms(self, frame: int) -> float:
        return float(self.steps[frame] * self.dt_ms)

save_animation

View source

def save_animation(figure, update: Callable[[int], object], output: str | Path, *, frames: int, fps: int=25, bitrate: int=3800) -> FuncAnimation

Create and save a Matplotlib FuncAnimation using FFmpeg. The callback receives the frame index. Defaults are 25 frames per second and 3800 kbps, with blit disabled. Return the animation object; FFmpeg must be installed separately.

ParameterAnnotationDefaultMeaning
figureunannotatedrequiredDefined by the source contract and implementation below.
updateCallable[[int], object]requiredDefined by the source contract and implementation below.
outputstr | PathrequiredDefined by the source contract and implementation below.
framesintrequiredNumber of output animation frames.
fpsint25Encoded video frames per second.
bitrateint3800FFmpeg video bitrate in kilobits per second.

Return annotation: FuncAnimation.

Return expressions (branch-dependent; names refer to the linked implementation):

animation
Implementation
def save_animation(
    figure,
    update: Callable[[int], object],
    output: str | Path,
    *,
    frames: int,
    fps: int = 25,
    bitrate: int = 3800,
) -> FuncAnimation:
    animation = FuncAnimation(
        figure, update, frames=frames, interval=1000 / fps, blit=False
    )
    animation.save(
        Path(output), writer=FFMpegWriter(fps=fps, bitrate=bitrate)
    )
    return animation

On this page