Skip to content

Sequences

sequences

Sequence length utilities for ML pipelines.

Fixed-length windows and sequence standardization — the universal pre-processing steps between variable-length motion clips and fixed-size model inputs.

sliding_window(data: npt.NDArray[np.float64], window_size: int, stride: int = 1) -> npt.NDArray[np.float64]

Extract sliding windows from a time-series array.

Parameters:

Name Type Description Default
data (ndarray, shape(T, ...))

Input array where axis 0 is the time dimension.

required
window_size int

Number of frames per window.

required
stride int

Step between consecutive window starts (default 1).

1

Returns:

Type Description
(ndarray, shape(num_windows, window_size, ...))

num_windows = (T - window_size) // stride + 1.

Raises:

Type Description
ValueError

If window_size exceeds the data length or stride < 1.

standardize_length(data: npt.NDArray[np.float64], target_length: int, method: str = 'pad', pad_value: float = 0.0) -> npt.NDArray[np.float64]

Standardize array length along axis 0.

Parameters:

Name Type Description Default
data (ndarray, shape(T, ...))
required
target_length int

Desired number of frames.

required
method ('pad', 'crop', 'resample_linear')
  • "pad": truncate from end if longer, zero-pad at end if shorter.
  • "crop": center-crop if longer, zero-pad at end if shorter.
  • "resample_linear": linearly interpolate to target_length frames along axis 0. Correct for position data, velocities, and generic feature arrays. Not correct for rotation arrays (Euler / quaternion / 6D / axis-angle) — linear interpolation does not preserve rotation geometry. For rotations, resample with :meth:pybvh.Bvh.resample (SLERP) before extracting arrays. The name makes the limitation visible at the call site; no runtime warning is emitted.
"pad"
pad_value float

Value used for padding (default 0.0). Only used by "pad" and "crop" methods.

Padding is a constant appended at the end; the alternatives are front-padding and edge-repeat (holding the last frame), neither of which is provided. The three differ for any model that reads the padded frames — pair padded arrays with a length or mask, as :func:pybvh_ml.torch.collate_motion_batch returns, so that they never do.

The default 0.0 is a valid feature value but not a valid rotation in any representation pybvh-ml packs: the zero quaternion has no norm, the zero 6D pair has no orthonormalization, and the zero rotation matrix is singular. Zero is the identity for Euler and axis-angle, so those pad to a rest pose rather than to something undefined. There is no scalar pad_value that expresses the identity for quaternion / 6D / rotation-matrix arrays — mask the padded frames instead of trying to pick one.

0.0

Returns:

Type Description
(ndarray, shape(target_length, ...))

"pad" and "crop" preserve the input dtype — they only select and append frames, so a float32 clip stays float32 rather than silently doubling in size. "resample_linear" returns float64: it computes new values, and the interpolation runs in double precision.

uniform_temporal_sample(num_frames: int, clip_length: int, mode: str = 'train', rng: np.random.Generator | None = None) -> npt.NDArray[np.intp]

Sample clip_length frame indices from a sequence of num_frames.

Divides the sequence into clip_length equal segments and picks one frame index per segment. In "train" mode, picks a random offset within each segment (temporal augmentation). In "test" mode, picks a deterministic offset (reproducible evaluation).

Handles three regimes:

  • num_frames < clip_length: sequential indices with a random start (train) or start at 0 (test). Some indices will be >= num_frames; the caller must apply indices % num_frames before indexing into data.
  • clip_length <= num_frames < 2 * clip_length: starts with [0, ..., clip_length-1] and randomly inserts gaps to spread indices across the full [0, num_frames) range.
  • num_frames >= 2 * clip_length: uniform segment-based sampling with random (train) or deterministic (test) offsets within each segment.

Parameters:

Name Type Description Default
num_frames int

Total frames in the source sequence.

required
clip_length int

Number of frame indices to return.

required
mode ('train', 'test')

Offset policy within each segment. Both modes draw their offsets from the generator; they differ in which generator they default to when rng is None — fresh entropy for "train", a fixed default_rng(0) for "test", which is what makes test-mode indices repeatable rather than making them zero. The one exception is the short-clip regime, where test mode starts at frame 0.

"train"
rng numpy Generator

Drives the sampling in both modes. None uses fresh entropy in train mode and a fixed default_rng(0) in test mode.

None

Returns:

Type Description
ndarray of shape (clip_length,), dtype int

Frame indices. May contain values >= num_frames when num_frames < clip_length; apply % num_frames to use.

Notes

mode="test" alone is not a reproducibility guarantee. Test mode fixes the offset policy, not the generator: a supplied rng overrides the fixed default in test mode as much as in train mode. Passing one generator shared with other draws — the natural thing to do when the same object is threaded through both modes — means it has advanced by the time the next call arrives, so repeated reads of the same clip return different frames. Pass rng=None, or a generator freshly seeded per call, whenever repeated reads must agree.

Before 0.5.0 test mode discarded a supplied rng outright, which made a shared generator harmless here and hid the distinction.

sample_temporal(data: npt.NDArray[np.float64], clip_length: int, num_samples: int = 1, mode: str = 'train', rng: np.random.Generator | None = None) -> npt.NDArray[np.float64]

Sample clip_length frames from data with wraparound.

Convenience wrapper around :func:uniform_temporal_sample that applies the sampled indices to an array and supports generating multiple independent samples.

Parameters:

Name Type Description Default
data (ndarray, shape(T, ...))

Input array where axis 0 is the time dimension.

required
clip_length int

Number of frames to sample.

required
num_samples int

Number of independent samples to generate (default 1). The rng is created once and threaded through every draw, so test mode yields num_samples distinct deterministic samples (reproducible across calls).

1
mode ('train', 'test')
"train"
rng numpy Generator

Drives the sampling in both modes; None uses fresh entropy in train mode and a fixed default_rng(0) in test mode. Supplying a generator that is shared with other draws makes even mode="test" vary between calls — see the Notes on :func:uniform_temporal_sample.

None

Returns:

Type Description
ndarray

Shape (num_samples, clip_length, ...) if num_samples > 1, or (clip_length, ...) if num_samples == 1.