Skip to content

Data formats

sleap-io provides a unified interface for reading and writing pose tracking data across multiple formats. The library automatically detects file formats and provides harmonized I/O operations.

Universal I/O Functions

sleap_io.load_file(filename, format=None, **kwargs)

Load a file and return the appropriate object.

Parameters:

Name Type Description Default
filename str | Path

Path to a file.

required
format Optional[str]

Optional format to load as. If not provided, will be inferred from the file extension. Available formats are: "slp", "nwb", "alphatracker", "labelstudio", "coco", "jabs", "dlc", "ultralytics", "leap", and "video".

None
**kwargs

Additional arguments passed to the format-specific loading function: - For "slp" format: No additional arguments. - For "nwb" format: No additional arguments. - For "alphatracker" format: No additional arguments. - For "leap" format: skeleton (Optional[Skeleton]): Skeleton to use if not defined in the file. - For "labelstudio" format: skeleton (Optional[Skeleton]): Skeleton to use for the labels. - For "coco" format: dataset_root (Optional[str]): Root directory of the dataset. grayscale (bool): If True, load images as grayscale (1 channel). If False, load as RGB (3 channels). Default is False. - For "jabs" format: skeleton (Optional[Skeleton]): Skeleton to use for the labels. - For "dlc" format: video_search_paths (Optional[List[str]]): Paths to search for video files. - For "ultralytics" format: See load_ultralytics for supported arguments. - For "video" format: See load_video for supported arguments.

{}

Returns:

Type Description
Union[Labels, Video]

A Labels or Video object.

Source code in sleap_io/io/main.py
def load_file(
    filename: str | Path, format: Optional[str] = None, **kwargs
) -> Union[Labels, Video]:
    """Load a file and return the appropriate object.

    Args:
        filename: Path to a file.
        format: Optional format to load as. If not provided, will be inferred from the
            file extension. Available formats are: "slp", "nwb", "alphatracker",
            "labelstudio", "coco", "jabs", "dlc", "ultralytics", "leap", and "video".
        **kwargs: Additional arguments passed to the format-specific loading function:
            - For "slp" format: No additional arguments.
            - For "nwb" format: No additional arguments.
            - For "alphatracker" format: No additional arguments.
            - For "leap" format: skeleton (Optional[Skeleton]): Skeleton to use if not
              defined in the file.
            - For "labelstudio" format: skeleton (Optional[Skeleton]): Skeleton to
              use for
              the labels.
            - For "coco" format: dataset_root (Optional[str]): Root directory of the
              dataset. grayscale (bool): If True, load images as grayscale (1 channel).
              If False, load as RGB (3 channels). Default is False.
            - For "jabs" format: skeleton (Optional[Skeleton]): Skeleton to use for
              the labels.
            - For "dlc" format: video_search_paths (Optional[List[str]]): Paths to
              search for video files.
            - For "ultralytics" format: See `load_ultralytics` for supported arguments.
            - For "video" format: See `load_video` for supported arguments.

    Returns:
        A `Labels` or `Video` object.
    """
    if isinstance(filename, Path):
        filename = filename.as_posix()

    if format is None:
        if filename.endswith(".slp"):
            format = "slp"
        elif filename.endswith(".nwb"):
            format = "nwb"
        elif filename.endswith(".mat"):
            format = "leap"
        elif filename.endswith(".json"):
            # Detect JSON format: AlphaTracker, COCO, or Label Studio
            if _detect_alphatracker_format(filename):
                format = "alphatracker"
            elif _detect_coco_format(filename):
                format = "coco"
            else:
                format = "json"
        elif filename.endswith(".h5"):
            format = "jabs"
        elif filename.endswith("data.yaml") or (
            Path(filename).is_dir() and (Path(filename) / "data.yaml").exists()
        ):
            format = "ultralytics"
        elif filename.endswith(".csv") and dlc.is_dlc_file(filename):
            format = "dlc"
        else:
            for vid_ext in Video.EXTS:
                if filename.endswith(vid_ext):
                    format = "video"
                    break
        if format is None:
            raise ValueError(f"Could not infer format from filename: '{filename}'.")

    if filename.endswith(".slp"):
        return load_slp(filename, **kwargs)
    elif filename.endswith(".nwb"):
        return load_nwb(filename, **kwargs)
    elif filename.endswith(".mat"):
        return load_leap(filename, **kwargs)
    elif filename.endswith(".json"):
        if format == "alphatracker":
            return load_alphatracker(filename, **kwargs)
        elif format == "coco":
            return load_coco(filename, **kwargs)
        else:
            return load_labelstudio(filename, **kwargs)
    elif filename.endswith(".h5"):
        return load_jabs(filename, **kwargs)
    elif format == "dlc":
        return load_dlc(filename, **kwargs)
    elif format == "ultralytics":
        return load_ultralytics(filename, **kwargs)
    elif format == "video":
        return load_video(filename, **kwargs)

sleap_io.save_file(labels, filename, format=None, verbose=True, **kwargs)

Save a file based on the extension.

Parameters:

Name Type Description Default
labels Labels

A SLEAP Labels object (see load_slp).

required
filename str | Path

Path to save labels to.

required
format Optional[str]

Optional format to save as. If not provided, will be inferred from the file extension. Available formats are: "slp", "nwb", "labelstudio", "jabs", and "ultralytics".

None
verbose bool

If True (the default), display a progress bar when embedding frames (only applies to the SLP format).

True
**kwargs

Additional arguments passed to the format-specific saving function: - For "slp" format: embed (bool | str | list[tuple[Video, int]] | None): Frames to embed in the saved labels file. One of None, True, "all", "user", "suggestions", "user+suggestions", "source" or list of tuples of (video, frame_idx). If False (the default), no frames are embedded. - For "nwb" format: pose_estimation_metadata (dict): Metadata to store in the NWB file. append (bool): If True, append to existing NWB file. - For "labelstudio" format: No additional arguments. - For "jabs" format: pose_version (int): JABS pose format version (1-6). root_folder (Optional[str]): Root folder for JABS project structure. - For "ultralytics" format: See save_ultralytics for supported arguments.

