4
4
"""
5
5
6
6
import enum
7
- from typing import Any , Dict , Generic , List , Optional , TypeVar , cast
7
+ from typing import Any , Dict , Generic , Iterable , List , Optional , TypeVar , cast
8
8
9
9
import pystac
10
10
from pystac .serialization .identify import STACJSONDescription , STACVersionID
14
14
15
15
T = TypeVar ("T" , pystac .Item , pystac .Asset )
16
16
17
- SCHEMA_URI = "https://stac-extensions.github.io/sar/v1.0.0/schema.json"
17
+ SCHEMA_URI : str = "https://stac-extensions.github.io/sar/v1.0.0/schema.json"
18
+ PREFIX : str = "sar:"
18
19
19
20
# Required
20
- INSTRUMENT_MODE : str = "sar: instrument_mode"
21
- FREQUENCY_BAND : str = "sar: frequency_band"
22
- POLARIZATIONS : str = "sar: polarizations"
23
- PRODUCT_TYPE : str = "sar: product_type"
21
+ INSTRUMENT_MODE : str = PREFIX + " instrument_mode"
22
+ FREQUENCY_BAND : str = PREFIX + " frequency_band"
23
+ POLARIZATIONS : str = PREFIX + " polarizations"
24
+ PRODUCT_TYPE : str = PREFIX + " product_type"
24
25
25
26
# Not required
26
- CENTER_FREQUENCY : str = "sar: center_frequency"
27
- RESOLUTION_RANGE : str = "sar: resolution_range"
28
- RESOLUTION_AZIMUTH : str = "sar: resolution_azimuth"
29
- PIXEL_SPACING_RANGE : str = "sar: pixel_spacing_range"
30
- PIXEL_SPACING_AZIMUTH : str = "sar: pixel_spacing_azimuth"
31
- LOOKS_RANGE : str = "sar: looks_range"
32
- LOOKS_AZIMUTH : str = "sar: looks_azimuth"
33
- LOOKS_EQUIVALENT_NUMBER : str = "sar: looks_equivalent_number"
34
- OBSERVATION_DIRECTION : str = "sar: observation_direction"
27
+ CENTER_FREQUENCY : str = PREFIX + " center_frequency"
28
+ RESOLUTION_RANGE : str = PREFIX + " resolution_range"
29
+ RESOLUTION_AZIMUTH : str = PREFIX + " resolution_azimuth"
30
+ PIXEL_SPACING_RANGE : str = PREFIX + " pixel_spacing_range"
31
+ PIXEL_SPACING_AZIMUTH : str = PREFIX + " pixel_spacing_azimuth"
32
+ LOOKS_RANGE : str = PREFIX + " looks_range"
33
+ LOOKS_AZIMUTH : str = PREFIX + " looks_azimuth"
34
+ LOOKS_EQUIVALENT_NUMBER : str = PREFIX + " looks_equivalent_number"
35
+ OBSERVATION_DIRECTION : str = PREFIX + " observation_direction"
35
36
36
37
37
38
class FrequencyBand (str , enum .Enum ):
@@ -60,17 +61,19 @@ class ObservationDirection(enum.Enum):
60
61
class SarExtension (
61
62
Generic [T ], PropertiesExtension , ExtensionManagementMixin [pystac .Item ]
62
63
):
63
- """SarItemExt extends Item to add sar properties to a STAC Item.
64
+ """An abstract class that can be used to extend the properties of an
65
+ :class:`~pystac.Item` or :class:`~pystac.Asset` with properties from the
66
+ :stac-ext:`SAR Extension <sar>`. This class is generic over the type of
67
+ STAC Object to be extended (e.g. :class:`~pystac.Item`,
68
+ :class:`~pystac.Asset`).
64
69
65
- Args:
66
- item : The item to be extended.
70
+ To create a concrete instance of :class:`SARExtension`, use the
71
+ :meth:`SARExtension.ext` method. For example:
67
72
68
- Attributes:
69
- item : The item that is being extended.
73
+ .. code-block:: python
70
74
71
- Note:
72
- Using SarItemExt to directly wrap an item will add the 'sar'
73
- extension ID to the item's stac_extensions.
75
+ >>> item: pystac.Item = ...
76
+ >>> sar_ext = SARExtension.ext(item)
74
77
"""
75
78
76
79
def apply (
@@ -149,11 +152,7 @@ def apply(
149
152
150
153
@property
151
154
def instrument_mode (self ) -> str :
152
- """Get or sets an instrument mode string for the item.
153
-
154
- Returns:
155
- str
156
- """
155
+ """Gets or sets an instrument mode string for the item."""
157
156
return get_required (
158
157
self ._get_property (INSTRUMENT_MODE , str ), self , INSTRUMENT_MODE
159
158
)
@@ -164,11 +163,7 @@ def instrument_mode(self, v: str) -> None:
164
163
165
164
@property
166
165
def frequency_band (self ) -> FrequencyBand :
167
- """Get or sets a FrequencyBand for the item.
168
-
169
- Returns:
170
- FrequencyBand
171
- """
166
+ """Gets or sets a FrequencyBand for the item."""
172
167
return get_required (
173
168
map_opt (
174
169
lambda x : FrequencyBand (x ), self ._get_property (FREQUENCY_BAND , str )
@@ -183,11 +178,7 @@ def frequency_band(self, v: FrequencyBand) -> None:
183
178
184
179
@property
185
180
def polarizations (self ) -> List [Polarization ]:
186
- """Get or sets a list of polarizations for the item.
187
-
188
- Returns:
189
- List[Polarization]
190
- """
181
+ """Gets or sets a list of polarizations for the item."""
191
182
return get_required (
192
183
map_opt (
193
184
lambda values : [Polarization (v ) for v in values ],
@@ -205,11 +196,7 @@ def polarizations(self, values: List[Polarization]) -> None:
205
196
206
197
@property
207
198
def product_type (self ) -> str :
208
- """Get or sets a product type string for the item.
209
-
210
- Returns:
211
- str
212
- """
199
+ """Gets or sets a product type string for the item."""
213
200
return get_required (self ._get_property (PRODUCT_TYPE , str ), self , PRODUCT_TYPE )
214
201
215
202
@product_type .setter
@@ -218,7 +205,7 @@ def product_type(self, v: str) -> None:
218
205
219
206
@property
220
207
def center_frequency (self ) -> Optional [float ]:
221
- """Get or sets a center frequency for the item."""
208
+ """Gets or sets a center frequency for the item."""
222
209
return self ._get_property (CENTER_FREQUENCY , float )
223
210
224
211
@center_frequency .setter
@@ -227,7 +214,7 @@ def center_frequency(self, v: Optional[float]) -> None:
227
214
228
215
@property
229
216
def resolution_range (self ) -> Optional [float ]:
230
- """Get or sets a resolution range for the item."""
217
+ """Gets or sets a resolution range for the item."""
231
218
return self ._get_property (RESOLUTION_RANGE , float )
232
219
233
220
@resolution_range .setter
@@ -236,7 +223,7 @@ def resolution_range(self, v: Optional[float]) -> None:
236
223
237
224
@property
238
225
def resolution_azimuth (self ) -> Optional [float ]:
239
- """Get or sets a resolution azimuth for the item."""
226
+ """Gets or sets a resolution azimuth for the item."""
240
227
return self ._get_property (RESOLUTION_AZIMUTH , float )
241
228
242
229
@resolution_azimuth .setter
@@ -245,7 +232,7 @@ def resolution_azimuth(self, v: Optional[float]) -> None:
245
232
246
233
@property
247
234
def pixel_spacing_range (self ) -> Optional [float ]:
248
- """Get or sets a pixel spacing range for the item."""
235
+ """Gets or sets a pixel spacing range for the item."""
249
236
return self ._get_property (PIXEL_SPACING_RANGE , float )
250
237
251
238
@pixel_spacing_range .setter
@@ -254,7 +241,7 @@ def pixel_spacing_range(self, v: Optional[float]) -> None:
254
241
255
242
@property
256
243
def pixel_spacing_azimuth (self ) -> Optional [float ]:
257
- """Get or sets a pixel spacing azimuth for the item."""
244
+ """Gets or sets a pixel spacing azimuth for the item."""
258
245
return self ._get_property (PIXEL_SPACING_AZIMUTH , float )
259
246
260
247
@pixel_spacing_azimuth .setter
@@ -263,7 +250,7 @@ def pixel_spacing_azimuth(self, v: Optional[float]) -> None:
263
250
264
251
@property
265
252
def looks_range (self ) -> Optional [int ]:
266
- """Get or sets a looks range for the item."""
253
+ """Gets or sets a looks range for the item."""
267
254
return self ._get_property (LOOKS_RANGE , int )
268
255
269
256
@looks_range .setter
@@ -272,7 +259,7 @@ def looks_range(self, v: Optional[int]) -> None:
272
259
273
260
@property
274
261
def looks_azimuth (self ) -> Optional [int ]:
275
- """Get or sets a looks azimuth for the item."""
262
+ """Gets or sets a looks azimuth for the item."""
276
263
return self ._get_property (LOOKS_AZIMUTH , int )
277
264
278
265
@looks_azimuth .setter
@@ -281,7 +268,7 @@ def looks_azimuth(self, v: Optional[int]) -> None:
281
268
282
269
@property
283
270
def looks_equivalent_number (self ) -> Optional [float ]:
284
- """Get or sets a looks equivalent number for the item."""
271
+ """Gets or sets a looks equivalent number for the item."""
285
272
return self ._get_property (LOOKS_EQUIVALENT_NUMBER , float )
286
273
287
274
@looks_equivalent_number .setter
@@ -290,7 +277,7 @@ def looks_equivalent_number(self, v: Optional[float]) -> None:
290
277
291
278
@property
292
279
def observation_direction (self ) -> Optional [ObservationDirection ]:
293
- """Get or sets an observation direction for the item."""
280
+ """Gets or sets an observation direction for the item."""
294
281
result = self ._get_property (OBSERVATION_DIRECTION , str )
295
282
if result is None :
296
283
return None
@@ -306,6 +293,16 @@ def get_schema_uri(cls) -> str:
306
293
307
294
@classmethod
308
295
def ext (cls , obj : T , add_if_missing : bool = False ) -> "SarExtension[T]" :
296
+ """Extends the given STAC Object with properties from the :stac-ext:`SAR
297
+ Extension <sar>`.
298
+
299
+ This extension can be applied to instances of :class:`~pystac.Item` or
300
+ :class:`~pystac.Asset`.
301
+
302
+ Raises:
303
+
304
+ pystac.ExtensionTypeError : If an invalid object type is passed.
305
+ """
309
306
if isinstance (obj , pystac .Item ):
310
307
if add_if_missing :
311
308
cls .add_to (obj )
@@ -323,6 +320,20 @@ def ext(cls, obj: T, add_if_missing: bool = False) -> "SarExtension[T]":
323
320
324
321
325
322
class ItemSarExtension (SarExtension [pystac .Item ]):
323
+ """A concrete implementation of :class:`SARExtension` on an :class:`~pystac.Item`
324
+ that extends the properties of the Item to include properties defined in the
325
+ :stac-ext:`SAR Extension <sar>`.
326
+
327
+ This class should generally not be instantiated directly. Instead, call
328
+ :meth:`SARExtension.ext` on an :class:`~pystac.Item` to extend it.
329
+ """
330
+
331
+ item : pystac .Item
332
+ """The :class:`~pystac.Item` being extended."""
333
+
334
+ properties : Dict [str , Any ]
335
+ """The :class:`~pystac.Item` properties, including extension properties."""
336
+
326
337
def __init__ (self , item : pystac .Item ):
327
338
self .item = item
328
339
self .properties = item .properties
@@ -332,6 +343,24 @@ def __repr__(self) -> str:
332
343
333
344
334
345
class AssetSarExtension (SarExtension [pystac .Asset ]):
346
+ """A concrete implementation of :class:`SARExtension` on an :class:`~pystac.Asset`
347
+ that extends the Asset fields to include properties defined in the
348
+ :stac-ext:`SAR Extension <sar>`.
349
+
350
+ This class should generally not be instantiated directly. Instead, call
351
+ :meth:`SARExtension.ext` on an :class:`~pystac.Asset` to extend it.
352
+ """
353
+
354
+ asset_href : str
355
+ """The ``href`` value of the :class:`~pystac.Asset` being extended."""
356
+
357
+ properties : Dict [str , Any ]
358
+ """The :class:`~pystac.Asset` fields, including extension properties."""
359
+
360
+ additional_read_properties : Optional [Iterable [Dict [str , Any ]]] = None
361
+ """If present, this will be a list containing 1 dictionary representing the
362
+ properties of the owning :class:`~pystac.Item`."""
363
+
335
364
def __init__ (self , asset : pystac .Asset ):
336
365
self .asset_href = asset .href
337
366
self .properties = asset .extra_fields
@@ -353,27 +382,29 @@ def migrate(
353
382
if version < "0.9" :
354
383
# Some sar fields became common_metadata
355
384
if (
356
- "sar: platform" in obj ["properties" ]
385
+ PREFIX + " platform" in obj ["properties" ]
357
386
and "platform" not in obj ["properties" ]
358
387
):
359
- obj ["properties" ]["platform" ] = obj ["properties" ]["sar: platform" ]
360
- del obj ["properties" ]["sar: platform" ]
388
+ obj ["properties" ]["platform" ] = obj ["properties" ][PREFIX + " platform" ]
389
+ del obj ["properties" ][PREFIX + " platform" ]
361
390
362
391
if (
363
- "sar: instrument" in obj ["properties" ]
392
+ PREFIX + " instrument" in obj ["properties" ]
364
393
and "instruments" not in obj ["properties" ]
365
394
):
366
- obj ["properties" ]["instruments" ] = [obj ["properties" ]["sar:instrument" ]]
367
- del obj ["properties" ]["sar:instrument" ]
395
+ obj ["properties" ]["instruments" ] = [
396
+ obj ["properties" ][PREFIX + "instrument" ]
397
+ ]
398
+ del obj ["properties" ][PREFIX + "instrument" ]
368
399
369
400
if (
370
- "sar: constellation" in obj ["properties" ]
401
+ PREFIX + " constellation" in obj ["properties" ]
371
402
and "constellation" not in obj ["properties" ]
372
403
):
373
404
obj ["properties" ]["constellation" ] = obj ["properties" ][
374
- "sar: constellation"
405
+ PREFIX + " constellation"
375
406
]
376
- del obj ["properties" ]["sar: constellation" ]
407
+ del obj ["properties" ][PREFIX + " constellation" ]
377
408
378
409
super ().migrate (obj , version , info )
379
410
0 commit comments