Skip to content

geojson

sleap_io.io.geojson

GeoJSON I/O for ROIs.

Provides reading and writing of ROIs in GeoJSON format (RFC 7946). The output is a GeoJSON FeatureCollection where each Feature corresponds to one ROI. This format is human-readable, compatible with the movement library (v0.15.0+), and supported by the broader geospatial Python ecosystem (Shapely, GeoPandas, QGIS, QuPath).

Classes:

Name Description
ROI

A region of interest defined by vector geometry.

UserROI

Human-annotated region of interest.

Functions:

Name Description
read_rois

Read ROIs from a GeoJSON file.

write_rois

Write ROIs to a GeoJSON FeatureCollection file.

Attributes:

Name Type Description
__cached__

str(object='') -> str

__doc__

str(object='') -> str

__file__

str(object='') -> str

__name__

str(object='') -> str

__package__

str(object='') -> str

__cached__ = '/home/runner/work/sleap-io/sleap-io/sleap_io/io/__pycache__/geojson.cpython-313.pyc' module-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

__doc__ = 'GeoJSON I/O for ROIs.\n\nProvides reading and writing of ROIs in GeoJSON format (RFC 7946). The output is\na GeoJSON FeatureCollection where each Feature corresponds to one ROI. This format\nis human-readable, compatible with the `movement` library (v0.15.0+), and supported\nby the broader geospatial Python ecosystem (Shapely, GeoPandas, QGIS, QuPath).\n' module-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

__file__ = '/home/runner/work/sleap-io/sleap-io/sleap_io/io/geojson.py' module-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

__name__ = 'sleap_io.io.geojson' module-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

__package__ = 'sleap_io.io' module-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

ROI

A region of interest defined by vector geometry.

ROIs store Shapely geometry objects and optional metadata for associating annotations with videos, frames, tracks, and instances.

Attributes:

Name Type Description
geometry

A Shapely geometry object (e.g., Polygon, box, Point).

name

Optional human-readable name for this ROI.

category

Optional Category (class label, e.g. class name for detection) for this ROI. Promoted from the legacy free-form string; None if unset. Mirrors Instance.category.

source

Optional string indicating the source of this annotation.

video

Optional Video this ROI is associated with. Used for static ROIs that are not tied to any specific frame.

track

Optional Track this ROI is associated with.

tracking_score

Confidence of the track identity assignment. None if unassigned or manually assigned.

identity

Optional global, ground-truth Identity for this ROI -- the persistent cross-video animal identity / re-identification key. None if no global identity is assigned. Mirrors Instance.identity.

identity_score

Score associated with the identity assignment (e.g. the re-ID match similarity). None if unassigned or assigned manually. Kept separate from tracking_score (short-term tracklet vs long-term identity).

instance

Optional Instance this ROI is associated with. Persisted in SLP format (v1.6+) via instance index.

identity_embedding

Optional Embedding describing this detection's appearance for re-identification. None by default.

category_score

Score associated with the category assignment (e.g. the classifier confidence). None if unassigned or assigned manually.

category_embedding

Optional Embedding describing this detection's appearance for classification. None by default.

Notes

ROIs use identity-based equality (two ROI objects are only equal if they are the same object in memory).

Methods:

Name Description
__attrs_post_init__

Validate that this class is not instantiated directly.

__init__

Method generated by attrs for class ROI.

__repr__

Method generated by attrs for class ROI.

__setattr__

Method generated by attrs for class ROI.

explode

Split a multi-geometry ROI into individual ROIs.

from_bbox

Create an ROI from a bounding box in xywh format.

from_multi_polygon

Create an ROI from multiple polygon coordinate sequences.

from_polygon

Create an ROI from polygon coordinates.

from_xyxy

Create an ROI from a bounding box in xyxy (min/max) format.

to_bbox

Reduce this ROI to a bounding box.

to_centroid

Reduce this ROI to a single centroid point.

to_mask

Rasterize this ROI into a binary segmentation mask.