{}
Source code in sleap_io/io/main.py
def save_file(
    labels: Labels,
    filename: str | Path,
    format: Optional[str] = None,
    verbose: bool = True,
    **kwargs,
):
    """Save a file based on the extension.

    Args:
        labels: A SLEAP `Labels` object (see `load_slp`).
        filename: Path to save labels to.
        format: Optional format to save as. If not provided, will be inferred from the
            file extension. Available formats are: "slp", "nwb", "labelstudio", "jabs",
            and "ultralytics".
        verbose: If `True` (the default), display a progress bar when embedding frames
            (only applies to the SLP format).
        **kwargs: Additional arguments passed to the format-specific saving function:
            - For "slp" format: embed (bool | str | list[tuple[Video, int]] |
              None): Frames
              to embed in the saved labels file. One of None, True, "all", "user",
              "suggestions", "user+suggestions", "source" or list of tuples of
              (video, frame_idx). If False (the default), no frames are embedded.
            - For "nwb" format: pose_estimation_metadata (dict): Metadata to store
              in the
              NWB file. append (bool): If True, append to existing NWB file.
            - For "labelstudio" format: No additional arguments.
            - For "jabs" format: pose_version (int): JABS pose format version (1-6).
              root_folder (Optional[str]): Root folder for JABS project structure.
            - For "ultralytics" format: See `save_ultralytics` for supported arguments.
    """
    if isinstance(filename, Path):
        filename = str(filename)

    if format is None:
        if filename.endswith(".slp"):
            format = "slp"
        elif filename.endswith(".nwb"):
            format = "nwb"
        elif filename.endswith(".json"):
            format = "labelstudio"
        elif "pose_version" in kwargs:
            format = "jabs"
        elif "split_ratios" in kwargs or Path(filename).is_dir():
            format = "ultralytics"

    if format == "slp":
        save_slp(labels, filename, verbose=verbose, **kwargs)
    elif format == "nwb":
        save_nwb(labels, filename, **kwargs)
    elif format == "labelstudio":
        save_labelstudio(labels, filename, **kwargs)
    elif format == "jabs":
        pose_version = kwargs.pop("pose_version", 5)
        root_folder = kwargs.pop("root_folder", filename)
        save_jabs(labels, pose_version=pose_version, root_folder=root_folder)
    elif format == "ultralytics":
        save_ultralytics(labels, filename, **kwargs)
    else:
        raise ValueError(f"Unknown format '{format}' for filename: '{filename}'.")

Video I/O

sleap_io.load_video(filename, **kwargs)

Load a video file.

Parameters:

Name Type Description Default
filename str

The filename(s) of the video. Supported extensions: "mp4", "avi", "mov", "mj2", "mkv", "h5", "hdf5", "slp", "png", "jpg", "jpeg", "tif", "tiff", "bmp". If the filename is a list, a list of image filenames are expected. If filename is a folder, it will be searched for images.

required
**kwargs

Additional arguments passed to Video.from_filename. Currently supports: - dataset: Name of dataset in HDF5 file. - grayscale: Whether to force grayscale. If None, autodetect on first frame load. - keep_open: Whether to keep the video reader open between calls to read frames. If False, will close the reader after each call. If True (the default), it will keep the reader open and cache it for subsequent calls which may enhance the performance of reading multiple frames. - source_video: Source video object if this is a proxy video. This is metadata and does not affect reading. - backend_metadata: Metadata to store on the video backend. This is useful for storing metadata that requires an open backend (e.g., shape information) without having to open the backend. - plugin: Video plugin to use for MediaVideo backend. One of "opencv", "FFMPEG", or "pyav". Also accepts aliases (case-insensitive): * opencv: "opencv", "cv", "cv2", "ocv" * FFMPEG: "FFMPEG", "ffmpeg", "imageio-ffmpeg", "imageio_ffmpeg" * pyav: "pyav", "av"

If not specified, uses the following priority: 1. Global default set via sio.set_default_video_plugin() 2. Auto-detection based on available packages

To set a global default:

import sleap_io as sio sio.set_default_video_plugin("opencv") video = sio.load_video("video.mp4") # Uses opencv - input_format: Format of the data in HDF5 datasets. One of "channels_last" (the default) in (frames, height, width, channels) order or "channels_first" in (frames, channels, width, height) order. - frame_map: Mapping from frame indices to indices in the HDF5 dataset. This is used to translate between frame indices of images within their source video and indices of images in the dataset. - source_filename: Path to the source video file for HDF5 embedded videos. - source_inds: Indices of frames in the source video file for HDF5 embedded videos. - image_format: Format of images in HDF5 embedded dataset.

{}

Returns:

Type Description
Video

A Video object.

See Also

set_default_video_plugin: Set the default video plugin globally. get_default_video_plugin: Get the current default video plugin.

