Files
2026-07-13 13:05:14 +08:00

179 lines
5.7 KiB
Python

from __future__ import annotations
from typing import TYPE_CHECKING
import pytest
import rerun as rr
from rerun.components import AnnotationContext, AnnotationContextLike
from rerun.datatypes import (
AnnotationInfo,
AnnotationInfoLike,
ClassDescription,
ClassDescriptionArrayLike,
ClassDescriptionMapElem,
KeypointPair,
KeypointPairLike,
Rgba32,
Utf8,
)
if TYPE_CHECKING:
from collections.abc import Sequence
ANNOTATION_INFO_INPUTS: list[AnnotationInfoLike] = [
AnnotationInfo(1, "label", Rgba32([1, 2, 3])),
AnnotationInfo(1, color=Rgba32([1, 2, 3])),
(1, "label"),
(1, "label", [1, 2, 3]),
]
KEYPOINT_MAP_INPUTS: list[Sequence[AnnotationInfoLike] | None] = [
None,
[],
[
(1, "label1"),
(2, "label2"),
],
[
(1, "label1", [1, 2, 3]),
(2, "label2", [4, 5, 6]),
],
[
AnnotationInfo(1, "label1", Rgba32([1, 2, 3])),
AnnotationInfo(2, "label2", Rgba32([4, 5, 6])),
],
]
KEYPOINT_CONNECTIONS_INPUTS: list[Sequence[KeypointPairLike] | None] = [
None,
[],
[
(1, 2),
],
[
[1, 2],
],
[
KeypointPair(1, 2),
],
]
def assert_correct_class_description(desc: ClassDescription) -> None:
assert desc.info.id == 1
if desc.info.label:
assert desc.info.label == Utf8("label")
if desc.info.color:
assert desc.info.color == Rgba32([1, 2, 3])
if desc.keypoint_annotations:
expected_annotations = [
AnnotationInfo(1, "label1", Rgba32([1, 2, 3])),
AnnotationInfo(2, "label2", Rgba32([4, 5, 6])),
]
for i, kp in enumerate(desc.keypoint_annotations):
assert kp.id == expected_annotations[i].id
if kp.label:
assert kp.label == expected_annotations[i].label
if kp.color:
assert kp.color == expected_annotations[i].color
if desc.keypoint_connections:
expected_pairs = [
KeypointPair(1, 2),
]
if len(desc.keypoint_connections) > 0:
assert desc.keypoint_connections == expected_pairs
@pytest.mark.parametrize("input", ANNOTATION_INFO_INPUTS)
@pytest.mark.parametrize("keypoint_annotations", KEYPOINT_MAP_INPUTS)
@pytest.mark.parametrize("keypoint_connections", KEYPOINT_CONNECTIONS_INPUTS)
def test_class_description(
input: AnnotationInfoLike,
keypoint_annotations: Sequence[AnnotationInfoLike] | None,
keypoint_connections: Sequence[KeypointPairLike] | None,
) -> None:
assert_correct_class_description(
ClassDescription(
info=input,
keypoint_annotations=keypoint_annotations,
keypoint_connections=keypoint_connections,
),
)
ANNOTATION_CONTEXT_INPUTS: list[ClassDescriptionArrayLike] = [
[
(1, "label1", [1, 2, 3]),
(2, "label2", [4, 5, 6]),
],
[
ClassDescription(info=(1, "label1", [1, 2, 3]), keypoint_annotations=[(3, "kp_label1", [7, 8, 9])]),
ClassDescription(info=(2, "label2", [4, 5, 6]), keypoint_annotations=[(4, "kp_label2", [10, 11, 12])]),
],
[
AnnotationInfo(1, "label1"),
AnnotationInfo(2, color=[4, 5, 6]),
],
[
ClassDescription(info=(1, "label1"), keypoint_annotations=[(3, "kp_label1")]),
ClassDescription(info=(2, "label2", [4, 5, 6]), keypoint_annotations=[(4, "kp_label2", [10, 11, 12])]),
],
[
ClassDescription(info=(1, "label1"), keypoint_connections=[(1, 2)]),
ClassDescription(info=(2, "label2")),
],
]
def assert_correct_annotation_context(ctx: AnnotationContext) -> None:
assert len(ctx.class_map) == 2
expected_classes = [
ClassDescriptionMapElem(
class_id=1,
class_description=ClassDescription(
info=(1, "label1", [1, 2, 3]),
keypoint_annotations=[(3, "kp_label1", [7, 8, 9])],
),
),
ClassDescriptionMapElem(
class_id=2,
class_description=ClassDescription(
info=(2, "label2", [4, 5, 6]),
keypoint_annotations=[(4, "kp_label2", [10, 11, 12])],
),
),
]
for i, item in enumerate(ctx.class_map):
assert item.class_id == expected_classes[i].class_id
assert item.class_description.info.id == expected_classes[i].class_description.info.id
if item.class_description.info.label:
assert item.class_description.info.label == expected_classes[i].class_description.info.label
if item.class_description.info.color:
assert item.class_description.info.color == expected_classes[i].class_description.info.color
if item.class_description.keypoint_annotations:
for j, kp in enumerate(item.class_description.keypoint_annotations):
assert kp.id == expected_classes[i].class_description.keypoint_annotations[j].id
if kp.label:
assert kp.label == expected_classes[i].class_description.keypoint_annotations[j].label
if kp.color:
assert kp.color == expected_classes[i].class_description.keypoint_annotations[j].color
@pytest.mark.parametrize("ctx", ANNOTATION_CONTEXT_INPUTS)
def test_annotation_context_component(ctx: Sequence[ClassDescriptionMapElem]) -> None:
assert_correct_annotation_context(AnnotationContext(ctx))
ANNOTATION_ARCH_INPUTS: Sequence[ClassDescriptionArrayLike] = [
ClassDescription(info=(1, "label1", [1, 2, 3])),
*ANNOTATION_CONTEXT_INPUTS,
]
@pytest.mark.parametrize("ctx", ANNOTATION_ARCH_INPUTS)
def test_annotation_context_arch(ctx: AnnotationContextLike) -> None:
# Verify we can construct the archetype
rr.AnnotationContext(ctx)
# TODO(jleibs): Actually verify the serialized arrow data has the right values