Source code in sleap_io/model/roi.py
@attrs.define(eq=False)
class ROI:
    """A region of interest defined by vector geometry.

    ROIs store Shapely geometry objects and optional metadata for associating
    annotations with videos, frames, tracks, and instances.

    Attributes:
        geometry: A Shapely geometry object (e.g., `Polygon`, `box`, `Point`).
        name: Optional human-readable name for this ROI.
        category: Optional `Category` (class label, e.g. class name for
            detection) for this ROI. Promoted from the legacy free-form string;
            ``None`` if unset. Mirrors `Instance.category`.
        source: Optional string indicating the source of this annotation.
        video: Optional `Video` this ROI is associated with. Used for static ROIs
            that are not tied to any specific frame.
        track: Optional `Track` this ROI is associated with.
        tracking_score: Confidence of the track identity assignment. ``None``
            if unassigned or manually assigned.
        identity: Optional global, ground-truth `Identity` for this ROI -- the
            persistent cross-video animal identity / re-identification key. ``None``
            if no global identity is assigned. Mirrors `Instance.identity`.
        identity_score: Score associated with the `identity` assignment (e.g. the
            re-ID match similarity). ``None`` if unassigned or assigned manually.
            Kept separate from `tracking_score` (short-term tracklet vs long-term
            identity).
        instance: Optional `Instance` this ROI is associated with. Persisted in
            SLP format (v1.6+) via instance index.
        identity_embedding: Optional `Embedding` describing this detection's
            appearance for re-identification. ``None`` by default.
        category_score: Score associated with the `category` assignment (e.g. the
            classifier confidence). ``None`` if unassigned or assigned manually.
        category_embedding: Optional `Embedding` describing this detection's
            appearance for classification. ``None`` by default.

    Notes:
        ROIs use identity-based equality (two ROI objects are only equal if they
        are the same object in memory).
    """

    geometry: "BaseGeometry" = attrs.field()

    @geometry.validator
    def _validate_geometry(self, attribute, value):
        """Validate that geometry is a Shapely BaseGeometry instance."""
        from shapely.geometry.base import BaseGeometry

        if not isinstance(value, BaseGeometry):
            raise TypeError(
                f"geometry must be a Shapely BaseGeometry instance, "
                f"got {type(value).__name__}"
            )

    name: str = attrs.field(default="")
    category: "Category | None" = attrs.field(default=None, converter=to_category)
    source: str = attrs.field(default="")
    video: "Video | None" = attrs.field(default=None)
    track: "Track | None" = attrs.field(default=None)
    tracking_score: float | None = attrs.field(default=None)
    identity: "Identity | None" = attrs.field(default=None)
    identity_score: float | None = attrs.field(default=None)
    instance: "Instance | None" = attrs.field(default=None)
    identity_embedding: "Embedding | None" = attrs.field(default=None, repr=False)
    category_score: float | None = attrs.field(default=None)
    category_embedding: "Embedding | None" = attrs.field(default=None, repr=False)

    # Private: deferred instance index for lazy loading. When ROIs are read
    # from a file without materialized instances (e.g., lazy mode), this stores
    # the raw instance_idx so it can be resolved later or written back as-is.
    _instance_idx: int = attrs.field(default=-1, repr=False, eq=False, init=False)

    def __attrs_post_init__(self):
        """Validate that this class is not instantiated directly."""
        if type(self) is ROI:
            raise TypeError("ROI is abstract. Use UserROI or PredictedROI.")

    @property
    def is_predicted(self) -> bool:
        """Whether this ROI is a model prediction."""
        return isinstance(self, PredictedROI)

    @property
    def is_empty(self) -> bool:
        """Whether this ROI's geometry is empty (no spatial extent)."""
        return bool(self.geometry.is_empty)

    @classmethod
    def from_bbox(
        cls,
        x: float,
        y: float,
        width: float,
        height: float,
        **kwargs,
    ) -> "ROI":
        """Create an ROI from a bounding box in xywh format.

        Args:
            x: Left edge x-coordinate.
            y: Top edge y-coordinate.
            width: Width of the bounding box.
            height: Height of the bounding box.
            **kwargs: Additional keyword arguments passed to the ROI constructor.

        Returns:
            An ROI with a rectangular polygon geometry.

        Note:
            For detection bounding boxes, prefer ``BoundingBox.from_xywh()`` or
            ``BoundingBox.from_xyxy()`` which provide richer metadata support.

        .. deprecated::
            Use ``BoundingBox.from_xywh()`` for detection bounding boxes.
        """
        import warnings

        warnings.warn(
            "ROI.from_bbox() is deprecated. Use BoundingBox.from_xywh() instead.",
            DeprecationWarning,
            stacklevel=2,
        )
        from shapely.geometry import box

        geom = box(x, y, x + width, y + height)
        return cls(geometry=geom, **kwargs)

    @classmethod
    def from_xyxy(
        cls,
        x1: float,
        y1: float,
        x2: float,
        y2: float,
        **kwargs,
    ) -> "ROI":
        """Create an ROI from a bounding box in xyxy (min/max) format.

        Args:
            x1: Left edge x-coordinate.
            y1: Top edge y-coordinate.
            x2: Right edge x-coordinate.
            y2: Bottom edge y-coordinate.
            **kwargs: Additional keyword arguments passed to the ROI constructor.

        Returns:
            An ROI with a rectangular polygon geometry.

        Note:
            For detection bounding boxes, prefer ``BoundingBox.from_xywh()`` or
            ``BoundingBox.from_xyxy()`` which provide richer metadata support.

        .. deprecated::
            Use ``BoundingBox.from_xyxy()`` for detection bounding boxes.
        """
        import warnings

        warnings.warn(
            "ROI.from_xyxy() is deprecated. Use BoundingBox.from_xyxy() instead.",
            DeprecationWarning,
            stacklevel=2,
        )
        from shapely.geometry import box

        geom = box(x1, y1, x2, y2)
        return cls(geometry=geom, **kwargs)

    @classmethod
    def from_polygon(
        cls,
        coords: list[tuple[float, float]] | np.ndarray,
        **kwargs,
    ) -> "ROI":
        """Create an ROI from polygon coordinates.

        Args:
            coords: A sequence of (x, y) coordinate pairs defining the polygon
                exterior ring. The polygon will be closed automatically.
            **kwargs: Additional keyword arguments passed to the ROI constructor.

        Returns:
            An ROI with a polygon geometry.
        """
        from shapely.geometry import Polygon

        geom = Polygon(coords)
        return cls(geometry=geom, **kwargs)

    @classmethod
    def from_multi_polygon(
        cls,
        polygons: list[list[tuple[float, float]] | np.ndarray],
        **kwargs,
    ) -> "ROI":
        """Create an ROI from multiple polygon coordinate sequences.

        Args:
            polygons: A list of polygon coordinate sequences. Each sequence is a
                list of (x, y) pairs defining a polygon exterior ring.
            **kwargs: Additional keyword arguments passed to the ROI constructor.

        Returns:
            An ROI with a MultiPolygon geometry.
        """
        from shapely.geometry import MultiPolygon, Polygon

        geom = MultiPolygon([Polygon(coords) for coords in polygons])
        return cls(geometry=geom, **kwargs)

    @property
    def is_bbox(self) -> bool:
        """Whether this ROI's geometry is a rectangular bounding box."""
        from shapely.geometry import Polygon

        if not isinstance(self.geometry, Polygon):
            return False
        # A rectangle has exactly 5 coordinates (closed ring) and the
        # minimum rotated rectangle has the same area.
        coords = list(self.geometry.exterior.coords)
        if len(coords) != 5:
            return False
        # Check if aligned to axes (all edges parallel to x or y axis)
        for i in range(4):
            dx = abs(coords[i + 1][0] - coords[i][0])
            dy = abs(coords[i + 1][1] - coords[i][1])
            if dx > 1e-10 and dy > 1e-10:
                return False
        return True

    @property
    def bounds(self) -> tuple[float, float, float, float]:
        """Bounding box as (minx, miny, maxx, maxy)."""
        return self.geometry.bounds

    @property
    def area(self) -> float:
        """Area of the geometry."""
        return self.geometry.area

    @property
    def centroid_xy(self) -> tuple[float, float]:
        """Centroid of the geometry as ``(x, y)``."""
        c = self.geometry.centroid
        return (c.x, c.y)

    @property
    def __geo_interface__(self) -> dict:
        """GeoJSON-compatible Feature representation.

        Returns a GeoJSON Feature dict following the Python `__geo_interface__`
        protocol. The Feature contains the ROI's geometry and metadata properties.

        Returns:
            A dictionary with ``"type"``, ``"geometry"``, and ``"properties"`` keys.
        """
        from shapely.geometry import mapping

        return {
            "type": "Feature",
            "geometry": mapping(self.geometry),
            "properties": {
                "name": self.name,
                "category": self.category.name if self.category is not None else "",
                "source": self.source,
            },
        }

    def to_mask(self, height: int, width: int) -> "SegmentationMask":
        """Rasterize this ROI into a binary segmentation mask.

        A `PredictedROI` produces a `PredictedSegmentationMask` carrying its
        `score`; any other ROI produces a `UserSegmentationMask`. Metadata
        (name, category, source, track, instance) is inherited either way.

        Args:
            height: Height of the output mask in pixels.
            width: Width of the output mask in pixels.

        Returns:
            A `SegmentationMask` with the rasterized geometry.
        """
        from sleap_io.model.mask import (
            PredictedSegmentationMask,
            UserSegmentationMask,
        )

        # Rasterize geometry to binary mask
        mask = _rasterize_geometry(self.geometry, height, width)

        kwargs = dict(
            name=self.name,
            category=self.category,
            category_score=self.category_score,
            category_embedding=self.category_embedding,
            source=self.source,
            track=self.track,
            tracking_score=self.tracking_score,
            identity=self.identity,
            identity_score=self.identity_score,
            identity_embedding=self.identity_embedding,
            instance=self.instance,
        )
        if self.is_predicted:
            return PredictedSegmentationMask.from_numpy(
                mask, score=self.score, **kwargs
            )
        return UserSegmentationMask.from_numpy(mask, **kwargs)

    def to_centroid(
        self, representative: bool = False, error_on_empty: bool = False
    ) -> "Centroid":
        """Reduce this ROI to a single centroid point.

        A `PredictedROI` produces a `PredictedCentroid` carrying its `score`; any
        other ROI produces a `UserCentroid`. Metadata (track, tracking_score,
        identity, identity_score, category, name, source, instance) is inherited.

        Args:
            representative: If ``True``, use Shapely's ``representative_point()``
                (a point guaranteed to lie within the geometry); otherwise use the
                geometric ``centroid`` (which may fall outside concave shapes).
            error_on_empty: If ``True``, raise ``ValueError`` when the geometry is
                empty instead of returning a degenerate (NaN) centroid.

        Returns:
            A `Centroid` at the geometry's centroid (or NaN if empty).

        Raises:
            ValueError: If the geometry is empty and ``error_on_empty`` is ``True``.
        """
        from sleap_io.model.centroid import PredictedCentroid, UserCentroid

        if self.geometry.is_empty:
            if error_on_empty:
                raise ValueError("Cannot compute centroid of an empty ROI geometry.")
            x = y = float("nan")
        else:
            pt = (
                self.geometry.representative_point()
                if representative
                else self.geometry.centroid
            )
            x, y = float(pt.x), float(pt.y)

        kwargs = dict(
            x=x,
            y=y,
            track=self.track,
            tracking_score=self.tracking_score,
            identity=self.identity,
            identity_score=self.identity_score,
            identity_embedding=self.identity_embedding,
            instance=self.instance,
            category=self.category,
            category_score=self.category_score,
            category_embedding=self.category_embedding,
            name=self.name,
            source=self.source,
        )
        if self.is_predicted:
            return PredictedCentroid(score=self.score, **kwargs)
        return UserCentroid(**kwargs)

    def to_bbox(
        self,
        padding: float | tuple[float, float] = 0.0,
        rotated: bool = False,
        error_on_empty: bool = False,
    ) -> "BoundingBox":
        """Reduce this ROI to a bounding box.

        A `PredictedROI` produces a `PredictedBoundingBox` carrying its `score`;
        any other ROI produces a `UserBoundingBox`. Metadata (track,
        tracking_score, identity, identity_score, category, name, source,
        instance) is inherited.

        Args:
            padding: Amount to inflate the box outward. Scalar applies to both
                axes; a ``(px, py)`` tuple applies per-axis. Negative values
                shrink the box. For rotated boxes, padding enlarges the
                pre-rotation extent about the center while preserving the angle.
            rotated: If ``True``, fit a minimum-area oriented box (rotated). If
                ``False``, fit an axis-aligned box from the geometry bounds.
            error_on_empty: If ``True``, raise ``ValueError`` when the geometry is
                empty instead of returning a degenerate (NaN) box.

        Returns:
            A `BoundingBox` enclosing the geometry (or NaN corners if empty).

        Raises:
            ValueError: If the geometry is empty and ``error_on_empty`` is ``True``.
        """
        from sleap_io.model.bbox import PredictedBoundingBox, UserBoundingBox

        if self.geometry.is_empty:
            if error_on_empty:
                raise ValueError(
                    "Cannot compute bounding box of an empty ROI geometry."
                )
            nan = float("nan")
            x1 = y1 = x2 = y2 = nan
            angle = 0.0
        else:
            x1, y1, x2, y2, angle = _geometry_to_bbox_coords(self.geometry, rotated)
            x1, y1, x2, y2 = _apply_padding(x1, y1, x2, y2, padding)

        kwargs = dict(
            x1=x1,
            y1=y1,
            x2=x2,
            y2=y2,
            angle=angle,
            track=self.track,
            tracking_score=self.tracking_score,
            identity=self.identity,
            identity_score=self.identity_score,
            identity_embedding=self.identity_embedding,
            instance=self.instance,
            category=self.category,
            category_score=self.category_score,
            category_embedding=self.category_embedding,
            name=self.name,
            source=self.source,
        )
        if self.is_predicted:
            return PredictedBoundingBox(score=self.score, **kwargs)
        return UserBoundingBox(**kwargs)

    def explode(self) -> list["ROI"]:
        """Split a multi-geometry ROI into individual ROIs.

        For ``MultiPolygon`` or ``GeometryCollection`` geometries, creates a
        separate ROI for each component geometry, preserving all metadata
        (name, category, source, video, track, instance).

        For single geometries (e.g., ``Polygon``, ``Point``), returns a list
        containing only this ROI.

        Returns:
            A list of ROIs, one per component geometry. For single geometries,
            returns ``[self]``.
        """
        from shapely.geometry import GeometryCollection, MultiPolygon

        if isinstance(self.geometry, (MultiPolygon, GeometryCollection)):
            extra = {"score": self.score} if hasattr(self, "score") else {}
            return [
                type(self)(
                    geometry=geom,
                    name=self.name,
                    category=self.category,
                    category_score=self.category_score,
                    category_embedding=self.category_embedding,
                    source=self.source,
                    video=self.video,
                    track=self.track,
                    tracking_score=self.tracking_score,
                    identity=self.identity,
                    identity_score=self.identity_score,
                    identity_embedding=self.identity_embedding,
                    instance=self.instance,
                    **extra,
                )
                for geom in self.geometry.geoms
            ]
        return [self]