Source code in sleap_io/io/main.py
def load_video(filename: str, **kwargs) -> Video:
    """Load a video file.

    Args:
        filename: The filename(s) of the video. Supported extensions: "mp4", "avi",
            "mov", "mj2", "mkv", "h5", "hdf5", "slp", "png", "jpg", "jpeg", "tif",
            "tiff", "bmp". If the filename is a list, a list of image filenames are
            expected. If filename is a folder, it will be searched for images.
        **kwargs: Additional arguments passed to `Video.from_filename`.
            Currently supports:
            - dataset: Name of dataset in HDF5 file.
            - grayscale: Whether to force grayscale. If None, autodetect on first
              frame load.
            - keep_open: Whether to keep the video reader open between calls to read
              frames.
              If False, will close the reader after each call. If True (the
              default), it will
              keep the reader open and cache it for subsequent calls which may
              enhance the
              performance of reading multiple frames.
            - source_video: Source video object if this is a proxy video. This is
              metadata
              and does not affect reading.
            - backend_metadata: Metadata to store on the video backend. This is
              useful for
              storing metadata that requires an open backend (e.g., shape
              information) without
              having to open the backend.
            - plugin: Video plugin to use for MediaVideo backend. One of "opencv",
              "FFMPEG",
              or "pyav". Also accepts aliases (case-insensitive):
              * opencv: "opencv", "cv", "cv2", "ocv"
              * FFMPEG: "FFMPEG", "ffmpeg", "imageio-ffmpeg", "imageio_ffmpeg"
              * pyav: "pyav", "av"

              If not specified, uses the following priority:
              1. Global default set via `sio.set_default_video_plugin()`
              2. Auto-detection based on available packages

              To set a global default:
              >>> import sleap_io as sio
              >>> sio.set_default_video_plugin("opencv")
              >>> video = sio.load_video("video.mp4")  # Uses opencv
            - input_format: Format of the data in HDF5 datasets. One of
              "channels_last" (the
              default) in (frames, height, width, channels) order or "channels_first" in
              (frames, channels, width, height) order.
            - frame_map: Mapping from frame indices to indices in the HDF5 dataset.
              This is
              used to translate between frame indices of images within their source
              video
              and indices of images in the dataset.
            - source_filename: Path to the source video file for HDF5 embedded videos.
            - source_inds: Indices of frames in the source video file for HDF5
              embedded videos.
            - image_format: Format of images in HDF5 embedded dataset.

    Returns:
        A `Video` object.

    See Also:
        set_default_video_plugin: Set the default video plugin globally.
        get_default_video_plugin: Get the current default video plugin.
    """
    return Video.from_filename(filename, **kwargs)

sleap_io.save_video(frames, filename, fps=30, pixelformat='yuv420p', codec='libx264', crf=25, preset='superfast', output_params=None)

Write a list of frames to a video file.

Parameters:

Name Type Description Default
frames ndarray | Video

Sequence of frames to write to video. Each frame should be a 2D or 3D numpy array with dimensions (height, width) or (height, width, channels).

required
filename str | Path

Path to output video file.

required
fps float

Frames per second. Defaults to 30.

30
pixelformat str

Pixel format for video. Defaults to "yuv420p".

'yuv420p'
codec str

Codec to use for encoding. Defaults to "libx264".

'libx264'
crf int

Constant rate factor to control lossiness of video. Values go from 2 to 32, with numbers in the 18 to 30 range being most common. Lower values mean less compressed/higher quality. Defaults to 25. No effect if codec is not "libx264".

25
preset str

H264 encoding preset. Defaults to "superfast". No effect if codec is not "libx264".

'superfast'
output_params list | None

Additional output parameters for FFMPEG. This should be a list of strings corresponding to command line arguments for FFMPEG and libx264. Use ffmpeg -h encoder=libx264 to see all options for libx264 output_params.

None

See also: sio.VideoWriter

Source code in sleap_io/io/main.py
def save_video(
    frames: np.ndarray | Video,
    filename: str | Path,
    fps: float = 30,
    pixelformat: str = "yuv420p",
    codec: str = "libx264",
    crf: int = 25,
    preset: str = "superfast",
    output_params: list | None = None,
):
    """Write a list of frames to a video file.

    Args:
        frames: Sequence of frames to write to video. Each frame should be a 2D or 3D
            numpy array with dimensions (height, width) or (height, width, channels).
        filename: Path to output video file.
        fps: Frames per second. Defaults to 30.
        pixelformat: Pixel format for video. Defaults to "yuv420p".
        codec: Codec to use for encoding. Defaults to "libx264".
        crf: Constant rate factor to control lossiness of video. Values go from 2 to 32,
            with numbers in the 18 to 30 range being most common. Lower values mean less
            compressed/higher quality. Defaults to 25. No effect if codec is not
            "libx264".
        preset: H264 encoding preset. Defaults to "superfast". No effect if codec is not
            "libx264".
        output_params: Additional output parameters for FFMPEG. This should be a list of
            strings corresponding to command line arguments for FFMPEG and libx264. Use
            `ffmpeg -h encoder=libx264` to see all options for libx264 output_params.

    See also: `sio.VideoWriter`
    """
    if output_params is None:
        output_params = []

    with video_writing.VideoWriter(
        filename,
        fps=fps,
        pixelformat=pixelformat,
        codec=codec,
        crf=crf,
        preset=preset,
        output_params=output_params,
    ) as writer:
        for frame in frames:
            writer(frame)

Format-Specific Functions

SLEAP Native Format (.slp)

The native SLEAP format stores complete pose tracking projects including videos, skeletons, and annotations.

sleap_io.load_slp(filename, open_videos=True)

Load a SLEAP dataset.

Parameters:

Name Type Description Default
filename str

Path to a SLEAP labels file (.slp).

required
open_videos bool

If True (the default), attempt to open the video backend for I/O. If False, the backend will not be opened (useful for reading metadata when the video files are not available).

True

Returns:

Type Description
Labels

The dataset as a Labels object.

Source code in sleap_io/io/main.py
def load_slp(filename: str, open_videos: bool = True) -> Labels:
    """Load a SLEAP dataset.

    Args:
        filename: Path to a SLEAP labels file (`.slp`).
        open_videos: If `True` (the default), attempt to open the video backend for
            I/O. If `False`, the backend will not be opened (useful for reading metadata
            when the video files are not available).

    Returns:
        The dataset as a `Labels` object.
    """
    return slp.read_labels(filename, open_videos=open_videos)

sleap_io.save_slp(labels, filename, embed=False, restore_original_videos=True, verbose=True)

Save a SLEAP dataset to a .slp file.

Parameters:

Name Type Description Default
labels Labels

A SLEAP Labels object (see load_slp).

required
filename str

Path to save labels to ending with .slp.

