Skip to content

Commit fb209f0

Browse files
chore: cleanup
1 parent 1e424ef commit fb209f0

File tree

5 files changed

+35
-46
lines changed

5 files changed

+35
-46
lines changed

libs/labelbox/src/labelbox/data/annotation_types/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
from .classification import ClassificationAnswer
3333
from .classification import Radio
3434
from .classification import Text
35-
from .classification import FrameLocation
3635

3736
from .data import GenericDataRowData
3837
from .data import MaskData
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from .classification import Checklist, ClassificationAnswer, Radio, Text, FrameLocation
1+
from .classification import Checklist, ClassificationAnswer, Radio, Text

libs/labelbox/src/labelbox/data/annotation_types/classification/classification.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77
from ..feature import FeatureSchema
88

99

10-
class FrameLocation(BaseModel):
11-
"""Represents a temporal frame range with start and end times (in milliseconds)."""
12-
start: int
13-
end: int
14-
15-
1610
class ClassificationAnswer(FeatureSchema, ConfidenceMixin, CustomMetricsMixin):
1711
"""
1812
- Represents a classification option.
@@ -23,16 +17,11 @@ class ClassificationAnswer(FeatureSchema, ConfidenceMixin, CustomMetricsMixin):
2317
Each answer can have a keyframe independent of the others.
2418
So unlike object annotations, classification annotations
2519
track keyframes at a classification answer level.
26-
27-
- For temporal classifications (audio/video), optional frames can specify
28-
one or more time ranges for this answer. Must be within root annotation's frame ranges.
29-
Defaults to root frame ranges if not specified.
3020
"""
3121

3222
extra: Dict[str, Any] = {}
3323
keyframe: Optional[bool] = None
3424
classifications: Optional[List["ClassificationAnnotation"]] = None
35-
frames: Optional[List[FrameLocation]] = None
3625

3726