__annotations__ = {'geometry': "'BaseGeometry'", 'name': 'str', 'category': "'Category | None'", 'source': 'str', 'video': "'Video | None'", 'track': "'Track | None'", 'tracking_score': 'float | None', 'identity': "'Identity | None'", 'identity_score': 'float | None', 'instance': "'Instance | None'", 'identity_embedding': "'Embedding | None'", 'category_score': 'float | None', 'category_embedding': "'Embedding | None'", '_instance_idx': 'int'} class-attribute

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

__attrs_own_setattr__ = True class-attribute

Returns True when the argument is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.

__attrs_props__ = ClassProps(is_exception=False, is_slotted=True, has_weakref_slot=True, is_frozen=False, kw_only=<KeywordOnly.NO: 'no'>, collected_fields_by_mro=True, added_init=True, added_repr=True, added_eq=False, added_ordering=False, hashability=<Hashability.LEAVE_ALONE: 'leave_alone'>, added_match_args=True, added_str=False, added_pickling=True, on_setattr_hook=<function pipe.<locals>.wrapped_pipe at 0x7f08471ce840>, field_transformer=None) class-attribute

Effective class properties as derived from parameters to attr.s() or define() decorators.

This is the same data structure that attrs uses internally to decide how to construct the final class.

Warning:

This feature is currently **experimental** and is not covered by our
strict backwards-compatibility guarantees.

Attributes:

Name Type Description
is_exception bool

Whether the class is treated as an exception class.

is_slotted bool

Whether the class is slotted <slotted classes>.

has_weakref_slot bool

Whether the class has a slot for weak references.

is_frozen bool

Whether the class is frozen.

kw_only KeywordOnly

Whether / how the class enforces keyword-only arguments on the __init__ method.

collected_fields_by_mro bool

Whether the class fields were collected by method resolution order. That is, correctly but unlike dataclasses.

added_init bool

Whether the class has an attrs-generated __init__ method.

added_repr bool

Whether the class has an attrs-generated __repr__ method.

added_eq bool

Whether the class has attrs-generated equality methods.

added_ordering bool

Whether the class has attrs-generated ordering methods.

hashability Hashability

How hashable <hashing> the class is.

added_match_args bool

Whether the class supports positional match <match> over its fields.

added_str bool

Whether the class has an attrs-generated __str__ method.

added_pickling bool

Whether the class has attrs-generated __getstate__ and __setstate__ methods for pickle.

on_setattr_hook Callable[[Any, Attribute[Any], Any], Any] | None

The class's __setattr__ hook.

field_transformer Callable[[Attribute[Any]], Attribute[Any]] | None

The class's field transformers <transform-fields>.

.. versionadded:: 25.4.0

__doc__ = "A region of interest defined by vector geometry.\n\nROIs store Shapely geometry objects and optional metadata for associating\nannotations with videos, frames, tracks, and instances.\n\nAttributes:\n geometry: A Shapely geometry object (e.g., `Polygon`, `box`, `Point`).\n name: Optional human-readable name for this ROI.\n category: Optional `Category` (class label, e.g. class name for\n detection) for this ROI. Promoted from the legacy free-form string;\n ``None`` if unset. Mirrors `Instance.category`.\n source: Optional string indicating the source of this annotation.\n video: Optional `Video` this ROI is associated with. Used for static ROIs\n that are not tied to any specific frame.\n track: Optional `Track` this ROI is associated with.\n tracking_score: Confidence of the track identity assignment. ``None``\n if unassigned or manually assigned.\n identity: Optional global, ground-truth `Identity` for this ROI -- the\n persistent cross-video animal identity / re-identification key. ``None``\n if no global identity is assigned. Mirrors `Instance.identity`.\n identity_score: Score associated with the `identity` assignment (e.g. the\n re-ID match similarity). ``None`` if unassigned or assigned manually.\n Kept separate from `tracking_score` (short-term tracklet vs long-term\n identity).\n instance: Optional `Instance` this ROI is associated with. Persisted in\n SLP format (v1.6+) via instance index.\n identity_embedding: Optional `Embedding` describing this detection's\n appearance for re-identification. ``None`` by default.\n category_score: Score associated with the `category` assignment (e.g. the\n classifier confidence). ``None`` if unassigned or assigned manually.\n category_embedding: Optional `Embedding` describing this detection's\n appearance for classification. ``None`` by default.\n\nNotes:\n ROIs use identity-based equality (two ROI objects are only equal if they\n are the same object in memory).\n" class-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

__firstlineno__ = 52 class-attribute

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer iteral.

int('0b100', base=0) 4

__geo_interface__ property

GeoJSON-compatible Feature representation.

Returns a GeoJSON Feature dict following the Python __geo_interface__ protocol. The Feature contains the ROI's geometry and metadata properties.

Returns:

Type Description

A dictionary with "type", "geometry", and "properties" keys.

__match_args__ = ('geometry', 'name', 'category', 'source', 'video', 'track', 'tracking_score', 'identity', 'identity_score', 'instance', 'identity_embedding', 'category_score', 'category_embedding') class-attribute

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

__module__ = 'sleap_io.model.roi' class-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