required
embed bool | str | list[tuple[Video, int]] | None

Frames to embed in the saved labels file. One of None, True, "all", "user", "suggestions", "user+suggestions", "source" or list of tuples of (video, frame_idx).

If False is specified (the default), the source video will be restored if available, otherwise the embedded frames will be re-saved.

If True or "all", all labeled frames and suggested frames will be embedded.

If "source" is specified, no images will be embedded and the source video will be restored if available.

This argument is only valid for the SLP backend.

False
restore_original_videos bool

If True (default) and embed=False, use original video files. If False and embed=False, keep references to source .pkg.slp files. Only applies when embed=False.

True
verbose bool

If True (the default), display a progress bar when embedding frames.

True
Source code in sleap_io/io/main.py
def save_slp(
    labels: Labels,
    filename: str,
    embed: bool | str | list[tuple[Video, int]] | None = False,
    restore_original_videos: bool = True,
    verbose: bool = True,
):
    """Save a SLEAP dataset to a `.slp` file.

    Args:
        labels: A SLEAP `Labels` object (see `load_slp`).
        filename: Path to save labels to ending with `.slp`.
        embed: Frames to embed in the saved labels file. One of `None`, `True`,
            `"all"`, `"user"`, `"suggestions"`, `"user+suggestions"`, `"source"` or list
            of tuples of `(video, frame_idx)`.

            If `False` is specified (the default), the source video will be restored
            if available, otherwise the embedded frames will be re-saved.

            If `True` or `"all"`, all labeled frames and suggested frames will be
            embedded.

            If `"source"` is specified, no images will be embedded and the source video
            will be restored if available.

            This argument is only valid for the SLP backend.
        restore_original_videos: If `True` (default) and `embed=False`, use original
            video files. If `False` and `embed=False`, keep references to source
            `.pkg.slp` files. Only applies when `embed=False`.
        verbose: If `True` (the default), display a progress bar when embedding frames.
    """
    return slp.write_labels(
        filename,
        labels,
        embed=embed,
        restore_original_videos=restore_original_videos,
        verbose=verbose,
    )

NWB Format (.nwb)

Neurodata Without Borders (NWB) is a standardized format for neurophysiology data. sleap-io provides comprehensive support for both reading and writing pose tracking data in NWB format.

Harmonized NWB I/O

The harmonized API automatically detects and routes to the appropriate NWB backend:

sleap_io.load_nwb(filename)

Load an NWB dataset as a SLEAP Labels object.

Parameters:

Name Type Description Default
filename str

Path to a NWB file (.nwb).

required

Returns:

Type Description
Labels

The dataset as a Labels object.

Source code in sleap_io/io/main.py
def load_nwb(filename: str) -> Labels:
    """Load an NWB dataset as a SLEAP `Labels` object.

    Args:
        filename: Path to a NWB file (`.nwb`).

    Returns:
        The dataset as a `Labels` object.
    """
    return nwb.load_nwb(filename)

sleap_io.save_nwb(labels, filename, nwb_format=NwbFormat.AUTO)

Save a SLEAP dataset to NWB format.

Parameters:

Name Type Description Default
labels Labels

A SLEAP Labels object (see load_slp).

required
filename Union[str, Path]

Path to NWB file to save to. Must end in .nwb.

required
nwb_format Union[NwbFormat, str]

Format to use for saving. Options are: - "auto" (default): Automatically detect based on data - "annotations": Save training annotations (PoseTraining) - "annotations_export": Export annotations with video frames - "predictions": Save predictions (PoseEstimation)

AUTO

Raises:

Type Description
ValueError

If an invalid format is specified.

Source code in sleap_io/io/main.py
def save_nwb(
    labels: Labels,
    filename: Union[str, Path],
    nwb_format: Union[NwbFormat, str] = NwbFormat.AUTO,
) -> None:
    """Save a SLEAP dataset to NWB format.

    Args:
        labels: A SLEAP `Labels` object (see `load_slp`).
        filename: Path to NWB file to save to. Must end in `.nwb`.
        nwb_format: Format to use for saving. Options are:
            - "auto" (default): Automatically detect based on data
            - "annotations": Save training annotations (PoseTraining)
            - "annotations_export": Export annotations with video frames
            - "predictions": Save predictions (PoseEstimation)

    Raises:
        ValueError: If an invalid format is specified.
    """
    nwb.save_nwb(labels, filename, nwb_format)

NWB Format Types

sleap-io supports multiple NWB format types through the nwb_format parameter:

  • "auto" (default): Automatically detect based on data content
  • Uses "annotations" if data contains user-labeled instances
  • Uses "predictions" if data contains only predicted instances

  • "annotations": Save as PoseTraining format (ndx-pose extension)

  • Stores manual annotations for training data
  • Preserves skeleton structure and node names
  • Includes annotator information

  • "annotations_export": Export annotations with embedded video frames

  • Creates self-contained NWB file with video data
  • Generates MJPEG video with frame provenance tracking
  • Useful for sharing complete datasets

  • "predictions": Save as PoseEstimation format (ndx-pose extension)

  • Stores predicted pose data from inference
  • Includes confidence scores
  • Supports multiple animals/tracks

Examples

Basic NWB Usage
import sleap_io as sio

# Load any NWB file (auto-detects format)
labels = sio.load_nwb("pose_data.nwb")

# Save with auto-detection
sio.save_nwb(labels, "output.nwb")

# Save with specific format
sio.save_nwb(labels, "training.nwb", nwb_format="annotations")
sio.save_nwb(labels, "predictions.nwb", nwb_format="predictions")
Advanced Annotations API

For more control over NWB training data, use the annotations module directly:

from sleap_io.io.nwb_annotations import save_labels, load_labels

