Python API

Import from pystac.extensions.sentinel1. Use Sentinel1Extension.ext() for Items and Sentinel1Extension.summaries() for Collections.

sentinel1

Read and write Sentinel-1 v0.2.0 Item properties and Collection summaries.

SENTINEL1_EXTENSION_HOOKS: ExtensionHooks = Sentinel1ExtensionHooks() module-attribute

SCHEMA_URI = 'https://stac-extensions.github.io/sentinel-1/v0.2.0/schema.json' module-attribute

Sentinel1Extension

Bases: Generic[T], PropertiesExtension, ExtensionManagementMixin[Item | Collection]

Extension API for the Sentinel-1 extension.

Source code in src/pystac/extensions/sentinel1.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
class Sentinel1Extension(
    Generic[T],
    PropertiesExtension,
    ExtensionManagementMixin[pystac.Item | pystac.Collection],
):
    """Extension API for the Sentinel-1 extension."""

    name: Literal["s1"] = "s1"

    # Preserve the public positional signature used by existing callers.
    def apply(  # noqa: PLR0913, PLR0917
        self,
        datatake_id: str | None = None,
        instrument_configuration_id: str | None = None,
        orbit_source: str | None = None,
        processing_datetime: datetime | None = None,
        product_identifier: str | None = None,
        product_timeliness: str | None = None,
        resolution: str | None = None,
        slice_number: str | None = None,
        total_slices: str | None = None,
        processing_level: str | None = None,
        shape: list[int] | None = None,
    ) -> None:
        """Set all fields in place, removing fields whose arguments are omitted.

        Deprecated fields remain available for compatibility with existing Items.
        Assignments are sequential; a shape error leaves earlier changes in place.

        Raises:
            ValueError: If shape has fewer than two elements, non-integers, or booleans.
        """
        self.datatake_id = datatake_id
        self.instrument_configuration_id = instrument_configuration_id
        self.orbit_source = orbit_source
        self.processing_datetime = processing_datetime
        self.product_identifier = product_identifier
        self.product_timeliness = product_timeliness
        self.resolution = resolution
        self.slice_number = slice_number
        self.total_slices = total_slices
        self.processing_level = processing_level
        self.shape = shape

    @property
    def datatake_id(self) -> str | None:
        """The datatake identifier as a string."""
        return self._get_property(DATATAKE_ID_PROP, str)

    @datatake_id.setter
    def datatake_id(self, value: str | None) -> None:
        self._set_property(DATATAKE_ID_PROP, value)

    @property
    def instrument_configuration_id(self) -> str | None:
        """The instrument configuration ID, stored as s1:instrument_configuration_ID."""
        return self._get_property(INSTRUMENT_CONFIGURATION_ID_PROP, str)

    @instrument_configuration_id.setter
    def instrument_configuration_id(self, value: str | None) -> None:
        self._set_property(INSTRUMENT_CONFIGURATION_ID_PROP, value)

    @property
    def orbit_source(self) -> str | None:
        """The orbit source, such as PREORB or RESORB."""
        return self._get_property(ORBIT_SOURCE_PROP, str)

    @orbit_source.setter
    def orbit_source(self, value: str | None) -> None:
        self._set_property(ORBIT_SOURCE_PROP, value)

    @property
    def processing_datetime(self) -> datetime | None:
        """The deprecated processing timestamp; prefer processing:datetime."""
        return map_opt(str_to_datetime, self._get_property(PROCESSING_DATETIME_PROP, str))

    @processing_datetime.setter
    def processing_datetime(self, value: datetime | None) -> None:
        self._set_property(PROCESSING_DATETIME_PROP, map_opt(datetime_to_str, value))

    @property
    def product_identifier(self) -> str | None:
        """The deprecated product identifier; prefer the Item ID or source links."""
        return self._get_property(PRODUCT_IDENTIFIER_PROP, str)

    @product_identifier.setter
    def product_identifier(self, value: str | None) -> None:
        self._set_property(PRODUCT_IDENTIFIER_PROP, value)

    @property
    def product_timeliness(self) -> str | None:
        """The deprecated timeliness; prefer product extension timeliness fields."""
        return self._get_property(PRODUCT_TIMELINESS_PROP, str)

    @product_timeliness.setter
    def product_timeliness(self, value: str | None) -> None:
        self._set_property(PRODUCT_TIMELINESS_PROP, value)

    @property
    def resolution(self) -> str | None:
        """The deprecated resolution class; prefer spatial or SAR resolution fields."""
        return self._get_property(RESOLUTION_PROP, str)

    @resolution.setter
    def resolution(self, value: str | None) -> None:
        self._set_property(RESOLUTION_PROP, value)

    @property
    def slice_number(self) -> str | None:
        """The slice number as a string."""
        return self._get_property(SLICE_NUMBER_PROP, str)

    @slice_number.setter
    def slice_number(self, value: str | None) -> None:
        self._set_property(SLICE_NUMBER_PROP, value)

    @property
    def total_slices(self) -> str | None:
        """The total number of slices as a string."""
        return self._get_property(TOTAL_SLICES_PROP, str)

    @total_slices.setter
    def total_slices(self, value: str | None) -> None:
        self._set_property(TOTAL_SLICES_PROP, value)

    @property
    def processing_level(self) -> str | None:
        """The deprecated processing level; prefer processing:level."""
        return self._get_property(PROCESSING_LEVEL_PROP, str)

    @processing_level.setter
    def processing_level(self, value: str | None) -> None:
        self._set_property(PROCESSING_LEVEL_PROP, value)

    @property
    def shape(self) -> list[int] | None:
        """The deprecated array dimensions; prefer proj:shape."""
        return self._get_property(SHAPE_PROP, list)

    @shape.setter
    def shape(self, value: list[int] | None) -> None:
        """Set or remove the deprecated shape field.

        Raises:
            ValueError: If shape has fewer than two elements, non-integers, or booleans.
        """
        self._set_property(SHAPE_PROP, _validate_shape(value))

    @classmethod
    def get_schema_uri(cls) -> str:
        """Return the upstream Sentinel-1 v0.2.0 schema identifier."""
        return SCHEMA_URI

    @classmethod
    def ext(cls, obj: T, add_if_missing: bool = False) -> Sentinel1Extension[T]:
        """Wrap an Item, optionally declaring the extension on it.

        Raises:
            pystac.ExtensionNotImplemented: If the extension is absent and not added.
            pystac.ExtensionTypeError: If the object is not an Item.
        """
        if isinstance(obj, pystac.Item):
            cls.ensure_has_extension(obj, add_if_missing)
            return cast("Sentinel1Extension[T]", ItemSentinel1Extension(obj))
        raise pystac.ExtensionTypeError(cls._ext_error_message(obj))

    @classmethod
    def summaries(
        cls, obj: pystac.Collection, add_if_missing: bool = False
    ) -> SummariesSentinel1Extension:
        """Wrap Collection summaries, optionally declaring the extension.

        Raises:
            pystac.ExtensionNotImplemented: If the extension is absent and not added.
        """
        cls.ensure_has_extension(obj, add_if_missing)
        return SummariesSentinel1Extension(obj)