__slots__ = ('geometry', 'name', 'category', 'source', 'video', 'track', 'tracking_score', 'identity', 'identity_score', 'instance', 'identity_embedding', 'category_score', 'category_embedding', '_instance_idx', '__weakref__') class-attribute

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

__static_attributes__ = () class-attribute

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

__weakref__ property

list of weak references to the object

area property

Area of the geometry.

bounds property

Bounding box as (minx, miny, maxx, maxy).

centroid_xy property

Centroid of the geometry as (x, y).

is_bbox property

Whether this ROI's geometry is a rectangular bounding box.

is_empty property

Whether this ROI's geometry is empty (no spatial extent).

is_predicted property

Whether this ROI is a model prediction.

__attrs_post_init__()

Validate that this class is not instantiated directly.

Source code in sleap_io/model/roi.py
def __attrs_post_init__(self):
    """Validate that this class is not instantiated directly."""
    if type(self) is ROI:
        raise TypeError("ROI is abstract. Use UserROI or PredictedROI.")

__init__(geometry, name='', category=None, source='', video=None, track=None, tracking_score=None, identity=None, identity_score=None, instance=None, identity_embedding=None, category_score=None, category_embedding=None)

Method generated by attrs for class ROI.

Source code in sleap_io/model/roi.py
import numpy as np

from sleap_io.model.category import to_category

if TYPE_CHECKING:
    from shapely.geometry import Polygon
    from shapely.geometry.base import BaseGeometry

    from sleap_io.model.bbox import BoundingBox
    from sleap_io.model.category import Category
    from sleap_io.model.centroid import Centroid
    from sleap_io.model.embedding import Embedding
    from sleap_io.model.identity import Identity
    from sleap_io.model.instance import Instance, Track
    from sleap_io.model.mask import SegmentationMask
    from sleap_io.model.video import Video


class AnnotationType(IntEnum):

__repr__()

Method generated by attrs for class ROI.

Source code in sleap_io/model/roi.py
"""Data structures for region of interest (ROI) annotations.

ROIs represent vector geometry annotations such as polygons and arbitrary shapes.
They use Shapely geometries internally for spatial operations.

The `AnnotationType` enum is kept for backward compatibility with old file formats
but is no longer used as a field on `ROI` or `SegmentationMask`.
"""

from __future__ import annotations

from enum import IntEnum
from typing import TYPE_CHECKING

import attrs

__setattr__(name, val)

Method generated by attrs for class ROI.

explode()

Split a multi-geometry ROI into individual ROIs.

For MultiPolygon or GeometryCollection geometries, creates a separate ROI for each component geometry, preserving all metadata (name, category, source, video, track, instance).

For single geometries (e.g., Polygon, Point), returns a list containing only this ROI.

Returns:

Type Description
list[ROI]

A list of ROIs, one per component geometry. For single geometries, returns [self].

Source code in sleap_io/model/roi.py
def explode(self) -> list["ROI"]:
    """Split a multi-geometry ROI into individual ROIs.

    For ``MultiPolygon`` or ``GeometryCollection`` geometries, creates a
    separate ROI for each component geometry, preserving all metadata
    (name, category, source, video, track, instance).

    For single geometries (e.g., ``Polygon``, ``Point``), returns a list
    containing only this ROI.

    Returns:
        A list of ROIs, one per component geometry. For single geometries,
        returns ``[self]``.
    """
    from shapely.geometry import GeometryCollection, MultiPolygon

    if isinstance(self.geometry, (MultiPolygon, GeometryCollection)):
        extra = {"score": self.score} if hasattr(self, "score") else {}
        return [
            type(self)(
                geometry=geom,
                name=self.name,
                category=self.category,
                category_score=self.category_score,
                category_embedding=self.category_embedding,
                source=self.source,
                video=self.video,
                track=self.track,
                tracking_score=self.tracking_score,
                identity=self.identity,
                identity_score=self.identity_score,
                identity_embedding=self.identity_embedding,
                instance=self.instance,
                **extra,
            )
            for geom in self.geometry.geoms
        ]
    return [self]

from_bbox(x, y, width, height, **kwargs) classmethod

Create an ROI from a bounding box in xywh format.

Parameters:

Name Type Description Default
x float

Left edge x-coordinate.

required
y float

Top edge y-coordinate.

required
width float

Width of the bounding box.

required
height float

Height of the bounding box.

required
**kwargs

Additional keyword arguments passed to the ROI constructor.

required

Returns:

Type Description
ROI

An ROI with a rectangular polygon geometry.

Note

For detection bounding boxes, prefer BoundingBox.from_xywh() or BoundingBox.from_xyxy() which provide richer metadata support.

.. deprecated:: Use BoundingBox.from_xywh() for detection bounding boxes.

Source code in sleap_io/model/roi.py
@classmethod
def from_bbox(
    cls,
    x: float,
    y: float,
    width: float,
    height: float,
    **kwargs,
) -> "ROI":
    """Create an ROI from a bounding box in xywh format.

    Args:
        x: Left edge x-coordinate.
        y: Top edge y-coordinate.
        width: Width of the bounding box.
        height: Height of the bounding box.
        **kwargs: Additional keyword arguments passed to the ROI constructor.

    Returns:
        An ROI with a rectangular polygon geometry.

    Note:
        For detection bounding boxes, prefer ``BoundingBox.from_xywh()`` or
        ``BoundingBox.from_xyxy()`` which provide richer metadata support.

    .. deprecated::
        Use ``BoundingBox.from_xywh()`` for detection bounding boxes.
    """
    import warnings

    warnings.warn(
        "ROI.from_bbox() is deprecated. Use BoundingBox.from_xywh() instead.",
        DeprecationWarning,
        stacklevel=2,
    )
    from shapely.geometry import box

    geom = box(x, y, x + width, y + height)
    return cls(geometry=geom, **kwargs)

from_multi_polygon(polygons, **kwargs) classmethod

Create an ROI from multiple polygon coordinate sequences.

Parameters:

Name Type Description Default
polygons list[list[tuple[float, float]] | ndarray]

A list of polygon coordinate sequences. Each sequence is a list of (x, y) pairs defining a polygon exterior ring.

required
**kwargs