# Save with custom metadata
save_labels(
    labels,
    "training.nwb",
    session_description="Mouse reaching task",
    identifier="mouse_01_session_03",
    annotator="researcher_name",
    nwb_kwargs={
        "session_id": "session_003",
        "experimenter": ["John Doe", "Jane Smith"],
        "lab": "Motor Control Lab",
        "institution": "University",
        "experiment_description": "Skilled reaching behavior"
    }
)

# Load annotations
labels = load_labels("training.nwb")
Export with Video Frames
from sleap_io.io.nwb_annotations import export_labels, export_labeled_frames

# Export complete dataset with videos
export_labels(
    labels,
    output_dir="export/",
    nwb_filename="dataset_with_videos.nwb",
    as_training=True,  # Include manual annotations
    include_videos=True  # Embed video frames
)

# Export only labeled frames as video
export_labeled_frames(
    labels,
    output_path="labeled_frames.avi",
    labels_output_path="labels.nwb",
    fps=30.0
)

NWB Metadata

The NWB format requires certain metadata fields. sleap-io provides sensible defaults:

  • Required fields (auto-generated if not provided):
  • session_description: Defaults to "Processed SLEAP pose data"
  • identifier: Auto-generated UUID string
  • session_start_time: Current timestamp

  • Optional fields (via nwb_kwargs):

  • session_id: Unique session identifier
  • experimenter: List of experimenters
  • lab: Laboratory name
  • institution: Institution name
  • experiment_description: Detailed experiment description
  • Any other valid NWB file fields

JABS Format (.h5)

JABS (Janelia Automatic Behavior System) format for behavior classification.

sleap_io.load_jabs(filename, skeleton=None)

Read JABS-style predictions from a file and return a Labels object.

Parameters:

Name Type Description Default
filename str

Path to the jabs h5 pose file.

required
skeleton Optional[Skeleton]

An optional Skeleton object.

None

Returns:

Type Description
Labels

Parsed labels as a Labels instance.

Source code in sleap_io/io/main.py
def load_jabs(filename: str, skeleton: Optional[Skeleton] = None) -> Labels:
    """Read JABS-style predictions from a file and return a `Labels` object.

    Args:
        filename: Path to the jabs h5 pose file.
        skeleton: An optional `Skeleton` object.

    Returns:
        Parsed labels as a `Labels` instance.
    """
    return jabs.read_labels(filename, skeleton=skeleton)

sleap_io.save_jabs(labels, pose_version, root_folder=None)

Save a SLEAP dataset to JABS pose file format.

Parameters:

Name Type Description Default
labels Labels

SLEAP Labels object.

required
pose_version int

The JABS pose version to write data out.

required
root_folder Optional[str]

Optional root folder where the files should be saved.

None
Note

Filenames for JABS poses are based on video filenames.

Source code in sleap_io/io/main.py
def save_jabs(labels: Labels, pose_version: int, root_folder: Optional[str] = None):
    """Save a SLEAP dataset to JABS pose file format.

    Args:
        labels: SLEAP `Labels` object.
        pose_version: The JABS pose version to write data out.
        root_folder: Optional root folder where the files should be saved.

    Note:
        Filenames for JABS poses are based on video filenames.
    """
    jabs.write_labels(labels, pose_version, root_folder)

Label Studio Format (.json)

Label Studio is a multi-modal annotation platform. Export annotations from Label Studio and load them into SLEAP.

sleap_io.load_labelstudio(filename, skeleton=None)

Read Label Studio-style annotations from a file and return a Labels object.

Parameters:

Name Type Description Default
filename str

Path to the label-studio annotation file in JSON format.

required
skeleton Optional[Union[Skeleton, list[str]]]

An optional Skeleton object or list of node names. If not provided (the default), skeleton will be inferred from the data. It may be useful to provide this so the keypoint label types can be filtered to just the ones in the skeleton.

None

Returns:

Type Description
Labels

Parsed labels as a Labels instance.

Source code in sleap_io/io/main.py
def load_labelstudio(
    filename: str, skeleton: Optional[Union[Skeleton, list[str]]] = None
) -> Labels:
    """Read Label Studio-style annotations from a file and return a `Labels` object.

    Args:
        filename: Path to the label-studio annotation file in JSON format.
        skeleton: An optional `Skeleton` object or list of node names. If not provided
            (the default), skeleton will be inferred from the data. It may be useful to
            provide this so the keypoint label types can be filtered to just the ones in
            the skeleton.

    Returns:
        Parsed labels as a `Labels` instance.
    """
    return labelstudio.read_labels(filename, skeleton=skeleton)

sleap_io.save_labelstudio(labels, filename)

Save a SLEAP dataset to Label Studio format.

Parameters:

Name Type Description Default
labels Labels

A SLEAP Labels object (see load_slp).

required
filename str

Path to save labels to ending with .json.

required
Source code in sleap_io/io/main.py
def save_labelstudio(labels: Labels, filename: str):
    """Save a SLEAP dataset to Label Studio format.

    Args:
        labels: A SLEAP `Labels` object (see `load_slp`).
        filename: Path to save labels to ending with `.json`.
    """
    labelstudio.write_labels(labels, filename)

DeepLabCut Format (.h5, .csv)

Load predictions from DeepLabCut, a popular markerless pose estimation tool.

sleap_io.load_dlc(filename, video_search_paths=None, **kwargs)

Read DeepLabCut annotations from a CSV file and return a Labels object.

Parameters:

Name Type Description Default
filename str

Path to DLC CSV file with annotations.

required
video_search_paths Optional[List[Union[str, Path]]]

Optional list of paths to search for video files.

None
**kwargs

Additional arguments passed to DLC loader.

{}

Returns:

Type Description
Labels

Parsed labels as a Labels instance.

Source code in sleap_io/io/main.py
def load_dlc(
    filename: str, video_search_paths: Optional[List[Union[str, Path]]] = None, **kwargs
) -> Labels:
    """Read DeepLabCut annotations from a CSV file and return a `Labels` object.

    Args:
        filename: Path to DLC CSV file with annotations.
        video_search_paths: Optional list of paths to search for video files.
        **kwargs: Additional arguments passed to DLC loader.

    Returns:
        Parsed labels as a `Labels` instance.
    """
    return dlc.load_dlc(filename, video_search_paths=video_search_paths, **kwargs)