datatake_id: str | None property writable

The datatake identifier as a string.

instrument_configuration_id: str | None property writable

The instrument configuration ID, stored as s1:instrument_configuration_ID.

orbit_source: str | None property writable

The orbit source, such as PREORB or RESORB.

processing_datetime: datetime | None property writable

The deprecated processing timestamp; prefer processing:datetime.

processing_level: str | None property writable

The deprecated processing level; prefer processing:level.

product_identifier: str | None property writable

The deprecated product identifier; prefer the Item ID or source links.

product_timeliness: str | None property writable

The deprecated timeliness; prefer product extension timeliness fields.

resolution: str | None property writable

The deprecated resolution class; prefer spatial or SAR resolution fields.

shape: list[int] | None property writable

The deprecated array dimensions; prefer proj:shape.

slice_number: str | None property writable

The slice number as a string.

total_slices: str | None property writable

The total number of slices as a string.

apply(datatake_id: str | None = None, instrument_configuration_id: str | None = None, orbit_source: str | None = None, processing_datetime: datetime | None = None, product_identifier: str | None = None, product_timeliness: str | None = None, resolution: str | None = None, slice_number: str | None = None, total_slices: str | None = None, processing_level: str | None = None, shape: list[int] | None = None) -> None

Set all fields in place, removing fields whose arguments are omitted.

Deprecated fields remain available for compatibility with existing Items. Assignments are sequential; a shape error leaves earlier changes in place.

Raises:
  • ValueError –

    If shape has fewer than two elements, non-integers, or booleans.

Source code in src/pystac/extensions/sentinel1.py
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
def apply(  # noqa: PLR0913, PLR0917
    self,
    datatake_id: str | None = None,
    instrument_configuration_id: str | None = None,
    orbit_source: str | None = None,
    processing_datetime: datetime | None = None,
    product_identifier: str | None = None,
    product_timeliness: str | None = None,
    resolution: str | None = None,
    slice_number: str | None = None,
    total_slices: str | None = None,
    processing_level: str | None = None,
    shape: list[int] | None = None,
) -> None:
    """Set all fields in place, removing fields whose arguments are omitted.

    Deprecated fields remain available for compatibility with existing Items.
    Assignments are sequential; a shape error leaves earlier changes in place.

    Raises:
        ValueError: If shape has fewer than two elements, non-integers, or booleans.
    """
    self.datatake_id = datatake_id
    self.instrument_configuration_id = instrument_configuration_id
    self.orbit_source = orbit_source
    self.processing_datetime = processing_datetime
    self.product_identifier = product_identifier
    self.product_timeliness = product_timeliness
    self.resolution = resolution
    self.slice_number = slice_number
    self.total_slices = total_slices
    self.processing_level = processing_level
    self.shape = shape