Additional keyword arguments passed to the ROI constructor.

required

Returns:

Type Description
ROI

An ROI with a MultiPolygon geometry.

Source code in sleap_io/model/roi.py
@classmethod
def from_multi_polygon(
    cls,
    polygons: list[list[tuple[float, float]] | np.ndarray],
    **kwargs,
) -> "ROI":
    """Create an ROI from multiple polygon coordinate sequences.

    Args:
        polygons: A list of polygon coordinate sequences. Each sequence is a
            list of (x, y) pairs defining a polygon exterior ring.
        **kwargs: Additional keyword arguments passed to the ROI constructor.

    Returns:
        An ROI with a MultiPolygon geometry.
    """
    from shapely.geometry import MultiPolygon, Polygon

    geom = MultiPolygon([Polygon(coords) for coords in polygons])
    return cls(geometry=geom, **kwargs)

from_polygon(coords, **kwargs) classmethod

Create an ROI from polygon coordinates.

Parameters:

Name Type Description Default
coords list[tuple[float, float]] | ndarray

A sequence of (x, y) coordinate pairs defining the polygon exterior ring. The polygon will be closed automatically.

required
**kwargs

Additional keyword arguments passed to the ROI constructor.

required

Returns:

Type Description
ROI

An ROI with a polygon geometry.

Source code in sleap_io/model/roi.py
@classmethod
def from_polygon(
    cls,
    coords: list[tuple[float, float]] | np.ndarray,
    **kwargs,
) -> "ROI":
    """Create an ROI from polygon coordinates.

    Args:
        coords: A sequence of (x, y) coordinate pairs defining the polygon
            exterior ring. The polygon will be closed automatically.
        **kwargs: Additional keyword arguments passed to the ROI constructor.

    Returns:
        An ROI with a polygon geometry.
    """
    from shapely.geometry import Polygon

    geom = Polygon(coords)
    return cls(geometry=geom, **kwargs)

from_xyxy(x1, y1, x2, y2, **kwargs) classmethod

Create an ROI from a bounding box in xyxy (min/max) format.

Parameters:

Name Type Description Default
x1 float

Left edge x-coordinate.

required
y1 float

Top edge y-coordinate.

required
x2 float

Right edge x-coordinate.

required
y2 float

Bottom edge y-coordinate.

required
**kwargs

Additional keyword arguments passed to the ROI constructor.

required

Returns:

Type Description
ROI

An ROI with a rectangular polygon geometry.

Note

For detection bounding boxes, prefer BoundingBox.from_xywh() or BoundingBox.from_xyxy() which provide richer metadata support.

.. deprecated:: Use BoundingBox.from_xyxy() for detection bounding boxes.

Source code in sleap_io/model/roi.py
@classmethod
def from_xyxy(
    cls,
    x1: float,
    y1: float,
    x2: float,
    y2: float,
    **kwargs,
) -> "ROI":
    """Create an ROI from a bounding box in xyxy (min/max) format.

    Args:
        x1: Left edge x-coordinate.
        y1: Top edge y-coordinate.
        x2: Right edge x-coordinate.
        y2: Bottom edge y-coordinate.
        **kwargs: Additional keyword arguments passed to the ROI constructor.

    Returns:
        An ROI with a rectangular polygon geometry.

    Note:
        For detection bounding boxes, prefer ``BoundingBox.from_xywh()`` or
        ``BoundingBox.from_xyxy()`` which provide richer metadata support.

    .. deprecated::
        Use ``BoundingBox.from_xyxy()`` for detection bounding boxes.
    """
    import warnings

    warnings.warn(
        "ROI.from_xyxy() is deprecated. Use BoundingBox.from_xyxy() instead.",
        DeprecationWarning,
        stacklevel=2,
    )
    from shapely.geometry import box

    geom = box(x1, y1, x2, y2)
    return cls(geometry=geom, **kwargs)

to_bbox(padding=0.0, rotated=False, error_on_empty=False)

Reduce this ROI to a bounding box.

A PredictedROI produces a PredictedBoundingBox carrying its score; any other ROI produces a UserBoundingBox. Metadata (track, tracking_score, identity, identity_score, category, name, source, instance) is inherited.

Parameters:

Name Type Description Default
padding float | tuple[float, float]

Amount to inflate the box outward. Scalar applies to both axes; a (px, py) tuple applies per-axis. Negative values shrink the box. For rotated boxes, padding enlarges the pre-rotation extent about the center while preserving the angle.

0.0
rotated bool

If True, fit a minimum-area oriented box (rotated). If False, fit an axis-aligned box from the geometry bounds.

False
error_on_empty bool

If True, raise ValueError when the geometry is empty instead of returning a degenerate (NaN) box.

False

Returns:

Type Description
BoundingBox

A BoundingBox enclosing the geometry (or NaN corners if empty).

Raises:

Type Description
ValueError

If the geometry is empty and error_on_empty is True.

Source code in sleap_io/model/roi.py
def to_bbox(
    self,
    padding: float | tuple[float, float] = 0.0,
    rotated: bool = False,
    error_on_empty: bool = False,
) -> "BoundingBox":
    """Reduce this ROI to a bounding box.

    A `PredictedROI` produces a `PredictedBoundingBox` carrying its `score`;
    any other ROI produces a `UserBoundingBox`. Metadata (track,
    tracking_score, identity, identity_score, category, name, source,
    instance) is inherited.

    Args:
        padding: Amount to inflate the box outward. Scalar applies to both
            axes; a ``(px, py)`` tuple applies per-axis. Negative values
            shrink the box. For rotated boxes, padding enlarges the
            pre-rotation extent about the center while preserving the angle.
        rotated: If ``True``, fit a minimum-area oriented box (rotated). If
            ``False``, fit an axis-aligned box from the geometry bounds.
        error_on_empty: If ``True``, raise ``ValueError`` when the geometry is
            empty instead of returning a degenerate (NaN) box.

    Returns:
        A `BoundingBox` enclosing the geometry (or NaN corners if empty).

    Raises:
        ValueError: If the geometry is empty and ``error_on_empty`` is ``True``.
    """
    from sleap_io.model.bbox import PredictedBoundingBox, UserBoundingBox

    if self.geometry.is_empty:
        if error_on_empty:
            raise ValueError(
                "Cannot compute bounding box of an empty ROI geometry."
            )
        nan = float("nan")
        x1 = y1 = x2 = y2 = nan
        angle = 0.0
    else:
        x1, y1, x2, y2, angle = _geometry_to_bbox_coords(self.geometry, rotated)
        x1, y1, x2, y2 = _apply_padding(x1, y1, x2, y2, padding)

    kwargs = dict(
        x1=x1,
        y1=y1,
        x2=x2,
        y2=y2,
        angle=angle,
        track=self.track,
        tracking_score=self.tracking_score,
        identity=self.identity,
        identity_score=self.identity_score,
        identity_embedding=self.identity_embedding,
        instance=self.instance,
        category=self.category,
        category_score=self.category_score,
        category_embedding=self.category_embedding,
        name=self.name,
        source=self.source,
    )
    if self.is_predicted:
        return PredictedBoundingBox(score=self.score, **kwargs)
    return UserBoundingBox(**kwargs)