AlphaTracker Format

Load predictions from AlphaTracker, a tracking system for socially-housed animals.

sleap_io.load_alphatracker(filename)

Read AlphaTracker annotations from a file and return a Labels object.

Parameters:

Name Type Description Default
filename str

Path to the AlphaTracker annotation file in JSON format.

required

Returns:

Type Description
Labels

Parsed labels as a Labels instance.

Source code in sleap_io/io/main.py
def load_alphatracker(filename: str) -> Labels:
    """Read AlphaTracker annotations from a file and return a `Labels` object.

    Args:
        filename: Path to the AlphaTracker annotation file in JSON format.

    Returns:
        Parsed labels as a `Labels` instance.
    """
    return alphatracker.read_labels(filename)

LEAP Format (.mat)

Load predictions from LEAP, a SLEAP predecessor. Requires scipy for .mat file support.

sleap_io.load_leap(filename, skeleton=None, **kwargs)

Load a LEAP dataset from a .mat file.

Parameters:

Name Type Description Default
filename str

Path to a LEAP .mat file.

required
skeleton Optional[Skeleton]

An optional Skeleton object. If not provided, will be constructed from the data in the file.

None
**kwargs

Additional arguments (currently unused).

{}

Returns:

Type Description
Labels

The dataset as a Labels object.

Source code in sleap_io/io/main.py
def load_leap(
    filename: str,
    skeleton: Optional[Skeleton] = None,
    **kwargs,
) -> Labels:
    """Load a LEAP dataset from a .mat file.

    Args:
        filename: Path to a LEAP .mat file.
        skeleton: An optional `Skeleton` object. If not provided, will be constructed
            from the data in the file.
        **kwargs: Additional arguments (currently unused).

    Returns:
        The dataset as a `Labels` object.
    """
    return leap.read_labels(filename, skeleton=skeleton)

COCO Format (.json)

Load annotations in COCO (Common Objects in Context) format, widely used in computer vision.

sleap_io.load_coco(json_path, dataset_root=None, grayscale=False, **kwargs)

Load a COCO-style pose dataset and return a Labels object.

Parameters:

Name Type Description Default
json_path str

Path to the COCO annotation JSON file.

required
dataset_root Optional[str]

Root directory of the dataset. If None, uses parent directory of json_path.

None
grayscale bool

If True, load images as grayscale (1 channel). If False, load as RGB (3 channels). Default is False.

False
**kwargs

Additional arguments (currently unused).

{}

Returns:

Type Description
Labels

The dataset as a Labels object.

Source code in sleap_io/io/main.py
def load_coco(
    json_path: str,
    dataset_root: Optional[str] = None,
    grayscale: bool = False,
    **kwargs,
) -> Labels:
    """Load a COCO-style pose dataset and return a Labels object.

    Args:
        json_path: Path to the COCO annotation JSON file.
        dataset_root: Root directory of the dataset. If None, uses parent directory
                     of json_path.
        grayscale: If True, load images as grayscale (1 channel). If False, load as
                   RGB (3 channels). Default is False.
        **kwargs: Additional arguments (currently unused).

    Returns:
        The dataset as a `Labels` object.
    """
    return coco.read_labels(json_path, dataset_root=dataset_root, grayscale=grayscale)

Ultralytics YOLO Format

Support for Ultralytics YOLO pose format.

sleap_io.load_ultralytics(dataset_path, split='train', skeleton=None, **kwargs)

Load an Ultralytics YOLO pose dataset as a SLEAP Labels object.

Parameters:

Name Type Description Default
dataset_path str

Path to the Ultralytics dataset root directory containing data.yaml.

required
split str

Dataset split to read ('train', 'val', or 'test'). Defaults to 'train'.

'train'
skeleton Optional[Skeleton]

Optional skeleton to use. If not provided, will be inferred from data.yaml.

None
**kwargs

Additional arguments passed to ultralytics.read_labels. Currently supports: - image_size: Tuple of (height, width) for coordinate denormalization. Defaults to (480, 640). Will attempt to infer from actual images if available.

{}

Returns:

Type Description
Labels

The dataset as a Labels object.

Source code in sleap_io/io/main.py
def load_ultralytics(
    dataset_path: str,
    split: str = "train",
    skeleton: Optional[Skeleton] = None,
    **kwargs,
) -> Labels:
    """Load an Ultralytics YOLO pose dataset as a SLEAP `Labels` object.

    Args:
        dataset_path: Path to the Ultralytics dataset root directory containing
            data.yaml.
        split: Dataset split to read ('train', 'val', or 'test'). Defaults to 'train'.
        skeleton: Optional skeleton to use. If not provided, will be inferred from
            data.yaml.
        **kwargs: Additional arguments passed to `ultralytics.read_labels`.
            Currently supports:
            - image_size: Tuple of (height, width) for coordinate denormalization.
              Defaults to
              (480, 640). Will attempt to infer from actual images if available.

    Returns:
        The dataset as a `Labels` object.
    """
    return ultralytics.read_labels(
        dataset_path, split=split, skeleton=skeleton, **kwargs
    )

sleap_io.save_ultralytics(labels, dataset_path, split_ratios={'train': 0.8, 'val': 0.2}, **kwargs)

Save a SLEAP dataset to Ultralytics YOLO pose format.

Parameters:

Name Type Description Default
labels Labels

A SLEAP Labels object.

required
dataset_path str

Path to save the Ultralytics dataset.

required
split_ratios dict

Dictionary mapping split names to ratios (must sum to 1.0). Defaults to {"train": 0.8, "val": 0.2}.

{'train': 0.8, 'val': 0.2}
**kwargs

