ethograph.labels.ml.stitch_gaps#

ethograph.labels.ml.stitch_gaps(labels, max_gap_len, skip_labels=None)[source]#

Fill small background gaps between same-label segments.

Scans the dense label array for short runs of zeros (background) flanked by the same non-zero label on both sides. When the gap is at most max_gap_len samples, it is filled with that label.

This is typically used after model prediction to clean up fragmented outputs where a behaviour is briefly interrupted by a few background frames.

Parameters:
  • labels (np.ndarray) – 1-D dense label array (int), where 0 = background.

  • max_gap_len (int) – Maximum gap length in samples to fill. Gaps longer than this are left untouched. Convert from seconds: int(gap_s * sample_rate).

  • skip_labels (set[int], optional) – Labels whose trailing gaps should never be filled. For example, skip_labels={3} means that a gap preceded by label 3 is always kept even if the same label follows.

Returns:

Copy of labels with qualifying gaps filled.

Return type:

np.ndarray

Examples

Basic gap stitching at 30 Hz (fill gaps up to 5 frames):

>>> import numpy as np
>>> from ethograph.labels.ml import stitch_gaps
>>> pred = np.array([1, 1, 0, 1, 1, 0, 0, 0, 2, 2])
>>> stitch_gaps(pred, max_gap_len=2).tolist()
[1, 1, 1, 1, 1, 0, 0, 0, 2, 2]

The single-frame gap (index 2) is filled because label 1 appears on both sides. The 3-frame gap (indices 5–7) is left alone because it exceeds max_gap_len=2.

Using skip_labels to protect specific transitions:

>>> pred = np.array([3, 3, 0, 3, 3])
>>> stitch_gaps(pred, max_gap_len=2, skip_labels={3}).tolist()
[3, 3, 0, 3, 3]