Centroids¶
Spatial annotations: Centroids · Boxes · ROIs · Segmentation. These types nest per-frame on
LabeledFrame— see Working with annotations in frames.
A Centroid represents a single point at the center of an object. Centroids
are the primary annotation type for object detection workflows where full
pose skeletons are not needed. Centroid is abstract — use UserCentroid or
PredictedCentroid.
Centroids support optional 3D coordinates (z), interconversion with
single-node Instance objects, and the same track/instance metadata as other annotation types.
Importing TrackMate detections
PredictedCentroid(source="trackmate") is the canonical representation for TrackMate (ImageJ/Fiji) point tracking results. Load spot exports directly with sio.load_trackmate or let sio.load_file auto-detect the format from the CSV header. See Formats → TrackMate for the full schema.
Direct construction¶
>>> import sleap_io as sio
>>> centroid = sio.UserCentroid(
... x=100.0, y=200.0,
... )
>>> print(centroid.xy)
(100.0, 200.0)
>>> print(centroid.yx)
(200.0, 100.0)
From a pose Instance¶
Create a centroid from an existing pose Instance with
Centroid.from_pose (equivalently
Instance.to_centroid):
>>> import numpy as np
>>> import sleap_io as sio
>>> skeleton = sio.Skeleton(["head", "thorax", "abdomen"])
>>> inst = sio.Instance.from_numpy(
... np.array([[10, 20], [30, 40], [50, 60]]),
... skeleton=skeleton,
... )
>>> centroid = sio.UserCentroid.from_pose(inst)
>>> print(centroid.xy)
(30.0, 40.0)
>>> print(centroid.source) # records the method used
center_of_mass
The method parameter controls how the center point is computed:
| Method | Behavior | source tag |
|---|---|---|
"center_of_mass" |
NaN-ignoring (unweighted) mean of visible points (default) | "center_of_mass" |
"bbox_center" |
Center of the bounding box of visible points | "bbox_center" |
"geometric_median" |
Weiszfeld geometric median of visible points (outlier-robust) | "geometric_median" |
"anchor" |
Coordinates of a specific node (requires node) |
"anchor:<node>" |
For method="anchor", pass node (a node name or index). If the anchor node is
occluded, supply a fallback method (one of the non-anchor methods) to compute
the centroid from the visible points instead; the source tag then records the
chain, e.g. "anchor:nose->center_of_mass":
>>> import numpy as np
>>> import sleap_io as sio
>>> skeleton = sio.Skeleton(["head", "thorax", "abdomen"])
>>> inst = sio.Instance.from_numpy(
... np.array([[10, 20], [30, 40], [50, 60]]),
... skeleton=skeleton,
... )
>>> anchor_c = sio.UserCentroid.from_pose(inst, method="anchor", node="head")
>>> print(anchor_c.xy)
(10.0, 20.0)
>>> print(anchor_c.source)
anchor:head
When there are no visible points (or an occluded anchor with no fallback), the
result is a degenerate centroid (x = y = nan); pass error_on_empty=True to
raise a ValueError instead. The is_empty property reports this cheaply:
>>> import sleap_io as sio
>>> print(sio.UserCentroid(x=float("nan"), y=float("nan")).is_empty)
True
Renamed from from_instance
Centroid.from_instance() was renamed to Centroid.from_pose() (the pose
modality is named pose everywhere, even though the backing class is
Instance). from_instance() is kept as a deprecated alias that forwards to
from_pose() and emits a DeprecationWarning.
Converting back to a pose Instance¶
A centroid can be converted to a single-node Instance with
Centroid.to_pose for interoperability with
pose-based workflows:
>>> import sleap_io as sio
>>> centroid = sio.UserCentroid(x=30.0, y=40.0)
>>> inst = centroid.to_pose()
>>> print(inst.numpy())
[[30. 40.]]
Renamed from to_instance
Centroid.to_instance() was renamed to Centroid.to_pose().
to_instance() is kept as a deprecated alias that forwards to to_pose()
and emits a DeprecationWarning.
Constructing boxes, ROIs, and masks¶
A centroid is a single point, so it can seed a fixed-size
BoundingBox, a circular ROI, or a rasterized
SegmentationMask around itself. These complete the
conversion matrix for the
centroid modality:
>>> import sleap_io as sio
>>> centroid = sio.UserCentroid(x=30.0, y=40.0)
>>> box = centroid.to_bbox(size=20) # 20x20 box centered on the point
>>> print(box.xyxy)
(20.0, 30.0, 40.0, 50.0)
>>> roi = centroid.to_roi(radius=5) # disc of radius 5
>>> print(round(roi.area, 2))
78.41
>>> mask = centroid.to_mask(100, 100, radius=5) # rasterized disc
>>> print(mask.area)
88
to_bbox requires size (a scalar for a square box or (w, h)) and accepts
padding. to_roi and to_mask require radius. A PredictedCentroid
produces predicted outputs carrying its score. A degenerate (NaN) centroid
yields an empty target (NaN box / empty-Polygon ROI / all-background mask)
unless error_on_empty=True.
User vs. predicted centroids¶
UserCentroid and PredictedCentroid distinguish human annotations from
model predictions. PredictedCentroid adds a score field for confidence:
>>> import sleap_io as sio
>>> user_c = sio.UserCentroid(x=10, y=20)
>>> print(user_c.is_predicted)
False
>>> pred_c = sio.PredictedCentroid(x=10, y=20, score=0.95)
>>> print(pred_c.score)
0.95
>>> print(pred_c.is_predicted)
True
When using from_pose(), the return type matches the input:
PredictedInstance produces PredictedCentroid, Instance produces
UserCentroid.
Metadata fields¶
Every centroid can carry optional metadata:
| Field | Type | Description |
|---|---|---|
track |
Track \| None |
Tracking identity across frames |
tracking_score |
float \| None |
Confidence of track identity assignment |
identity |
Identity \| None |
Global cross-video re-ID identity (mirrors Instance.identity); persists via /identity_links (owner_type=2) |
identity_score |
float \| None |
Confidence of the identity assignment |
instance |
Instance \| None |
Linked pose instance |
z |
float \| None |
Optional Z-coordinate for 3D data |
category |
str |
Class label (e.g., "cell") |
name |
str |
Human-readable name |
source |
str |
How the centroid was computed (e.g., "center_of_mass") |
Rendering
Centroids compose with pose rendering in sio.render_image / sio.render_video and are listed in Rendering → Segmentation Overlays. For standalone canvases, pair sio.draw_bboxes with Centroid.to_pose() or use the pose drawing helpers directly.
See also
- Boxes, ROIs, Segmentation — the other spatial annotation types.
- Labels & Frames: Accessing centroids via
labels.centroidsand filtered queries withget_centroids(). - Formats: TrackMate: Importing point-tracking detections as
PredictedCentroid. - Converting between annotation types:
centroid.to_pose(),centroid.to_bbox(),centroid.to_roi(),centroid.to_mask(), and the full modality matrix.
API reference¶
sleap_io.Centroid
¶
A point representing the center of an object.
Supports optional 3D coordinates, track/instance metadata,
and interconversion with single-node Instance objects.
Attributes:
| Name | Type | Description |
|---|---|---|
x |
X-coordinate in pixel space. |
|
y |
Y-coordinate in pixel space. |
|
z |
Optional Z-coordinate for 3D data. |
|
track |
Optional tracking identity. |
|
tracking_score |
Confidence of the track identity assignment. |
|
identity |
Optional global, ground-truth |
|
identity_score |
Score associated with the |
|
instance |
Optional linked pose instance. |
|
category |
Optional |
|
name |
Human-readable name (e.g., |
|
source |
How the centroid was computed (e.g., |
|
identity_embedding |
Optional |
|
category_score |
Score associated with the |
|
category_embedding |
Optional |
Notes
Centroids use identity-based equality (two Centroid objects are only equal if they are the same object in memory).
This class is abstract. Use UserCentroid or PredictedCentroid
instead.
Methods:
| Name | Description |
|---|---|
__attrs_post_init__ |
Validate that this class is not instantiated directly. |
__init__ |
Method generated by attrs for class Centroid. |
__repr__ |
Method generated by attrs for class Centroid. |
__setattr__ |
Method generated by attrs for class Centroid. |
from_instance |
Create a centroid from an |
from_pose |
Create a centroid from a pose |
to_bbox |
Construct a fixed-size bounding box centered on this centroid. |
to_instance |
Convert this centroid to a single-node |
to_mask |
Rasterize a circular ROI around this centroid into a mask. |
to_pose |
Convert this centroid to a single-node |
to_roi |
Construct a circular ROI centered on this centroid. |
Source code in sleap_io/model/centroid.py
@attrs.define(eq=False)
class Centroid:
"""A point representing the center of an object.
Supports optional 3D coordinates, track/instance metadata,
and interconversion with single-node ``Instance`` objects.
Attributes:
x: X-coordinate in pixel space.
y: Y-coordinate in pixel space.
z: Optional Z-coordinate for 3D data. ``None`` for 2D.
track: Optional tracking identity.
tracking_score: Confidence of the track identity assignment. ``None``
if unassigned or manually assigned.
identity: Optional global, ground-truth `Identity` for this centroid -- 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 linked pose instance.
category: Optional `Category` (class label, e.g. ``"lysosome"``,
``"cell"``) for this centroid. Promoted from the legacy free-form
string; ``None`` if unset. Mirrors `Instance.category`.
name: Human-readable name (e.g., ``"ID43008"``).
source: How the centroid was computed (e.g., ``"center_of_mass"``,
``"trackmate"``).
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:
Centroids use identity-based equality (two Centroid objects are only
equal if they are the same object in memory).
This class is abstract. Use ``UserCentroid`` or ``PredictedCentroid``
instead.
"""
x: float = attrs.field()
y: float = attrs.field()
z: float | 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)
category: "Category | None" = attrs.field(default=None, converter=to_category)
name: str = attrs.field(default="")
source: str = attrs.field(default="")
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.
_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 Centroid:
raise TypeError(
"Centroid is abstract. Use UserCentroid or PredictedCentroid."
)
@property
def xy(self) -> tuple[float, float]:
"""Return coordinates as ``(x, y)``."""
return (self.x, self.y)
@property
def yx(self) -> tuple[float, float]:
"""Return coordinates as ``(y, x)`` (row, col order)."""
return (self.y, self.x)
@property
def xyz(self) -> tuple[float, float, float | None]:
"""Return coordinates as ``(x, y, z)``."""
return (self.x, self.y, self.z)
@property
def is_predicted(self) -> bool:
"""Return ``True`` if this is a ``PredictedCentroid``."""
return isinstance(self, PredictedCentroid)
@property
def is_empty(self) -> bool:
"""Whether this centroid is degenerate (NaN ``x`` or ``y``)."""
return bool(np.isnan(self.x) or np.isnan(self.y))
def to_pose(
self, skeleton: "Skeleton | None" = None
) -> "Instance | PredictedInstance":
"""Convert this centroid to a single-node ``Instance``.
Args:
skeleton: Skeleton to use for the instance. Must have exactly one
node. Defaults to the shared ``CENTROID_SKELETON``.
Returns:
A ``PredictedInstance`` if this is a ``PredictedCentroid``,
otherwise an ``Instance``.
Raises:
ValueError: If the skeleton has more than one node.
"""
from sleap_io.model.instance import Instance, PredictedInstance
if skeleton is None:
skeleton = get_centroid_skeleton()
if len(skeleton) > 1:
raise ValueError(
f"Skeleton must have exactly 1 node for centroid conversion, "
f"got {len(skeleton)}."
)
points = np.array([[self.x, self.y]])
if isinstance(self, PredictedCentroid):
return PredictedInstance.from_numpy(
points_data=points,
skeleton=skeleton,
score=self.score,
track=self.track,
tracking_score=self.tracking_score,
identity=self.identity,
identity_score=self.identity_score,
identity_embedding=self.identity_embedding,
category=self.category,
category_score=self.category_score,
category_embedding=self.category_embedding,
)
else:
return Instance.from_numpy(
points_data=points,
skeleton=skeleton,
track=self.track,
tracking_score=self.tracking_score,
identity=self.identity,
identity_score=self.identity_score,
identity_embedding=self.identity_embedding,
category=self.category,
category_score=self.category_score,
category_embedding=self.category_embedding,
)
def to_instance(
self, skeleton: "Skeleton | None" = None
) -> "Instance | PredictedInstance":
"""Convert this centroid to a single-node ``Instance`` (deprecated).
.. deprecated::
Use :meth:`to_pose` instead.
Args:
skeleton: Skeleton to use for the instance. Must have exactly one
node. Defaults to the shared ``CENTROID_SKELETON``.
Returns:
A ``PredictedInstance`` if this is a ``PredictedCentroid``,
otherwise an ``Instance``.
"""
import warnings
warnings.warn(
"Centroid.to_instance() is deprecated; use Centroid.to_pose() instead.",
DeprecationWarning,
stacklevel=2,
)
return self.to_pose(skeleton=skeleton)
@classmethod
def from_pose(
cls,
instance: "Instance",
method: str = "center_of_mass",
node: "str | int | None" = None,
fallback: "str | None" = None,
error_on_empty: bool = False,
**kwargs,
) -> "Centroid":
"""Create a centroid from a pose ``Instance``.
Args:
instance: The source instance.
method: Computation method:
- ``"center_of_mass"``: NaN-ignoring unweighted mean of visible
node coordinates.
- ``"bbox_center"``: Center of the bounding box of visible points.
- ``"geometric_median"``: Weiszfeld geometric median of visible
points (robust to outliers).
- ``"anchor"``: Coordinates of a specific node (requires ``node``).
node: Node specification for the ``"anchor"`` method. Can be a node
name (str) or index (int). Required for ``"anchor"``.
fallback: For the ``"anchor"`` method, a non-anchor method
(``"center_of_mass"``, ``"bbox_center"``, or
``"geometric_median"``) to fall back to when the anchor node is
occluded. If ``None``, an occluded anchor yields a degenerate
centroid (or raises when ``error_on_empty`` is ``True``).
error_on_empty: If ``True``, raise ``ValueError`` when there are no
visible points to compute the requested centroid instead of
returning a degenerate (NaN) centroid.
**kwargs: Additional keyword arguments passed to the centroid
constructor (e.g., ``video``, ``frame_idx``, ``category``).
Returns:
A ``PredictedCentroid`` if the instance is a ``PredictedInstance``,
otherwise a ``UserCentroid``. The ``source`` attribute records the
computation method (e.g. ``"center_of_mass"``, ``"anchor:nose"``, or
``"anchor:nose->center_of_mass"`` when a fallback was used).
Raises:
ValueError: For an unknown ``method``, a missing ``node`` for the
``"anchor"`` method, an invalid ``node`` type, or (when
``error_on_empty`` is ``True``) when there are no visible points.
"""
from sleap_io.model.instance import PredictedInstance
pts = instance.numpy(invisible_as_nan=True)
visible = ~np.isnan(pts[:, 0])
nan = float("nan")
def _compute(reduce_method: str) -> tuple[float, float]:
"""Compute a non-anchor centroid; returns NaN if no visible points."""
if reduce_method == "center_of_mass":
if not visible.any():
return nan, nan
return (
float(pts[visible, 0].mean()),
float(pts[visible, 1].mean()),
)
elif reduce_method == "bbox_center":
if not visible.any():
return nan, nan
return (
float((pts[visible, 0].min() + pts[visible, 0].max()) / 2),
float((pts[visible, 1].min() + pts[visible, 1].max()) / 2),
)
elif reduce_method == "geometric_median":
if not visible.any():
return nan, nan
return _geometric_median(pts[visible])
else:
raise ValueError(
f"Unknown method {reduce_method!r}. Expected 'center_of_mass', "
f"'bbox_center', 'geometric_median', or 'anchor'."
)
if method == "anchor":
if node is None:
raise ValueError("Must specify 'node' for anchor method.")
if isinstance(node, str):
node_idx = instance.skeleton.index(node)
elif isinstance(node, (int, np.integer)):
node_idx = int(node)
else:
raise ValueError(f"node must be str or int, got {type(node).__name__}")
if not np.isnan(pts[node_idx, 0]):
x = float(pts[node_idx, 0])
y = float(pts[node_idx, 1])
source = f"anchor:{node}"
elif fallback is not None:
x, y = _compute(fallback)
source = f"anchor:{node}->{fallback}"
else:
x = y = nan
source = f"anchor:{node}"
elif method in ("center_of_mass", "bbox_center", "geometric_median"):
x, y = _compute(method)
source = method
else:
raise ValueError(
f"Unknown method {method!r}. Expected 'center_of_mass', "
f"'bbox_center', 'geometric_median', or 'anchor'."
)
if (np.isnan(x) or np.isnan(y)) and error_on_empty:
raise ValueError(
f"No visible points to compute centroid (method={method!r})."
)
# Build constructor kwargs.
centroid_kwargs = dict(
x=x,
y=y,
track=instance.track,
tracking_score=instance.tracking_score,
identity=instance.identity,
identity_score=instance.identity_score,
identity_embedding=instance.identity_embedding,
category=instance.category,
category_score=instance.category_score,
category_embedding=instance.category_embedding,
instance=instance,
source=source,
)
centroid_kwargs.update(kwargs)
if isinstance(instance, PredictedInstance):
return PredictedCentroid(score=instance.score, **centroid_kwargs)
else:
return UserCentroid(**centroid_kwargs)
@classmethod
def from_instance(
cls,
instance: "Instance",
method: str = "center_of_mass",
node: "str | int | None" = None,
fallback: "str | None" = None,
error_on_empty: bool = False,
**kwargs,
) -> "Centroid":
"""Create a centroid from an ``Instance`` (deprecated).
.. deprecated::
Use :meth:`from_pose` instead.
Args:
instance: The source instance.
method: Computation method (see :meth:`from_pose`).
node: Node specification for the ``"anchor"`` method.
fallback: Fallback method for an occluded anchor.
error_on_empty: Whether to raise instead of returning a degenerate
centroid.
**kwargs: Additional keyword arguments passed to the constructor.
Returns:
A ``PredictedCentroid`` or ``UserCentroid`` (see :meth:`from_pose`).
"""
import warnings
warnings.warn(
"Centroid.from_instance() is deprecated; use Centroid.from_pose() instead.",
DeprecationWarning,
stacklevel=2,
)
return cls.from_pose(
instance,
method=method,
node=node,
fallback=fallback,
error_on_empty=error_on_empty,
**kwargs,
)
def to_bbox(
self,
size: float | tuple[float, float],
padding: float | tuple[float, float] = 0.0,
error_on_empty: bool = False,
) -> "BoundingBox":
"""Construct a fixed-size bounding box centered on this centroid.
A ``PredictedCentroid`` produces a ``PredictedBoundingBox`` carrying its
``score``; any other centroid produces a ``UserBoundingBox``. Metadata
(track, tracking_score, identity, identity_score, category, name, source,
instance) is inherited.
Args:
size: Box size centered on the centroid. A scalar yields a square box
of that side length; a ``(w, h)`` tuple sets width and height
independently. Required.
padding: Amount to inflate the box outward after sizing. Scalar
applies to both axes; a ``(px, py)`` tuple applies per-axis.
Negative values shrink the box.
error_on_empty: If ``True``, raise ``ValueError`` when this centroid
is degenerate (NaN) instead of returning a degenerate box.
Returns:
A ``BoundingBox`` centered on the centroid (or NaN corners if empty).
Raises:
ValueError: If ``size`` is ``None``, or if the centroid is degenerate
and ``error_on_empty`` is ``True``.
"""
if size is None:
raise ValueError("'size' is required for Centroid.to_bbox().")
from sleap_io.model.bbox import PredictedBoundingBox, UserBoundingBox
from sleap_io.model.roi import _apply_padding
if self.is_empty:
if error_on_empty:
raise ValueError(
"Cannot compute bounding box of a degenerate (NaN) centroid."
)
nan = float("nan")
x1 = y1 = x2 = y2 = nan
else:
if isinstance(size, (tuple, list)):
w, h = size
else:
w = h = size
x1 = self.x - w / 2
y1 = self.y - h / 2
x2 = self.x + w / 2
y2 = self.y + h / 2
x1, y1, x2, y2 = _apply_padding(x1, y1, x2, y2, padding)
kwargs = dict(
x1=x1,
y1=y1,
x2=x2,
y2=y2,
angle=0.0,
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 to_roi(self, radius: float, error_on_empty: bool = False) -> "ROI":
"""Construct a circular ROI centered on this centroid.
A ``PredictedCentroid`` produces a ``PredictedROI`` carrying its
``score``; any other centroid produces a ``UserROI``. Metadata (track,
tracking_score, identity, identity_score, category, name, source,
instance) is inherited.
Args:
radius: Radius of the circular ROI. Required.
error_on_empty: If ``True``, raise ``ValueError`` when this centroid
is degenerate (NaN) instead of returning an empty-geometry ROI.
Returns:
A ``ROI`` with a buffered-point (circular) geometry, or an empty
``Polygon`` geometry if the centroid is degenerate.
Raises:
ValueError: If the centroid is degenerate and ``error_on_empty`` is
``True``.
"""
from shapely.geometry import Point, Polygon
from sleap_io.model.roi import PredictedROI, UserROI
if self.is_empty:
if error_on_empty:
raise ValueError("Cannot compute ROI of a degenerate (NaN) centroid.")
geom = Polygon()
else:
geom = Point(self.x, self.y).buffer(radius)
kwargs = dict(
geometry=geom,
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 PredictedROI(score=self.score, **kwargs)
return UserROI(**kwargs)
def to_mask(
self,
height: int,
width: int,
radius: float,
error_on_empty: bool = False,
) -> "SegmentationMask":
"""Rasterize a circular ROI around this centroid into a mask.
Equivalent to ``self.to_roi(radius).to_mask(height, width)``. A
``PredictedCentroid`` produces a ``PredictedSegmentationMask`` carrying
its ``score``; any other centroid produces a ``UserSegmentationMask``.
Metadata is inherited.
Args:
height: Height of the output mask in pixels.
width: Width of the output mask in pixels.
radius: Radius of the circular region around the centroid. Required.
error_on_empty: If ``True``, raise ``ValueError`` when this centroid
is degenerate (NaN) instead of returning an all-background mask.
Returns:
A ``SegmentationMask`` with the rasterized circular region (all
background if the centroid is degenerate).
Raises:
ValueError: If the centroid is degenerate and ``error_on_empty`` is
``True``.
"""
if self.is_empty:
if error_on_empty:
raise ValueError("Cannot compute mask of a degenerate (NaN) centroid.")
from sleap_io.model.mask import (
PredictedSegmentationMask,
UserSegmentationMask,
)
empty = np.zeros((height, width), dtype=bool)
kwargs = dict(
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 PredictedSegmentationMask.from_numpy(
empty, score=self.score, **kwargs
)
return UserSegmentationMask.from_numpy(empty, **kwargs)
return self.to_roi(radius).to_mask(height, width)
__annotations__ = {'x': 'float', 'y': 'float', 'z': 'float | None', 'track': "'Track | None'", 'tracking_score': 'float | None', 'identity': "'Identity | None'", 'identity_score': 'float | None', 'instance': "'Instance | None'", 'category': "'Category | None'", 'name': 'str', 'source': 'str', '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 |
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
|
collected_fields_by_mro |
bool
|
Whether the class fields were collected by method resolution order.
That is, correctly but unlike |
added_init |
bool
|
Whether the class has an attrs-generated |
added_repr |
bool
|
Whether the class has an attrs-generated |
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 |
added_match_args |
bool
|
Whether the class supports positional |
added_str |
bool
|
Whether the class has an attrs-generated |
added_pickling |
bool
|
Whether the class has attrs-generated |
on_setattr_hook |
Callable[[Any, Attribute[Any], Any], Any] | None
|
The class's |
field_transformer |
Callable[[Attribute[Any]], Attribute[Any]] | None
|
The class's |
.. versionadded:: 25.4.0
__doc__ = 'A point representing the center of an object.\n\nSupports optional 3D coordinates, track/instance metadata,\nand interconversion with single-node ``Instance`` objects.\n\nAttributes:\n x: X-coordinate in pixel space.\n y: Y-coordinate in pixel space.\n z: Optional Z-coordinate for 3D data. ``None`` for 2D.\n track: Optional tracking identity.\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 centroid -- 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 linked pose instance.\n category: Optional `Category` (class label, e.g. ``"lysosome"``,\n ``"cell"``) for this centroid. Promoted from the legacy free-form\n string; ``None`` if unset. Mirrors `Instance.category`.\n name: Human-readable name (e.g., ``"ID43008"``).\n source: How the centroid was computed (e.g., ``"center_of_mass"``,\n ``"trackmate"``).\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 Centroids use identity-based equality (two Centroid objects are only\n equal if they are the same object in memory).\n\n This class is abstract. Use ``UserCentroid`` or ``PredictedCentroid``\n instead.\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__ = 101
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__ = ('x', 'y', 'z', 'track', 'tracking_score', 'identity', 'identity_score', 'instance', 'category', 'name', 'source', '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.centroid'
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__ = ('x', 'y', 'z', 'track', 'tracking_score', 'identity', 'identity_score', 'instance', 'category', 'name', 'source', '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
is_empty
property
¶
Whether this centroid is degenerate (NaN x or y).
is_predicted
property
¶
Return True if this is a PredictedCentroid.
xy
property
¶
Return coordinates as (x, y).
xyz
property
¶
Return coordinates as (x, y, z).
yx
property
¶
Return coordinates as (y, x) (row, col order).
__attrs_post_init__()
¶
__init__(x, y, z=None, track=None, tracking_score=None, identity=None, identity_score=None, instance=None, category=None, name='', source='', identity_embedding=None, category_score=None, category_embedding=None)
¶
Method generated by attrs for class Centroid.
Source code in sleap_io/model/centroid.py
from __future__ import annotations
from typing import TYPE_CHECKING
import attrs
import numpy as np
from sleap_io.model.category import to_category
if TYPE_CHECKING:
from sleap_io.model.bbox import BoundingBox
from sleap_io.model.category import Category
from sleap_io.model.embedding import Embedding
from sleap_io.model.identity import Identity
from sleap_io.model.instance import Instance, PredictedInstance, Track
from sleap_io.model.mask import SegmentationMask
from sleap_io.model.roi import ROI
from sleap_io.model.skeleton import Skeleton
__repr__()
¶
Method generated by attrs for class Centroid.
Source code in sleap_io/model/centroid.py
"""Data structures for centroid annotations.
Centroids are lightweight point annotations representing the center of an object.
They support user/predicted distinction and interconversion with single-node
``Instance`` objects.
The class hierarchy:
- ``Centroid`` — abstract base with coordinates, video/frame/track/instance metadata
- ``UserCentroid`` — human-annotated or derived centroid
- ``PredictedCentroid`` — model-predicted centroid with confidence score
A module-level ``CENTROID_SKELETON`` is provided for creating single-node
``Instance`` objects from centroids.
"""
__setattr__(name, val)
¶
Method generated by attrs for class Centroid.
from_instance(instance, method='center_of_mass', node=None, fallback=None, error_on_empty=False, **kwargs)
classmethod
¶
Create a centroid from an Instance (deprecated).
.. deprecated::
Use :meth:from_pose instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instance
|
Instance
|
The source instance. |
required |
method
|
str
|
Computation method (see :meth: |
'center_of_mass'
|
node
|
str | int | None
|
Node specification for the |
None
|
fallback
|
str | None
|
Fallback method for an occluded anchor. |
None
|
error_on_empty
|
bool
|
Whether to raise instead of returning a degenerate centroid. |
False
|
**kwargs
|
Additional keyword arguments passed to the constructor. |
required |
Returns:
| Type | Description |
|---|---|
Centroid
|
A |
Source code in sleap_io/model/centroid.py
@classmethod
def from_instance(
cls,
instance: "Instance",
method: str = "center_of_mass",
node: "str | int | None" = None,
fallback: "str | None" = None,
error_on_empty: bool = False,
**kwargs,
) -> "Centroid":
"""Create a centroid from an ``Instance`` (deprecated).
.. deprecated::
Use :meth:`from_pose` instead.
Args:
instance: The source instance.
method: Computation method (see :meth:`from_pose`).
node: Node specification for the ``"anchor"`` method.
fallback: Fallback method for an occluded anchor.
error_on_empty: Whether to raise instead of returning a degenerate
centroid.
**kwargs: Additional keyword arguments passed to the constructor.
Returns:
A ``PredictedCentroid`` or ``UserCentroid`` (see :meth:`from_pose`).
"""
import warnings
warnings.warn(
"Centroid.from_instance() is deprecated; use Centroid.from_pose() instead.",
DeprecationWarning,
stacklevel=2,
)
return cls.from_pose(
instance,
method=method,
node=node,
fallback=fallback,
error_on_empty=error_on_empty,
**kwargs,
)
from_pose(instance, method='center_of_mass', node=None, fallback=None, error_on_empty=False, **kwargs)
classmethod
¶
Create a centroid from a pose Instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instance
|
Instance
|
The source instance. |
required |
method
|
str
|
Computation method:
- |
'center_of_mass'
|
node
|
str | int | None
|
Node specification for the |
None
|
fallback
|
str | None
|
For the |
None
|
error_on_empty
|
bool
|
If |
False
|
**kwargs
|
Additional keyword arguments passed to the centroid
constructor (e.g., |
required |
Returns:
| Type | Description |
|---|---|
Centroid
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
For an unknown |
Source code in sleap_io/model/centroid.py
@classmethod
def from_pose(
cls,
instance: "Instance",
method: str = "center_of_mass",
node: "str | int | None" = None,
fallback: "str | None" = None,
error_on_empty: bool = False,
**kwargs,
) -> "Centroid":
"""Create a centroid from a pose ``Instance``.
Args:
instance: The source instance.
method: Computation method:
- ``"center_of_mass"``: NaN-ignoring unweighted mean of visible
node coordinates.
- ``"bbox_center"``: Center of the bounding box of visible points.
- ``"geometric_median"``: Weiszfeld geometric median of visible
points (robust to outliers).
- ``"anchor"``: Coordinates of a specific node (requires ``node``).
node: Node specification for the ``"anchor"`` method. Can be a node
name (str) or index (int). Required for ``"anchor"``.
fallback: For the ``"anchor"`` method, a non-anchor method
(``"center_of_mass"``, ``"bbox_center"``, or
``"geometric_median"``) to fall back to when the anchor node is
occluded. If ``None``, an occluded anchor yields a degenerate
centroid (or raises when ``error_on_empty`` is ``True``).
error_on_empty: If ``True``, raise ``ValueError`` when there are no
visible points to compute the requested centroid instead of
returning a degenerate (NaN) centroid.
**kwargs: Additional keyword arguments passed to the centroid
constructor (e.g., ``video``, ``frame_idx``, ``category``).
Returns:
A ``PredictedCentroid`` if the instance is a ``PredictedInstance``,
otherwise a ``UserCentroid``. The ``source`` attribute records the
computation method (e.g. ``"center_of_mass"``, ``"anchor:nose"``, or
``"anchor:nose->center_of_mass"`` when a fallback was used).
Raises:
ValueError: For an unknown ``method``, a missing ``node`` for the
``"anchor"`` method, an invalid ``node`` type, or (when
``error_on_empty`` is ``True``) when there are no visible points.
"""
from sleap_io.model.instance import PredictedInstance
pts = instance.numpy(invisible_as_nan=True)
visible = ~np.isnan(pts[:, 0])
nan = float("nan")
def _compute(reduce_method: str) -> tuple[float, float]:
"""Compute a non-anchor centroid; returns NaN if no visible points."""
if reduce_method == "center_of_mass":
if not visible.any():
return nan, nan
return (
float(pts[visible, 0].mean()),
float(pts[visible, 1].mean()),
)
elif reduce_method == "bbox_center":
if not visible.any():
return nan, nan
return (
float((pts[visible, 0].min() + pts[visible, 0].max()) / 2),
float((pts[visible, 1].min() + pts[visible, 1].max()) / 2),
)
elif reduce_method == "geometric_median":
if not visible.any():
return nan, nan
return _geometric_median(pts[visible])
else:
raise ValueError(
f"Unknown method {reduce_method!r}. Expected 'center_of_mass', "
f"'bbox_center', 'geometric_median', or 'anchor'."
)
if method == "anchor":
if node is None:
raise ValueError("Must specify 'node' for anchor method.")
if isinstance(node, str):
node_idx = instance.skeleton.index(node)
elif isinstance(node, (int, np.integer)):
node_idx = int(node)
else:
raise ValueError(f"node must be str or int, got {type(node).__name__}")
if not np.isnan(pts[node_idx, 0]):
x = float(pts[node_idx, 0])
y = float(pts[node_idx, 1])
source = f"anchor:{node}"
elif fallback is not None:
x, y = _compute(fallback)
source = f"anchor:{node}->{fallback}"
else:
x = y = nan
source = f"anchor:{node}"
elif method in ("center_of_mass", "bbox_center", "geometric_median"):
x, y = _compute(method)
source = method
else:
raise ValueError(
f"Unknown method {method!r}. Expected 'center_of_mass', "
f"'bbox_center', 'geometric_median', or 'anchor'."
)
if (np.isnan(x) or np.isnan(y)) and error_on_empty:
raise ValueError(
f"No visible points to compute centroid (method={method!r})."
)
# Build constructor kwargs.
centroid_kwargs = dict(
x=x,
y=y,
track=instance.track,
tracking_score=instance.tracking_score,
identity=instance.identity,
identity_score=instance.identity_score,
identity_embedding=instance.identity_embedding,
category=instance.category,
category_score=instance.category_score,
category_embedding=instance.category_embedding,
instance=instance,
source=source,
)
centroid_kwargs.update(kwargs)
if isinstance(instance, PredictedInstance):
return PredictedCentroid(score=instance.score, **centroid_kwargs)
else:
return UserCentroid(**centroid_kwargs)
to_bbox(size, padding=0.0, error_on_empty=False)
¶
Construct a fixed-size bounding box centered on this centroid.
A PredictedCentroid produces a PredictedBoundingBox carrying its
score; any other centroid produces a UserBoundingBox. Metadata
(track, tracking_score, identity, identity_score, category, name, source,
instance) is inherited.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
float | tuple[float, float]
|
Box size centered on the centroid. A scalar yields a square box
of that side length; a |
required |
padding
|
float | tuple[float, float]
|
Amount to inflate the box outward after sizing. Scalar
applies to both axes; a |
0.0
|
error_on_empty
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
BoundingBox
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in sleap_io/model/centroid.py
def to_bbox(
self,
size: float | tuple[float, float],
padding: float | tuple[float, float] = 0.0,
error_on_empty: bool = False,
) -> "BoundingBox":
"""Construct a fixed-size bounding box centered on this centroid.
A ``PredictedCentroid`` produces a ``PredictedBoundingBox`` carrying its
``score``; any other centroid produces a ``UserBoundingBox``. Metadata
(track, tracking_score, identity, identity_score, category, name, source,
instance) is inherited.
Args:
size: Box size centered on the centroid. A scalar yields a square box
of that side length; a ``(w, h)`` tuple sets width and height
independently. Required.
padding: Amount to inflate the box outward after sizing. Scalar
applies to both axes; a ``(px, py)`` tuple applies per-axis.
Negative values shrink the box.
error_on_empty: If ``True``, raise ``ValueError`` when this centroid
is degenerate (NaN) instead of returning a degenerate box.
Returns:
A ``BoundingBox`` centered on the centroid (or NaN corners if empty).
Raises:
ValueError: If ``size`` is ``None``, or if the centroid is degenerate
and ``error_on_empty`` is ``True``.
"""
if size is None:
raise ValueError("'size' is required for Centroid.to_bbox().")
from sleap_io.model.bbox import PredictedBoundingBox, UserBoundingBox
from sleap_io.model.roi import _apply_padding
if self.is_empty:
if error_on_empty:
raise ValueError(
"Cannot compute bounding box of a degenerate (NaN) centroid."
)
nan = float("nan")
x1 = y1 = x2 = y2 = nan
else:
if isinstance(size, (tuple, list)):
w, h = size
else:
w = h = size
x1 = self.x - w / 2
y1 = self.y - h / 2
x2 = self.x + w / 2
y2 = self.y + h / 2
x1, y1, x2, y2 = _apply_padding(x1, y1, x2, y2, padding)
kwargs = dict(
x1=x1,
y1=y1,
x2=x2,
y2=y2,
angle=0.0,
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_instance(skeleton=None)
¶
Convert this centroid to a single-node Instance (deprecated).
.. deprecated::
Use :meth:to_pose instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
skeleton
|
Skeleton | None
|
Skeleton to use for the instance. Must have exactly one
node. Defaults to the shared |
None
|
Returns:
| Type | Description |
|---|---|
Instance | PredictedInstance
|
A |
Source code in sleap_io/model/centroid.py
def to_instance(
self, skeleton: "Skeleton | None" = None
) -> "Instance | PredictedInstance":
"""Convert this centroid to a single-node ``Instance`` (deprecated).
.. deprecated::
Use :meth:`to_pose` instead.
Args:
skeleton: Skeleton to use for the instance. Must have exactly one
node. Defaults to the shared ``CENTROID_SKELETON``.
Returns:
A ``PredictedInstance`` if this is a ``PredictedCentroid``,
otherwise an ``Instance``.
"""
import warnings
warnings.warn(
"Centroid.to_instance() is deprecated; use Centroid.to_pose() instead.",
DeprecationWarning,
stacklevel=2,
)
return self.to_pose(skeleton=skeleton)
to_mask(height, width, radius, error_on_empty=False)
¶
Rasterize a circular ROI around this centroid into a mask.
Equivalent to self.to_roi(radius).to_mask(height, width). A
PredictedCentroid produces a PredictedSegmentationMask carrying
its score; any other centroid produces a UserSegmentationMask.
Metadata is inherited.
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 |
radius
|
float
|
Radius of the circular region around the centroid. Required. |
required |
error_on_empty
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
SegmentationMask
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the centroid is degenerate and |
Source code in sleap_io/model/centroid.py
def to_mask(
self,
height: int,
width: int,
radius: float,
error_on_empty: bool = False,
) -> "SegmentationMask":
"""Rasterize a circular ROI around this centroid into a mask.
Equivalent to ``self.to_roi(radius).to_mask(height, width)``. A
``PredictedCentroid`` produces a ``PredictedSegmentationMask`` carrying
its ``score``; any other centroid produces a ``UserSegmentationMask``.
Metadata is inherited.
Args:
height: Height of the output mask in pixels.
width: Width of the output mask in pixels.
radius: Radius of the circular region around the centroid. Required.
error_on_empty: If ``True``, raise ``ValueError`` when this centroid
is degenerate (NaN) instead of returning an all-background mask.
Returns:
A ``SegmentationMask`` with the rasterized circular region (all
background if the centroid is degenerate).
Raises:
ValueError: If the centroid is degenerate and ``error_on_empty`` is
``True``.
"""
if self.is_empty:
if error_on_empty:
raise ValueError("Cannot compute mask of a degenerate (NaN) centroid.")
from sleap_io.model.mask import (
PredictedSegmentationMask,
UserSegmentationMask,
)
empty = np.zeros((height, width), dtype=bool)
kwargs = dict(
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 PredictedSegmentationMask.from_numpy(
empty, score=self.score, **kwargs
)
return UserSegmentationMask.from_numpy(empty, **kwargs)
return self.to_roi(radius).to_mask(height, width)
to_pose(skeleton=None)
¶
Convert this centroid to a single-node Instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
skeleton
|
Skeleton | None
|
Skeleton to use for the instance. Must have exactly one
node. Defaults to the shared |
None
|
Returns:
| Type | Description |
|---|---|
Instance | PredictedInstance
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the skeleton has more than one node. |
Source code in sleap_io/model/centroid.py
def to_pose(
self, skeleton: "Skeleton | None" = None
) -> "Instance | PredictedInstance":
"""Convert this centroid to a single-node ``Instance``.
Args:
skeleton: Skeleton to use for the instance. Must have exactly one
node. Defaults to the shared ``CENTROID_SKELETON``.
Returns:
A ``PredictedInstance`` if this is a ``PredictedCentroid``,
otherwise an ``Instance``.
Raises:
ValueError: If the skeleton has more than one node.
"""
from sleap_io.model.instance import Instance, PredictedInstance
if skeleton is None:
skeleton = get_centroid_skeleton()
if len(skeleton) > 1:
raise ValueError(
f"Skeleton must have exactly 1 node for centroid conversion, "
f"got {len(skeleton)}."
)
points = np.array([[self.x, self.y]])
if isinstance(self, PredictedCentroid):
return PredictedInstance.from_numpy(
points_data=points,
skeleton=skeleton,
score=self.score,
track=self.track,
tracking_score=self.tracking_score,
identity=self.identity,
identity_score=self.identity_score,
identity_embedding=self.identity_embedding,
category=self.category,
category_score=self.category_score,
category_embedding=self.category_embedding,
)
else:
return Instance.from_numpy(
points_data=points,
skeleton=skeleton,
track=self.track,
tracking_score=self.tracking_score,
identity=self.identity,
identity_score=self.identity_score,
identity_embedding=self.identity_embedding,
category=self.category,
category_score=self.category_score,
category_embedding=self.category_embedding,
)
to_roi(radius, error_on_empty=False)
¶
Construct a circular ROI centered on this centroid.
A PredictedCentroid produces a PredictedROI carrying its
score; any other centroid produces a UserROI. Metadata (track,
tracking_score, identity, identity_score, category, name, source,
instance) is inherited.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
radius
|
float
|
Radius of the circular ROI. Required. |
required |
error_on_empty
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
ROI
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the centroid is degenerate and |
Source code in sleap_io/model/centroid.py
def to_roi(self, radius: float, error_on_empty: bool = False) -> "ROI":
"""Construct a circular ROI centered on this centroid.
A ``PredictedCentroid`` produces a ``PredictedROI`` carrying its
``score``; any other centroid produces a ``UserROI``. Metadata (track,
tracking_score, identity, identity_score, category, name, source,
instance) is inherited.
Args:
radius: Radius of the circular ROI. Required.
error_on_empty: If ``True``, raise ``ValueError`` when this centroid
is degenerate (NaN) instead of returning an empty-geometry ROI.
Returns:
A ``ROI`` with a buffered-point (circular) geometry, or an empty
``Polygon`` geometry if the centroid is degenerate.
Raises:
ValueError: If the centroid is degenerate and ``error_on_empty`` is
``True``.
"""
from shapely.geometry import Point, Polygon
from sleap_io.model.roi import PredictedROI, UserROI
if self.is_empty:
if error_on_empty:
raise ValueError("Cannot compute ROI of a degenerate (NaN) centroid.")
geom = Polygon()
else:
geom = Point(self.x, self.y).buffer(radius)
kwargs = dict(
geometry=geom,
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 PredictedROI(score=self.score, **kwargs)
return UserROI(**kwargs)
sleap_io.UserCentroid
¶
Bases: sleap_io.model.centroid.Centroid
A human-annotated or derived centroid.
Inherits all fields from Centroid. Has no additional fields.
See Centroid for attribute documentation.
Methods:
| Name | Description |
|---|---|
__init__ |
Method generated by attrs for class UserCentroid. |
__repr__ |
Method generated by attrs for class UserCentroid. |
__setattr__ |
Method generated by attrs for class UserCentroid. |
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 |
|
__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/centroid.py
__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 |
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
|
collected_fields_by_mro |
bool
|
Whether the class fields were collected by method resolution order.
That is, correctly but unlike |
added_init |
bool
|
Whether the class has an attrs-generated |
added_repr |
bool
|
Whether the class has an attrs-generated |
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 |
added_match_args |
bool
|
Whether the class supports positional |
added_str |
bool
|
Whether the class has an attrs-generated |
added_pickling |
bool
|
Whether the class has attrs-generated |
on_setattr_hook |
Callable[[Any, Attribute[Any], Any], Any] | None
|
The class's |
field_transformer |
Callable[[Attribute[Any]], Attribute[Any]] | None
|
The class's |
.. versionadded:: 25.4.0
__doc__ = 'A human-annotated or derived centroid.\n\nInherits all fields from ``Centroid``. Has no additional fields.\n\nSee ``Centroid`` for attribute documentation.\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__ = 638
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__ = ('x', 'y', 'z', 'track', 'tracking_score', 'identity', 'identity_score', 'instance', 'category', 'name', 'source', '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.centroid'
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__(x, y, z=None, track=None, tracking_score=None, identity=None, identity_score=None, instance=None, category=None, name='', source='', identity_embedding=None, category_score=None, category_embedding=None)
¶
Method generated by attrs for class UserCentroid.
Source code in sleap_io/model/centroid.py
from __future__ import annotations
from typing import TYPE_CHECKING
import attrs
import numpy as np
from sleap_io.model.category import to_category
if TYPE_CHECKING:
from sleap_io.model.bbox import BoundingBox
from sleap_io.model.category import Category
from sleap_io.model.embedding import Embedding
from sleap_io.model.identity import Identity
from sleap_io.model.instance import Instance, PredictedInstance, Track
from sleap_io.model.mask import SegmentationMask
from sleap_io.model.roi import ROI
from sleap_io.model.skeleton import Skeleton
__repr__()
¶
Method generated by attrs for class UserCentroid.
Source code in sleap_io/model/centroid.py
"""Data structures for centroid annotations.
Centroids are lightweight point annotations representing the center of an object.
They support user/predicted distinction and interconversion with single-node
``Instance`` objects.
The class hierarchy:
- ``Centroid`` — abstract base with coordinates, video/frame/track/instance metadata
- ``UserCentroid`` — human-annotated or derived centroid
- ``PredictedCentroid`` — model-predicted centroid with confidence score
A module-level ``CENTROID_SKELETON`` is provided for creating single-node
``Instance`` objects from centroids.
"""
__setattr__(name, val)
¶
Method generated by attrs for class UserCentroid.
sleap_io.PredictedCentroid
¶
Bases: sleap_io.model.centroid.Centroid
A model-predicted centroid with a confidence score.
Attributes:
| Name | Type | Description |
|---|---|---|
score |
Detection confidence score (0-1). |
See Centroid for other attribute documentation.
Methods:
| Name | Description |
|---|---|
__init__ |
Method generated by attrs for class PredictedCentroid. |
__repr__ |
Method generated by attrs for class PredictedCentroid. |
__setattr__ |
Method generated by attrs for class PredictedCentroid. |
Source code in sleap_io/model/centroid.py
__annotations__ = {'score': 'float'}
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 |
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
|
collected_fields_by_mro |
bool
|
Whether the class fields were collected by method resolution order.
That is, correctly but unlike |
added_init |
bool
|
Whether the class has an attrs-generated |
added_repr |
bool
|
Whether the class has an attrs-generated |
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 |
added_match_args |
bool
|
Whether the class supports positional |
added_str |
bool
|
Whether the class has an attrs-generated |
added_pickling |
bool
|
Whether the class has attrs-generated |
on_setattr_hook |
Callable[[Any, Attribute[Any], Any], Any] | None
|
The class's |
field_transformer |
Callable[[Attribute[Any]], Attribute[Any]] | None
|
The class's |
.. versionadded:: 25.4.0
__doc__ = 'A model-predicted centroid with a confidence score.\n\nAttributes:\n score: Detection confidence score (0-1).\n\nSee ``Centroid`` for other attribute documentation.\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__ = 650
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__ = ('x', 'y', 'z', 'track', 'tracking_score', 'identity', 'identity_score', 'instance', 'category', 'name', 'source', 'identity_embedding', 'category_score', 'category_embedding', 'score')
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.centroid'
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__ = ('score',)
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__(x, y, z=None, track=None, tracking_score=None, identity=None, identity_score=None, instance=None, category=None, name='', source='', identity_embedding=None, category_score=None, category_embedding=None, score=0.0)
¶
Method generated by attrs for class PredictedCentroid.
Source code in sleap_io/model/centroid.py
from __future__ import annotations
from typing import TYPE_CHECKING
import attrs
import numpy as np
from sleap_io.model.category import to_category
if TYPE_CHECKING:
from sleap_io.model.bbox import BoundingBox
from sleap_io.model.category import Category
from sleap_io.model.embedding import Embedding
from sleap_io.model.identity import Identity
from sleap_io.model.instance import Instance, PredictedInstance, Track
from sleap_io.model.mask import SegmentationMask
from sleap_io.model.roi import ROI
from sleap_io.model.skeleton import Skeleton
__repr__()
¶
Method generated by attrs for class PredictedCentroid.
Source code in sleap_io/model/centroid.py
"""Data structures for centroid annotations.
Centroids are lightweight point annotations representing the center of an object.
They support user/predicted distinction and interconversion with single-node
``Instance`` objects.
The class hierarchy:
- ``Centroid`` — abstract base with coordinates, video/frame/track/instance metadata
- ``UserCentroid`` — human-annotated or derived centroid
- ``PredictedCentroid`` — model-predicted centroid with confidence score
A module-level ``CENTROID_SKELETON`` is provided for creating single-node
``Instance`` objects from centroids.
"""
__setattr__(name, val)
¶
Method generated by attrs for class PredictedCentroid.