4
4
"""
5
5
6
6
from enum import Enum
7
- from pystac .extensions .base import ExtensionManagementMixin
7
+ from pystac .extensions .base import ExtensionManagementMixin , SummariesExtension
8
8
from typing import Any , Dict , Iterable , List , Optional , Set , Union , cast
9
9
10
10
import pystac
11
11
from pystac .serialization .identify import STACJSONDescription , STACVersionID
12
12
from pystac .extensions .hooks import ExtensionHooks
13
- from pystac .utils import get_required
13
+ from pystac .utils import get_required , map_opt
14
14
15
15
SCHEMA_URI = "https://stac-extensions.github.io/label/v1.0.0/schema.json"
16
16
@@ -52,6 +52,28 @@ def __str__(self) -> str:
52
52
"""Convenience attribute for checking if values are valid label types"""
53
53
54
54
55
+ class LabelTask (str , Enum ):
56
+ """Enumerates recommended values for "label:tasks" field."""
57
+
58
+ def __str__ (self ) -> str :
59
+ return str (self .value )
60
+
61
+ REGRESSION = "regression"
62
+ CLASSIFICATION = "classification"
63
+ DETECTION = "detection"
64
+ SEGMENTATION = "segmentation"
65
+
66
+
67
+ class LabelMethod (str , Enum ):
68
+ """Enumerates recommended values for "label:methods" field."""
69
+
70
+ def __str__ (self ) -> str :
71
+ return str (self .value )
72
+
73
+ AUTOMATED = "automated"
74
+ MANUAL = "manual"
75
+
76
+
55
77
class LabelClasses :
56
78
"""Defines the list of possible class names (e.g., tree, building, car, hippo).
57
79
@@ -121,6 +143,15 @@ def __repr__(self) -> str:
121
143
"," .join ([str (x ) for x in self .classes ])
122
144
)
123
145
146
+ def __eq__ (self , o : object ) -> bool :
147
+ if isinstance (o , LabelClasses ):
148
+ o = o .to_dict ()
149
+
150
+ if not isinstance (o , dict ):
151
+ return NotImplemented
152
+
153
+ return self .to_dict () == o
154
+
124
155
def to_dict (self ) -> Dict [str , Any ]:
125
156
"""Returns the dictionary representing the JSON of this instance."""
126
157
return self .properties
@@ -180,6 +211,15 @@ def to_dict(self) -> Dict[str, Any]:
180
211
"""Returns the dictionary representing the JSON of this instance."""
181
212
return self .properties
182
213
214
+ def __eq__ (self , o : object ) -> bool :
215
+ if isinstance (o , LabelCount ):
216
+ o = o .to_dict ()
217
+
218
+ if not isinstance (o , dict ):
219
+ return NotImplemented
220
+
221
+ return self .to_dict () == o
222
+
183
223
184
224
class LabelStatistics :
185
225
"""Contains statistics for regression/continuous numeric value data.
@@ -234,6 +274,15 @@ def to_dict(self) -> Dict[str, Any]:
234
274
"""Returns the dictionary representing the JSON of this LabelStatistics."""
235
275
return self .properties
236
276
277
+ def __eq__ (self , o : object ) -> bool :
278
+ if isinstance (o , LabelStatistics ):
279
+ o = o .to_dict ()
280
+
281
+ if not isinstance (o , dict ):
282
+ return NotImplemented
283
+
284
+ return self .to_dict () == o
285
+
237
286
238
287
class LabelOverview :
239
288
"""Stores counts (for classification-type data) or summary statistics (for
@@ -379,6 +428,15 @@ def to_dict(self) -> Dict[str, Any]:
379
428
"""Returns the dictionary representing the JSON of this LabelOverview."""
380
429
return self .properties
381
430
431
+ def __eq__ (self , o : object ) -> bool :
432
+ if isinstance (o , LabelOverview ):
433
+ o = o .to_dict ()
434
+
435
+ if not isinstance (o , dict ):
436
+ return NotImplemented
437
+
438
+ return self .to_dict () == o
439
+
382
440
383
441
class LabelExtension (ExtensionManagementMixin [pystac .Item ]):
384
442
"""A class that can be used to extend the properties of an
@@ -403,8 +461,8 @@ def apply(
403
461
label_type : LabelType ,
404
462
label_properties : Optional [List [str ]] = None ,
405
463
label_classes : Optional [List [LabelClasses ]] = None ,
406
- label_tasks : Optional [List [str ]] = None ,
407
- label_methods : Optional [List [str ]] = None ,
464
+ label_tasks : Optional [List [Union [ LabelTask , str ] ]] = None ,
465
+ label_methods : Optional [List [Union [ LabelMethod , str ] ]] = None ,
408
466
label_overviews : Optional [List [LabelOverview ]] = None ,
409
467
) -> None :
410
468
"""Applies label extension properties to the extended Item.
@@ -499,28 +557,28 @@ def label_classes(self, v: Optional[List[LabelClasses]]) -> None:
499
557
self .obj .properties [CLASSES_PROP ] = classes
500
558
501
559
@property
502
- def label_tasks (self ) -> Optional [List [str ]]:
560
+ def label_tasks (self ) -> Optional [List [Union [ LabelTask , str ] ]]:
503
561
"""Gets or set a list of tasks these labels apply to. Usually a subset of 'regression',
504
562
'classification', 'detection', or 'segmentation', but may be arbitrary
505
563
values."""
506
564
return self .obj .properties .get (TASKS_PROP )
507
565
508
566
@label_tasks .setter
509
- def label_tasks (self , v : Optional [List [str ]]) -> None :
567
+ def label_tasks (self , v : Optional [List [Union [ LabelTask , str ] ]]) -> None :
510
568
if v is None :
511
569
self .obj .properties .pop (TASKS_PROP , None )
512
570
else :
513
571
self .obj .properties [TASKS_PROP ] = v
514
572
515
573
@property
516
- def label_methods (self ) -> Optional [List [str ]]:
574
+ def label_methods (self ) -> Optional [List [Union [ LabelMethod , str ] ]]:
517
575
"""Gets or set a list of methods used for labeling.
518
576
519
577
Usually a subset of 'automated' or 'manual', but may be arbitrary values."""
520
578
return self .obj .properties .get ("label:methods" )
521
579
522
580
@label_methods .setter
523
- def label_methods (self , v : Optional [List [str ]]) -> None :
581
+ def label_methods (self , v : Optional [List [Union [ LabelMethod , str ] ]]) -> None :
524
582
if v is None :
525
583
self .obj .properties .pop ("label:methods" , None )
526
584
else :
@@ -655,6 +713,83 @@ def ext(cls, obj: pystac.Item, add_if_missing: bool = False) -> "LabelExtension"
655
713
f"Label extension does not apply to type { type (obj )} "
656
714
)
657
715
716
+ @staticmethod
717
+ def summaries (obj : pystac .Collection ) -> "SummariesLabelExtension" :
718
+ """Returns the extended summaries object for the given collection."""
719
+ return SummariesLabelExtension (obj )
720
+
721
+
722
+ class SummariesLabelExtension (SummariesExtension ):
723
+ """A concrete implementation of :class:`~SummariesExtension` that extends
724
+ the ``summaries`` field of a :class:`~pystac.Collection` to include properties
725
+ defined in the :stac-ext:`Label Extension <label>`.
726
+ """
727
+
728
+ @property
729
+ def label_properties (self ) -> Optional [List [str ]]:
730
+ """Get or sets the summary of :attr:`LabelExtension.label_properties` values
731
+ for this Collection.
732
+ """
733
+
734
+ return self .summaries .get_list (PROPERTIES_PROP )
735
+
736
+ @label_properties .setter
737
+ def label_properties (self , v : Optional [List [LabelClasses ]]) -> None :
738
+ self ._set_summary (PROPERTIES_PROP , v )
739
+
740
+ @property
741
+ def label_classes (self ) -> Optional [List [LabelClasses ]]:
742
+ """Get or sets the summary of :attr:`LabelExtension.label_classes` values
743
+ for this Collection.
744
+ """
745
+
746
+ return map_opt (
747
+ lambda classes : [LabelClasses (c ) for c in classes ],
748
+ self .summaries .get_list (CLASSES_PROP ),
749
+ )
750
+
751
+ @label_classes .setter
752
+ def label_classes (self , v : Optional [List [LabelClasses ]]) -> None :
753
+ self ._set_summary (
754
+ CLASSES_PROP , map_opt (lambda classes : [c .to_dict () for c in classes ], v )
755
+ )
756
+
757
+ @property
758
+ def label_type (self ) -> Optional [List [LabelType ]]:
759
+ """Get or sets the summary of :attr:`LabelExtension.label_type` values
760
+ for this Collection.
761
+ """
762
+
763
+ return self .summaries .get_list (TYPE_PROP )
764
+
765
+ @label_type .setter
766
+ def label_type (self , v : Optional [List [LabelType ]]) -> None :
767
+ self ._set_summary (TYPE_PROP , v )
768
+
769
+ @property
770
+ def label_tasks (self ) -> Optional [List [Union [LabelTask , str ]]]:
771
+ """Get or sets the summary of :attr:`LabelExtension.label_tasks` values
772
+ for this Collection.
773
+ """
774
+
775
+ return self .summaries .get_list (TASKS_PROP )
776
+
777
+ @label_tasks .setter
778
+ def label_tasks (self , v : Optional [List [Union [LabelTask , str ]]]) -> None :
779
+ self ._set_summary (TASKS_PROP , v )
780
+
781
+ @property
782
+ def label_methods (self ) -> Optional [List [Union [LabelMethod , str ]]]:
783
+ """Get or sets the summary of :attr:`LabelExtension.label_methods` values
784
+ for this Collection.
785
+ """
786
+
787
+ return self .summaries .get_list (METHODS_PROP )
788
+
789
+ @label_methods .setter
790
+ def label_methods (self , v : Optional [List [Union [LabelMethod , str ]]]) -> None :
791
+ self ._set_summary (METHODS_PROP , v )
792
+
658
793
659
794
class LabelExtensionHooks (ExtensionHooks ):
660
795
schema_uri : str = SCHEMA_URI
0 commit comments