to_centroid(representative=False, error_on_empty=False)

Reduce this ROI to a single centroid point.

A PredictedROI produces a PredictedCentroid carrying its score; any other ROI produces a UserCentroid. Metadata (track, tracking_score, identity, identity_score, category, name, source, instance) is inherited.

Parameters:

Name Type Description Default
representative bool

If True, use Shapely's representative_point() (a point guaranteed to lie within the geometry); otherwise use the geometric centroid (which may fall outside concave shapes).

False
error_on_empty bool

If True, raise ValueError when the geometry is empty instead of returning a degenerate (NaN) centroid.

False

Returns:

Type Description
Centroid

A Centroid at the geometry's centroid (or NaN if empty).

Raises:

Type Description
ValueError

If the geometry is empty and error_on_empty is True.

Source code in sleap_io/model/roi.py
def to_centroid(
    self, representative: bool = False, error_on_empty: bool = False
) -> "Centroid":
    """Reduce this ROI to a single centroid point.

    A `PredictedROI` produces a `PredictedCentroid` carrying its `score`; any
    other ROI produces a `UserCentroid`. Metadata (track, tracking_score,
    identity, identity_score, category, name, source, instance) is inherited.

    Args:
        representative: If ``True``, use Shapely's ``representative_point()``
            (a point guaranteed to lie within the geometry); otherwise use the
            geometric ``centroid`` (which may fall outside concave shapes).
        error_on_empty: If ``True``, raise ``ValueError`` when the geometry is
            empty instead of returning a degenerate (NaN) centroid.

    Returns:
        A `Centroid` at the geometry's centroid (or NaN if empty).

    Raises:
        ValueError: If the geometry is empty and ``error_on_empty`` is ``True``.
    """
    from sleap_io.model.centroid import PredictedCentroid, UserCentroid

    if self.geometry.is_empty:
        if error_on_empty:
            raise ValueError("Cannot compute centroid of an empty ROI geometry.")
        x = y = float("nan")
    else:
        pt = (
            self.geometry.representative_point()
            if representative
            else self.geometry.centroid
        )
        x, y = float(pt.x), float(pt.y)

    kwargs = dict(
        x=x,
        y=y,
        track=self.track,
        tracking_score=self.tracking_score,
        identity=self.identity,
        identity_score=self.identity_score,
        identity_embedding=self.identity_embedding,
        instance=self.instance,
        category=self.category,
        category_score=self.category_score,
        category_embedding=self.category_embedding,
        name=self.name,
        source=self.source,
    )
    if self.is_predicted:
        return PredictedCentroid(score=self.score, **kwargs)
    return UserCentroid(**kwargs)

to_mask(height, width)

Rasterize this ROI into a binary segmentation mask.

A PredictedROI produces a PredictedSegmentationMask carrying its score; any other ROI produces a UserSegmentationMask. Metadata (name, category, source, track, instance) is inherited either way.

Parameters:

Name Type Description Default
height int

Height of the output mask in pixels.

required
width int

Width of the output mask in pixels.

required

Returns:

Type Description
SegmentationMask

A SegmentationMask with the rasterized geometry.

Source code in sleap_io/model/roi.py
def to_mask(self, height: int, width: int) -> "SegmentationMask":
    """Rasterize this ROI into a binary segmentation mask.

    A `PredictedROI` produces a `PredictedSegmentationMask` carrying its
    `score`; any other ROI produces a `UserSegmentationMask`. Metadata
    (name, category, source, track, instance) is inherited either way.

    Args:
        height: Height of the output mask in pixels.
        width: Width of the output mask in pixels.

    Returns:
        A `SegmentationMask` with the rasterized geometry.
    """
    from sleap_io.model.mask import (
        PredictedSegmentationMask,
        UserSegmentationMask,
    )

    # Rasterize geometry to binary mask
    mask = _rasterize_geometry(self.geometry, height, width)

    kwargs = dict(
        name=self.name,
        category=self.category,
        category_score=self.category_score,
        category_embedding=self.category_embedding,
        source=self.source,
        track=self.track,
        tracking_score=self.tracking_score,
        identity=self.identity,
        identity_score=self.identity_score,
        identity_embedding=self.identity_embedding,
        instance=self.instance,
    )
    if self.is_predicted:
        return PredictedSegmentationMask.from_numpy(
            mask, score=self.score, **kwargs
        )
    return UserSegmentationMask.from_numpy(mask, **kwargs)

UserROI

Bases: sleap_io.model.roi.ROI

Human-annotated region of interest.

Methods:

Name Description
__init__

Method generated by attrs for class UserROI.

__repr__

Method generated by attrs for class UserROI.

__setattr__

Method generated by attrs for class UserROI.

Attributes:

Name Type Description
__annotations__

dict() -> new empty dictionary

__attrs_own_setattr__

Returns True when the argument is true, False otherwise.

__attrs_props__

Effective class properties as derived from parameters to attr.s() or

__doc__

str(object='') -> str

__firstlineno__

int([x]) -> integer

__match_args__

Built-in immutable sequence.

__module__

str(object='') -> str

__slots__

Built-in immutable sequence.