ext(obj: T, add_if_missing: bool = False) -> Sentinel1Extension[T] classmethod

Wrap an Item, optionally declaring the extension on it.

Raises:
  • ExtensionNotImplemented –

    If the extension is absent and not added.

  • ExtensionTypeError –

    If the object is not an Item.

Source code in src/pystac/extensions/sentinel1.py
224
225
226
227
228
229
230
231
232
233
234
235
@classmethod
def ext(cls, obj: T, add_if_missing: bool = False) -> Sentinel1Extension[T]:
    """Wrap an Item, optionally declaring the extension on it.

    Raises:
        pystac.ExtensionNotImplemented: If the extension is absent and not added.
        pystac.ExtensionTypeError: If the object is not an Item.
    """
    if isinstance(obj, pystac.Item):
        cls.ensure_has_extension(obj, add_if_missing)
        return cast("Sentinel1Extension[T]", ItemSentinel1Extension(obj))
    raise pystac.ExtensionTypeError(cls._ext_error_message(obj))

get_schema_uri() -> str classmethod

Return the upstream Sentinel-1 v0.2.0 schema identifier.

Source code in src/pystac/extensions/sentinel1.py
219
220
221
222
@classmethod
def get_schema_uri(cls) -> str:
    """Return the upstream Sentinel-1 v0.2.0 schema identifier."""
    return SCHEMA_URI

summaries(obj: pystac.Collection, add_if_missing: bool = False) -> SummariesSentinel1Extension classmethod

Wrap Collection summaries, optionally declaring the extension.

Raises:
  • ExtensionNotImplemented –

    If the extension is absent and not added.

Source code in src/pystac/extensions/sentinel1.py
237
238
239
240
241
242
243
244
245
246
247
@classmethod
def summaries(
    cls, obj: pystac.Collection, add_if_missing: bool = False
) -> SummariesSentinel1Extension:
    """Wrap Collection summaries, optionally declaring the extension.

    Raises:
        pystac.ExtensionNotImplemented: If the extension is absent and not added.
    """
    cls.ensure_has_extension(obj, add_if_missing)
    return SummariesSentinel1Extension(obj)

ItemSentinel1Extension

Bases: Sentinel1Extension[Item]

Store Sentinel-1 metadata directly in a PySTAC Item's properties.

Attributes:
  • item (Item) –

    The Item whose properties are read and mutated by this wrapper.

Source code in src/pystac/extensions/sentinel1.py
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
class ItemSentinel1Extension(Sentinel1Extension[pystac.Item]):
    """Store Sentinel-1 metadata directly in a PySTAC Item's properties.

    Attributes:
        item: The Item whose properties are read and mutated by this wrapper.
    """

    item: pystac.Item

    def __init__(self, item: pystac.Item) -> None:
        self.item = item
        self.properties = item.properties

    def __repr__(self) -> str:
        return f"<ItemSentinel1Extension Item id={self.item.id}>"

SummariesSentinel1Extension

Bases: SummariesExtension

Read and replace Sentinel-1 summaries without aggregating Items.