3827
class Radio(ConfidenceMixin, CustomMetricsMixin, BaseModel):
@@ -80,11 +69,9 @@ class ClassificationAnnotation(
8069
classifications (Optional[List[ClassificationAnnotation]]): Optional sub classification of the annotation
8170
feature_schema_id (Optional[Cuid])
8271
value (Union[Text, Checklist, Radio])
83-
frames (Optional[List[FrameLocation]]): Frame ranges for temporal classifications (audio/video). Must be within root annotation's frame ranges. Defaults to root frames if not specified.
8472
extra (Dict[str, Any])
8573
"""
8674

8775
value: Union[Text, Checklist, Radio]
8876
message_id: Optional[str] = None
89-
frames: Optional[List[FrameLocation]] = None
9077

libs/labelbox/src/labelbox/data/annotation_types/label.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ def validate_data(cls, data):
6969
def object_annotations(self) -> List[ObjectAnnotation]:
7070
return self._get_annotations_by_type(ObjectAnnotation)
7171

72-
def classification_annotations(self) -> List[ClassificationAnnotation]:
73-
return self._get_annotations_by_type(ClassificationAnnotation)
72+
def classification_annotations(self) -> List[Union[ClassificationAnnotation, TemporalClassificationText, TemporalClassificationQuestion]]:
73+
return self._get_annotations_by_type((ClassificationAnnotation, TemporalClassificationText, TemporalClassificationQuestion))
7474

7575
def _get_annotations_by_type(self, annotation_type):
7676
return [

libs/labelbox/src/labelbox/data/annotation_types/temporal.py

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@
55
frame-level precision. All temporal classifications support nested hierarchies.
66
"""
77

8-
from typing import List, Optional, Tuple, Union
9-
from pydantic import Field
8+
from typing import Any, Dict, List, Optional, Tuple, Union
9+
from pydantic import BaseModel, Field
1010

11-
from labelbox.data.annotation_types.annotation import ClassificationAnnotation
12-
from labelbox.data.annotation_types.classification.classification import (
13-
ClassificationAnswer,
14-
FrameLocation,
15-
)
11+
from ...annotated_types import Cuid
1612

1713

18-
class TemporalClassificationAnswer(ClassificationAnswer):
14+
class TemporalClassificationAnswer(BaseModel):
1915
"""
2016
Temporal answer for Radio/Checklist questions with frame ranges.
2117
@@ -27,8 +23,8 @@ class TemporalClassificationAnswer(ClassificationAnswer):
2723
frames (List[Tuple[int, int]]): List of (start_frame, end_frame) ranges in milliseconds
2824
classifications (Optional[List[Union[TemporalClassificationText, TemporalClassificationQuestion]]]):
2925
Nested classifications within this answer
30-
feature_schema_id (Optional[str]): Feature schema identifier
31-
extra (dict): Additional metadata
26+
feature_schema_id (Optional[Cuid]): Feature schema identifier
27+
extra (Dict[str, Any]): Additional metadata
3228
3329
Example:
3430
>>> # Radio answer with nested classifications
@@ -49,16 +45,19 @@ class TemporalClassificationAnswer(ClassificationAnswer):
4945
>>> )
5046
"""
5147

48+
name: str
5249
frames: List[Tuple[int, int]] = Field(
5350
default_factory=list,
5451
description="List of (start_frame, end_frame) tuples in milliseconds",
5552
)
5653
classifications: Optional[
5754
List[Union["TemporalClassificationText", "TemporalClassificationQuestion"]]
5855
] = None
56+
feature_schema_id: Optional[Cuid] = None
57+
extra: Dict[str, Any] = Field(default_factory=dict)
5958

6059

61-
class TemporalClassificationText(ClassificationAnnotation):
60+
class TemporalClassificationText(BaseModel):
6261
"""
6362
Temporal text classification with multiple text values at different frame ranges.
6463
@@ -67,17 +66,17 @@ class TemporalClassificationText(ClassificationAnnotation):
6766
6867
Args:
6968
name (str): Name of the text classification
70-
values (List[Tuple[int, int, str]]): List of (start_frame, end_frame, text_value) tuples
69+
value (List[Tuple[int, int, str]]): List of (start_frame, end_frame, text_value) tuples
7170
classifications (Optional[List[Union[TemporalClassificationText, TemporalClassificationQuestion]]]):
7271
Nested classifications
73-
feature_schema_id (Optional[str]): Feature schema identifier
74-
extra (dict): Additional metadata
72+
feature_schema_id (Optional[Cuid]): Feature schema identifier
73+
extra (Dict[str, Any]): Additional metadata
7574
7675
Example:
7776
>>> # Simple text with multiple temporal values
7877
>>> transcription = TemporalClassificationText(
7978
>>> name="transcription",
80-
>>> values=[
79+
>>> value=[
8180
>>> (1600, 2000, "Hello, how can I help you?"),
8281
>>> (2500, 3000, "Thank you for calling!"),
8382
>>> ]
@@ -86,31 +85,33 @@ class TemporalClassificationText(ClassificationAnnotation):
8685
>>> # Text with nested classifications
8786
>>> transcription_with_notes = TemporalClassificationText(
8887
>>> name="transcription",
89-
>>> values=[
88+
>>> value=[
9089
>>> (1600, 2000, "Hello, how can I help you?"),
9190
>>> ],
9291
>>> classifications=[
9392
>>> TemporalClassificationText(
9493
>>> name="speaker_notes",
95-
>>> values=[
94+
>>> value=[
9695
>>> (1600, 2000, "Polite greeting"),
9796
>>> ]
9897
>>> )
9998
>>> ]
10099
>>> )
101100
"""
102101

103-
# Override parent's value field
102+
name: str
104103
value: List[Tuple[int, int, str]] = Field(
105104
default_factory=list,
106105
description="List of (start_frame, end_frame, text_value) tuples",
107106
)
108107
classifications: Optional[
109108
List[Union["TemporalClassificationText", "TemporalClassificationQuestion"]]
110109
] = None
110+
feature_schema_id: Optional[Cuid] = None
111+
extra: Dict[str, Any] = Field(default_factory=dict)
111112

112113

113-
class TemporalClassificationQuestion(ClassificationAnnotation):
114+
class TemporalClassificationQuestion(BaseModel):
114115
"""
115116
Temporal Radio/Checklist question with multiple answer options.
116117
@@ -119,20 +120,20 @@ class TemporalClassificationQuestion(ClassificationAnnotation):
119120
120121
Args:
121122
name (str): Name of the question/classification
122-
answers (List[TemporalClassificationAnswer]): List of answer options with frame ranges
123-
feature_schema_id (Optional[str]): Feature schema identifier
124-
extra (dict): Additional metadata
123+
value (List[TemporalClassificationAnswer]): List of answer options with frame ranges
124+
feature_schema_id (Optional[Cuid]): Feature schema identifier
125+
extra (Dict[str, Any]): Additional metadata
125126
126127
Note:
127-
- Radio: Single answer in the answers list
128-
- Checklist: Multiple answers in the answers list
128+
- Radio: Single answer in the value list
129+
- Checklist: Multiple answers in the value list
129130
The serializer automatically handles the distinction based on the number of answers.
130131
131132
Example:
132133
>>> # Radio question (single answer)
133134
>>> speaker = TemporalClassificationQuestion(
134135
>>> name="speaker",
135-
>>> answers=[
136+
>>> value=[
136137
>>> TemporalClassificationAnswer(
137138
>>> name="user",
138139
>>> frames=[(200, 1600)]
@@ -143,7 +144,7 @@ class TemporalClassificationQuestion(ClassificationAnnotation):
143144
>>> # Checklist question (multiple answers)
144145
>>> audio_quality = TemporalClassificationQuestion(
145146
>>> name="audio_quality",
146-
>>> answers=[
147+
>>> value=[
147148
>>> TemporalClassificationAnswer(
148149
>>> name="background_noise",
149150
>>> frames=[(0, 1500), (2000, 3000)]
@@ -158,14 +159,14 @@ class TemporalClassificationQuestion(ClassificationAnnotation):
158159
>>> # Nested structure: Radio > Radio > Radio
159160
>>> speaker_with_tone = TemporalClassificationQuestion(
160161
>>> name="speaker",
161-
>>> answers=[
162+
>>> value=[
162163
>>> TemporalClassificationAnswer(
163164
>>> name="user",
164165
>>> frames=[(200, 1600)],
165166
>>> classifications=[
166167
>>> TemporalClassificationQuestion(
167168
>>> name="tone",
168-
>>> answers=[
169+
>>> value=[
169170
>>> TemporalClassificationAnswer(
170171
>>> name="professional",
171172
>>> frames=[(1000, 1600)]
@@ -178,14 +179,16 @@ class TemporalClassificationQuestion(ClassificationAnnotation):
178179
>>> )
179180
"""
180181

181-
# Override parent's value field
182+
name: str
182183
value: List[TemporalClassificationAnswer] = Field(
183184
default_factory=list,
184185
description="List of temporal answer options",
185186
)
186187
classifications: Optional[
187188
List[Union["TemporalClassificationText", "TemporalClassificationQuestion"]]
188189
] = None
190+
feature_schema_id: Optional[Cuid] = None
191+
extra: Dict[str, Any] = Field(default_factory=dict)
189192

190193

191194
# Update forward references for recursive types

0 commit comments

Comments
 (0)