__static_attributes__

Built-in immutable sequence.

Source code in sleap_io/model/roi.py
@attrs.define(eq=False)
class UserROI(ROI):
    """Human-annotated region of interest."""

    pass

__annotations__ = {} class-attribute

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

__attrs_own_setattr__ = True class-attribute

Returns True when the argument is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.

__attrs_props__ = ClassProps(is_exception=False, is_slotted=True, has_weakref_slot=True, is_frozen=False, kw_only=<KeywordOnly.NO: 'no'>, collected_fields_by_mro=True, added_init=True, added_repr=True, added_eq=False, added_ordering=False, hashability=<Hashability.LEAVE_ALONE: 'leave_alone'>, added_match_args=True, added_str=False, added_pickling=True, on_setattr_hook=<function pipe.<locals>.wrapped_pipe at 0x7f08471ce840>, field_transformer=None) class-attribute

Effective class properties as derived from parameters to attr.s() or define() decorators.

This is the same data structure that attrs uses internally to decide how to construct the final class.

Warning:

This feature is currently **experimental** and is not covered by our
strict backwards-compatibility guarantees.

Attributes:

Name Type Description
is_exception bool

Whether the class is treated as an exception class.

is_slotted bool

Whether the class is slotted <slotted classes>.

has_weakref_slot bool

Whether the class has a slot for weak references.

is_frozen bool

Whether the class is frozen.

kw_only KeywordOnly

Whether / how the class enforces keyword-only arguments on the __init__ method.

collected_fields_by_mro bool

Whether the class fields were collected by method resolution order. That is, correctly but unlike dataclasses.

added_init bool

Whether the class has an attrs-generated __init__ method.

added_repr bool

Whether the class has an attrs-generated __repr__ method.

added_eq bool

Whether the class has attrs-generated equality methods.

added_ordering bool

Whether the class has attrs-generated ordering methods.

hashability Hashability

How hashable <hashing> the class is.

added_match_args bool

Whether the class supports positional match <match> over its fields.

added_str bool

Whether the class has an attrs-generated __str__ method.

added_pickling bool

Whether the class has attrs-generated __getstate__ and __setstate__ methods for pickle.

on_setattr_hook Callable[[Any, Attribute[Any], Any], Any] | None

The class's __setattr__ hook.

field_transformer Callable[[Attribute[Any]], Attribute[Any]] | None

The class's field transformers <transform-fields>.

.. versionadded:: 25.4.0

__doc__ = 'Human-annotated region of interest.' class-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

__firstlineno__ = 783 class-attribute

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer iteral.

int('0b100', base=0) 4

__match_args__ = ('geometry', 'name', 'category', 'source', 'video', 'track', 'tracking_score', 'identity', 'identity_score', 'instance', 'identity_embedding', 'category_score', 'category_embedding') class-attribute

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

__module__ = 'sleap_io.model.roi' class-attribute

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

__slots__ = () class-attribute

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

__static_attributes__ = () class-attribute

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

__init__(geometry, name='', category=None, source='', video=None, track=None, tracking_score=None, identity=None, identity_score=None, instance=None, identity_embedding=None, category_score=None, category_embedding=None)

Method generated by attrs for class UserROI.

Source code in sleap_io/model/roi.py
import numpy as np

from sleap_io.model.category import to_category

if TYPE_CHECKING:
    from shapely.geometry import Polygon
    from shapely.geometry.base import BaseGeometry

    from sleap_io.model.bbox import BoundingBox
    from sleap_io.model.category import Category
    from sleap_io.model.centroid import Centroid
    from sleap_io.model.embedding import Embedding
    from sleap_io.model.identity import Identity
    from sleap_io.model.instance import Instance, Track
    from sleap_io.model.mask import SegmentationMask
    from sleap_io.model.video import Video


class AnnotationType(IntEnum):

__repr__()

Method generated by attrs for class UserROI.

Source code in sleap_io/model/roi.py
"""Data structures for region of interest (ROI) annotations.

ROIs represent vector geometry annotations such as polygons and arbitrary shapes.
They use Shapely geometries internally for spatial operations.

The `AnnotationType` enum is kept for backward compatibility with old file formats
but is no longer used as a field on `ROI` or `SegmentationMask`.
"""

from __future__ import annotations

from enum import IntEnum
from typing import TYPE_CHECKING

import attrs

__setattr__(name, val)

Method generated by attrs for class UserROI.

read_rois(filename)

Read ROIs from a GeoJSON file.

Accepts both a FeatureCollection and a single Feature as input. Features with null geometries are skipped.

Parameters:

Name Type Description Default
filename str | Path

Path to a .geojson file.

required

Returns:

Type Description
list[ROI]

A list of ROIs parsed from the file.

Source code in sleap_io/io/geojson.py
def read_rois(filename: str | Path) -> list[ROI]:
    """Read ROIs from a GeoJSON file.

    Accepts both a FeatureCollection and a single Feature as input. Features with
    null geometries are skipped.

    Args:
        filename: Path to a ``.geojson`` file.

    Returns:
        A list of ROIs parsed from the file.
    """
    with open(filename) as f:
        data = json.load(f)

    if data.get("type") == "FeatureCollection":
        features = data.get("features", [])
    elif data.get("type") == "Feature":
        features = [data]
    else:
        features = []

    rois = []
    for feature in features:
        geom = feature.get("geometry")
        if geom is None:
            continue
        rois.append(_feature_to_roi(feature))
    return rois

write_rois(rois, filename)

Write ROIs to a GeoJSON FeatureCollection file.

Parameters:

Name Type Description Default
rois list[ROI]

List of ROIs to write.

required
filename str | Path

Path to the output .geojson file.

required
Source code in sleap_io/io/geojson.py
def write_rois(rois: list[ROI], filename: str | Path) -> None:
    """Write ROIs to a GeoJSON FeatureCollection file.

    Args:
        rois: List of ROIs to write.
        filename: Path to the output ``.geojson`` file.
    """
    feature_collection = {
        "type": "FeatureCollection",
        "features": [_roi_to_feature(roi) for roi in rois],
    }
    with open(filename, "w") as f:
        json.dump(feature_collection, f, indent=2)