Additional arguments passed to ultralytics.write_labels. Currently supports: - class_id: Class ID to use for all instances (default: 0). - image_format: Image format to use for saving frames. Either "png" (default, lossless) or "jpg". - image_quality: Image quality for JPEG format (1-100). For PNG, this is the compression level (0-9). If None, uses default quality settings. - verbose: If True (default), show progress bars during export. - use_multiprocessing: If True, use multiprocessing for parallel image saving. Default is False. - n_workers: Number of worker processes. If None, uses CPU count - 1. Only used if use_multiprocessing=True.

{}
Source code in sleap_io/io/main.py
def save_ultralytics(
    labels: Labels,
    dataset_path: str,
    split_ratios: dict = {"train": 0.8, "val": 0.2},
    **kwargs,
):
    """Save a SLEAP dataset to Ultralytics YOLO pose format.

    Args:
        labels: A SLEAP `Labels` object.
        dataset_path: Path to save the Ultralytics dataset.
        split_ratios: Dictionary mapping split names to ratios (must sum to 1.0).
                     Defaults to {"train": 0.8, "val": 0.2}.
        **kwargs: Additional arguments passed to `ultralytics.write_labels`.
            Currently supports:
            - class_id: Class ID to use for all instances (default: 0).
            - image_format: Image format to use for saving frames. Either "png"
              (default, lossless) or "jpg".
            - image_quality: Image quality for JPEG format (1-100). For PNG, this is
              the compression
              level (0-9). If None, uses default quality settings.
            - verbose: If True (default), show progress bars during export.
            - use_multiprocessing: If True, use multiprocessing for parallel image
              saving. Default is False.
            - n_workers: Number of worker processes. If None, uses CPU count - 1.
              Only used if
              use_multiprocessing=True.
    """
    ultralytics.write_labels(labels, dataset_path, split_ratios=split_ratios, **kwargs)

Working with Multiple Datasets

Load Multiple Files

Load and combine multiple pose tracking files:

sleap_io.load_labels_set(path, format=None, open_videos=True, **kwargs)

Load a LabelsSet from multiple files.

Parameters:

Name Type Description Default
path Union[str, Path, list[Union[str, Path]], dict[str, Union[str, Path]]]

Can be one of: - A directory path containing label files - A list of file paths - A dictionary mapping names to file paths

required
format Optional[str]

Optional format specification. If None, will try to infer from path. Supported formats: "slp", "ultralytics"

None
open_videos bool

If True (the default), attempt to open video backends.

True
**kwargs

Additional format-specific arguments.

{}

Returns:

Type Description
LabelsSet

A LabelsSet containing the loaded Labels objects.

Examples:

Load from SLP directory:

>>> labels_set = load_labels_set("path/to/splits/")

Load from list of SLP files:

>>> labels_set = load_labels_set(["train.slp", "val.slp"])

Load from Ultralytics dataset:

>>> labels_set = load_labels_set("path/to/yolo_dataset/", format="ultralytics")
Source code in sleap_io/io/main.py
def load_labels_set(
    path: Union[str, Path, list[Union[str, Path]], dict[str, Union[str, Path]]],
    format: Optional[str] = None,
    open_videos: bool = True,
    **kwargs,
) -> LabelsSet:
    """Load a LabelsSet from multiple files.

    Args:
        path: Can be one of:
            - A directory path containing label files
            - A list of file paths
            - A dictionary mapping names to file paths
        format: Optional format specification. If None, will try to infer from path.
            Supported formats: "slp", "ultralytics"
        open_videos: If `True` (the default), attempt to open video backends.
        **kwargs: Additional format-specific arguments.

    Returns:
        A LabelsSet containing the loaded Labels objects.

    Examples:
        Load from SLP directory:
        >>> labels_set = load_labels_set("path/to/splits/")

        Load from list of SLP files:
        >>> labels_set = load_labels_set(["train.slp", "val.slp"])

        Load from Ultralytics dataset:
        >>> labels_set = load_labels_set("path/to/yolo_dataset/", format="ultralytics")
    """
    # Try to infer format if not specified
    if format is None:
        if isinstance(path, (str, Path)):
            path_obj = Path(path)
            if path_obj.is_dir():
                # Check for ultralytics structure
                if (path_obj / "data.yaml").exists() or any(
                    (path_obj / split).exists() for split in ["train", "val", "test"]
                ):
                    format = "ultralytics"
                else:
                    # Default to SLP for directories
                    format = "slp"
            else:
                # Single file path - check extension
                if path_obj.suffix == ".slp":
                    format = "slp"
        elif isinstance(path, list) and len(path) > 0:
            # Check first file in list
            first_path = Path(path[0])
            if first_path.suffix == ".slp":
                format = "slp"
        elif isinstance(path, dict):
            # Dictionary input defaults to SLP
            format = "slp"

    if format == "slp":
        return slp.read_labels_set(path, open_videos=open_videos)
    elif format == "ultralytics":
        # Extract ultralytics-specific kwargs
        splits = kwargs.pop("splits", None)
        skeleton = kwargs.pop("skeleton", None)
        image_size = kwargs.pop("image_size", (480, 640))
        # Remove verbose from kwargs if present (for backward compatibility)
        kwargs.pop("verbose", None)

        if not isinstance(path, (str, Path)):
            raise ValueError(
                "Ultralytics format requires a directory path, "
                f"got {type(path).__name__}"
            )

        return ultralytics.read_labels_set(
            str(path),
            splits=splits,
            skeleton=skeleton,
            image_size=image_size,
        )
    else:
        raise ValueError(
            f"Unknown format: {format}. Supported formats: 'slp', 'ultralytics'"
        )

Skeleton Files

Load and save skeleton definitions separately:

sleap_io.load_skeleton(filename)

Load skeleton(s) from a JSON, YAML, or SLP file.

Parameters:

Name Type Description Default
filename str | Path