Source code in src/pystac/extensions/sentinel1.py
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
class SummariesSentinel1Extension(SummariesExtension):
    """Read and replace Sentinel-1 summaries without aggregating Items."""

    @property
    def datatake_id(self) -> list[str] | None:
        """The list of datatake id values, or None when absent."""
        return self.summaries.get_list(DATATAKE_ID_PROP)

    @datatake_id.setter
    def datatake_id(self, value: list[str] | None) -> None:
        self._set_summary(DATATAKE_ID_PROP, value)

    @property
    def instrument_configuration_id(self) -> list[str] | None:
        """The list of instrument configuration id values, or None when absent."""
        return self.summaries.get_list(INSTRUMENT_CONFIGURATION_ID_PROP)

    @instrument_configuration_id.setter
    def instrument_configuration_id(self, value: list[str] | None) -> None:
        self._set_summary(INSTRUMENT_CONFIGURATION_ID_PROP, value)

    @property
    def orbit_source(self) -> list[str] | None:
        """The list of orbit source values, or None when absent."""
        return self.summaries.get_list(ORBIT_SOURCE_PROP)

    @orbit_source.setter
    def orbit_source(self, value: list[str] | None) -> None:
        self._set_summary(ORBIT_SOURCE_PROP, value)

    @property
    def processing_datetime(self) -> RangeSummary[datetime] | None:
        """The processing datetime range, or None when absent."""
        return map_opt(
            lambda summary: RangeSummary(
                str_to_datetime(summary.minimum), str_to_datetime(summary.maximum)
            ),
            self.summaries.get_range(PROCESSING_DATETIME_PROP),
        )

    @processing_datetime.setter
    def processing_datetime(self, value: RangeSummary[datetime] | None) -> None:
        self._set_summary(
            PROCESSING_DATETIME_PROP,
            map_opt(
                lambda summary: RangeSummary(
                    datetime_to_str(summary.minimum), datetime_to_str(summary.maximum)
                ),
                value,
            ),
        )

    @property
    def product_identifier(self) -> list[str] | None:
        """The list of product identifier values, or None when absent."""
        return self.summaries.get_list(PRODUCT_IDENTIFIER_PROP)

    @product_identifier.setter
    def product_identifier(self, value: list[str] | None) -> None:
        self._set_summary(PRODUCT_IDENTIFIER_PROP, value)

    @property
    def product_timeliness(self) -> list[str] | None:
        """The list of product timeliness values, or None when absent."""
        return self.summaries.get_list(PRODUCT_TIMELINESS_PROP)

    @product_timeliness.setter
    def product_timeliness(self, value: list[str] | None) -> None:
        self._set_summary(PRODUCT_TIMELINESS_PROP, value)

    @property
    def resolution(self) -> list[str] | None:
        """The list of resolution values, or None when absent."""
        return self.summaries.get_list(RESOLUTION_PROP)

    @resolution.setter
    def resolution(self, value: list[str] | None) -> None:
        self._set_summary(RESOLUTION_PROP, value)

    @property
    def slice_number(self) -> list[str] | None:
        """The list of slice number values, or None when absent."""
        return self.summaries.get_list(SLICE_NUMBER_PROP)

    @slice_number.setter
    def slice_number(self, value: list[str] | None) -> None:
        self._set_summary(SLICE_NUMBER_PROP, value)

    @property
    def total_slices(self) -> list[str] | None:
        """The list of total slices values, or None when absent."""
        return self.summaries.get_list(TOTAL_SLICES_PROP)

    @total_slices.setter
    def total_slices(self, value: list[str] | None) -> None:
        self._set_summary(TOTAL_SLICES_PROP, value)

    @property
    def processing_level(self) -> list[str] | None:
        """The list of processing level values, or None when absent."""
        return self.summaries.get_list(PROCESSING_LEVEL_PROP)

    @processing_level.setter
    def processing_level(self, value: list[str] | None) -> None:
        self._set_summary(PROCESSING_LEVEL_PROP, value)

    @property
    def shape(self) -> list[list[int]] | None:
        """The list of shape values, or None when absent."""
        return self.summaries.get_list(SHAPE_PROP)

    @shape.setter
    def shape(self, value: list[list[int]] | None) -> None:
        self._set_summary(SHAPE_PROP, value)

datatake_id: list[str] | None property writable

The list of datatake id values, or None when absent.

instrument_configuration_id: list[str] | None property writable

The list of instrument configuration id values, or None when absent.

orbit_source: list[str] | None property writable

The list of orbit source values, or None when absent.

processing_datetime: RangeSummary[datetime] | None property writable

The processing datetime range, or None when absent.

processing_level: list[str] | None property writable

The list of processing level values, or None when absent.

product_identifier: list[str] | None property writable

The list of product identifier values, or None when absent.

product_timeliness: list[str] | None property writable

The list of product timeliness values, or None when absent.

resolution: list[str] | None property writable

The list of resolution values, or None when absent.

shape: list[list[int]] | None property writable

The list of shape values, or None when absent.

slice_number: list[str] | None property writable

The list of slice number values, or None when absent.

total_slices: list[str] | None property writable

The list of total slices values, or None when absent.

Sentinel1ExtensionHooks

Bases: ExtensionHooks

Describe Sentinel-1 identifiers and supported objects for PySTAC hooks.

Source code in src/pystac/extensions/sentinel1.py
383
384
385
386
387
388
389
390
391
class Sentinel1ExtensionHooks(ExtensionHooks):
    """Describe Sentinel-1 identifiers and supported objects for PySTAC hooks."""

    schema_uri: str = SCHEMA_URI
    prev_extension_ids: ClassVar[set[str]] = {"sentinel-1"}
    stac_object_types: ClassVar[set[pystac.STACObjectType]] = {
        pystac.STACObjectType.ITEM,
        pystac.STACObjectType.COLLECTION,
    }