Path to a skeleton file. Supported formats: - JSON: Standalone skeleton or training config with embedded skeletons - YAML: Simplified skeleton format - SLP: SLEAP project file

required

Returns:

Type Description
Union[Skeleton, List[Skeleton]]

A single Skeleton or list of Skeleton objects.

Notes

This function loads skeletons from various file types: - JSON files: Can be standalone skeleton files (jsonpickle format) or training config files with embedded skeletons - YAML files: Use a simplified human-readable format - SLP files: Extracts skeletons from SLEAP project files The format is detected based on the file extension and content.

Source code in sleap_io/io/main.py
def load_skeleton(filename: str | Path) -> Union[Skeleton, List[Skeleton]]:
    """Load skeleton(s) from a JSON, YAML, or SLP file.

    Args:
        filename: Path to a skeleton file. Supported formats:
            - JSON: Standalone skeleton or training config with embedded skeletons
            - YAML: Simplified skeleton format
            - SLP: SLEAP project file

    Returns:
        A single `Skeleton` or list of `Skeleton` objects.

    Notes:
        This function loads skeletons from various file types:
        - JSON files: Can be standalone skeleton files (jsonpickle format) or training
          config files with embedded skeletons
        - YAML files: Use a simplified human-readable format
        - SLP files: Extracts skeletons from SLEAP project files
        The format is detected based on the file extension and content.
    """
    if isinstance(filename, Path):
        filename = str(filename)

    # Detect format based on extension
    if filename.lower().endswith(".slp"):
        # SLP format - extract skeletons from SLEAP file
        from sleap_io.io.slp import read_skeletons

        return read_skeletons(filename)
    elif filename.lower().endswith((".yaml", ".yml")):
        # YAML format
        with open(filename, "r") as f:
            yaml_data = f.read()
        decoder = SkeletonYAMLDecoder()
        return decoder.decode(yaml_data)
    else:
        # JSON format (default) - could be standalone or training config
        import json

        with open(filename, "r") as f:
            json_data = f.read()

        # Try to detect if this is a training config file
        try:
            data = json.loads(json_data)
            if isinstance(data, dict) and "data" in data:
                if "labels" in data["data"] and "skeletons" in data["data"]["labels"]:
                    # This is a training config file with embedded skeletons
                    decoder = SkeletonDecoder()
                    return decoder.decode(data["data"]["labels"]["skeletons"])
        except (json.JSONDecodeError, KeyError, TypeError):
            # Not a training config or invalid JSON structure
            pass

        # Fall back to regular skeleton JSON decoding
        decoder = SkeletonDecoder()
        return decoder.decode(json_data)

sleap_io.save_skeleton(skeleton, filename)

Save skeleton(s) to a JSON or YAML file.

Parameters:

Name Type Description Default
skeleton Union[Skeleton, List[Skeleton]]

A single Skeleton or list of Skeleton objects to save.

required
filename str | Path

Path to save the skeleton file.

required
Notes

This function saves skeletons in either JSON or YAML format based on the file extension. JSON files use the jsonpickle format compatible with SLEAP, while YAML files use a simplified human-readable format.

Source code in sleap_io/io/main.py
def save_skeleton(skeleton: Union[Skeleton, List[Skeleton]], filename: str | Path):
    """Save skeleton(s) to a JSON or YAML file.

    Args:
        skeleton: A single `Skeleton` or list of `Skeleton` objects to save.
        filename: Path to save the skeleton file.

    Notes:
        This function saves skeletons in either JSON or YAML format based on the
        file extension. JSON files use the jsonpickle format compatible with SLEAP,
        while YAML files use a simplified human-readable format.
    """
    if isinstance(filename, Path):
        filename = str(filename)

    # Detect format based on extension
    if filename.lower().endswith((".yaml", ".yml")):
        # YAML format
        encoder = SkeletonYAMLEncoder()
        yaml_data = encoder.encode(skeleton)
        with open(filename, "w") as f:
            f.write(yaml_data)
    else:
        # JSON format (default)
        encoder = SkeletonEncoder()
        json_data = encoder.encode(skeleton)
        with open(filename, "w") as f:
            f.write(json_data)

Format Detection

sleap-io automatically detects file formats based on:

  1. File extension: .slp, .nwb, .h5, .json, .mat, .csv
  2. File content: For ambiguous extensions like .h5 (JABS vs DLC) or .json (Label Studio vs COCO)
  3. Explicit format: Pass format parameter to override auto-detection

Format Conversion Examples

Convert Between Formats

import sleap_io as sio

# Load from any supported format
labels = sio.load_file("data.slp")

# Save to different formats
labels.save("data.nwb")  # NWB format
labels.save("data.labelstudio.json")  # Label Studio
labels.save("data_yolo/")  # Ultralytics YOLO

Batch Conversion

import sleap_io as sio
from pathlib import Path

# Convert all SLEAP files to NWB
for slp_file in Path("data/").glob("*.slp"):
    labels = sio.load_file(slp_file)
    nwb_file = slp_file.with_suffix(".nwb")
    labels.save(nwb_file)

Round-Trip Preservation

Most formats preserve data during round-trip conversion:

import sleap_io as sio

# Load original
labels_original = sio.load_file("data.slp")

# Save and reload
labels_original.save("temp.nwb")
labels_reloaded = sio.load_file("temp.nwb")

# Data is preserved
assert len(labels_original) == len(labels_reloaded)
assert labels_original.skeleton == labels_reloaded.skeleton

Format Limitations

Different formats have varying capabilities:

Format Read Write Videos Skeletons Tracks Confidence User/Predicted
SLEAP (.slp)
NWB (.nwb) ✅*
JABS (.h5)
Label Studio
DeepLabCut
AlphaTracker
LEAP (.mat)
COCO
Ultralytics

*NWB can embed videos with annotations_export format

See Also

  • Data Model: Understanding the core data structures
  • Examples: More usage examples and recipes
  • Merging: Combining data from multiple sources