Source code for pystac.extensions.eo

from pystac import (STACError, Extensions)
from pystac.item import Item
from pystac.extensions.base import (ItemExtension, ExtensionDefinition, ExtendedObject)


[docs]class EOItemExt(ItemExtension): """EOItemExt is the extension of the Item in the eo extension which represents a snapshot of the earth for a single date and time. Args: item (Item): The item to be extended. Attributes: item (Item): The Item that is being extended. Note: Using EOItemExt to directly wrap an item will add the 'eo' extension ID to the item's stac_extensions. """ def __init__(self, item): if item.stac_extensions is None: item.stac_extensions = [Extensions.EO] elif Extensions.EO not in item.stac_extensions: item.stac_extensions.append(Extensions.EO) self.item = item
[docs] def apply(self, gsd, bands, cloud_cover=None): """Applies label extension properties to the extended Item. Args: gsd (float): The Ground Sample Distance of the sensor bands (List[Band]): a list of :class:`~pystac.Band` objects that represent the available bands. cloud_cover (float or None): The estimate of cloud cover as a percentage (0-100) of the entire scene. If not available the field should not be provided. """ self.gsd = gsd self.bands = bands self.cloud_cover = cloud_cover
@property def gsd(self): """Get or sets the Ground Sample Distance at the sensor. Returns: [float] """ return self.item.properties.get('eo:gsd') @gsd.setter def gsd(self, v): self.item.properties['eo:gsd'] = v @property def bands(self): """Get or sets a list of :class:`~pystac.Band` objects that represent the available bands. Returns: [List[Band]] """ bands = self.item.properties.get('eo:bands') if bands is None: raise STACError("Missing required field 'eo:bands' in item properties") return [Band(b) for b in bands] @bands.setter def bands(self, v): self.item.properties['eo:bands'] = [b.to_dict() for b in v] @property def cloud_cover(self): """Get or sets the estimate of cloud cover as a percentage (0-100) of the entire scene. If not available the field should not be provided. Returns: [float or None] """ return self.item.properties.get('eo:cloud_cover') @cloud_cover.setter def cloud_cover(self, v): self.item.properties['eo:cloud_cover'] = v def __repr__(self): return '<EOItemExt Item id={}>'.format(self.item.id)
[docs] def get_asset_bands(self, asset): """Gets the bands for the given asset. Args: asset [Asset]: The asset from the associated item to get the bands of. Returns: [List[Band] or None]: A list of Band objects associated with the asset, or None if the asset doesn't exist or does not contain band information. """ if 'eo:bands' not in asset.properties: return None result = [] band_length = len(self.bands) for band_idx in asset.properties['eo:bands']: if band_idx >= band_length: raise STACError("Item {} contains assets with band indexes out of range! " "Band index {} is greater than the number of bands " "for the item ({})".format(self.item.id, band_idx, band_length)) result.append(self.bands[band_idx]) return result
[docs] def set_asset_bands(self, asset, band_names): """Sets the band information for an asset of this item. Args: asset [Asset]: The asset from the associated item to set the bands for. band_names (List[str]): List of band names to assign to the asset. These names must reference names in the item's bands property. """ band_idxs = [i for i, b in enumerate(self.bands) if b.name in band_names] if len(set(band_idxs)) != len(set(band_names)): missing_band_names = set(band_names) - set([self.bands[i] for i in band_idxs]) raise KeyError("Bands not found in item's bands: {}".format(','.join( map(lambda x: "'{}'".format(x), missing_band_names)))) asset.properties['eo:bands'] = band_idxs
@classmethod def _object_links(cls): return []
[docs] @classmethod def from_item(cls, item): return cls(item)
[docs]class Band: """Represents Band information attached to an Item that implements the eo extension. Use Band.create to create a new Band. """ def __init__(self, properties): self.properties = properties
[docs] def apply(self, name, common_name=None, description=None, center_wavelength=None, full_width_half_max=None): """ Sets the properties for this Band. Args: name (str): The name of the band (e.g., "B01", "B02", "B1", "B5", "QA"). common_name (str): The name commonly used to refer to the band to make it easier to search for bands across instruments. See the `list of accepted common names <https://github.com/radiantearth/stac-spec/tree/v0.8.1/extensions/eo#common-band-names>`_. description (str): Description to fully explain the band. center_wavelength (float): The center wavelength of the band, in micrometers (μm). full_width_half_max (float): Full width at half maximum (FWHM). The width of the band, as measured at half the maximum transmission, in micrometers (μm). """ self.name = name self.common_name = common_name self.description = description self.center_wavelength = center_wavelength self.full_width_half_max = full_width_half_max
[docs] @classmethod def create(cls, name, common_name=None, description=None, center_wavelength=None, full_width_half_max=None): """ Creates a new band. Args: name (str): The name of the band (e.g., "B01", "B02", "B1", "B5", "QA"). common_name (str): The name commonly used to refer to the band to make it easier to search for bands across instruments. See the `list of accepted common names <https://github.com/radiantearth/stac-spec/tree/v0.8.1/extensions/eo#common-band-names>`_. description (str): Description to fully explain the band. center_wavelength (float): The center wavelength of the band, in micrometers (μm). full_width_half_max (float): Full width at half maximum (FWHM). The width of the band, as measured at half the maximum transmission, in micrometers (μm). """ b = cls({}) b.apply(name=name, common_name=common_name, description=description, center_wavelength=center_wavelength, full_width_half_max=full_width_half_max) return b
@property def name(self): """Get or sets the name of the band (e.g., "B01", "B02", "B1", "B5", "QA"). Returns: [str] """ return self.properties.get('name') @name.setter def name(self, v): self.properties['name'] = v @property def common_name(self): """Get or sets the name commonly used to refer to the band to make it easier to search for bands across instruments. See the `list of accepted common names <https://github.com/radiantearth/stac-spec/tree/v0.8.1/extensions/eo#common-band-names>`_. Returns: [str] """ return self.properties.get('common_name') @common_name.setter def common_name(self, v): if v is not None: self.properties['common_name'] = v else: self.properties.pop('common_name', None) @property def description(self): """Get or sets the description to fully explain the band. CommonMark 0.29 syntax MAY be used for rich text representation. Returns: [str] """ return self.properties.get('description') @description.setter def description(self, v): if v is not None: self.properties['description'] = v else: self.properties.pop('description', None) @property def center_wavelength(self): """Get or sets the center wavelength of the band, in micrometers (μm). Returns: [float] """ return self.properties.get('center_wavelength') @center_wavelength.setter def center_wavelength(self, v): if v is not None: self.properties['center_wavelength'] = v else: self.properties.pop('center_wavelength', None) @property def full_width_half_max(self): """Get or sets the full width at half maximum (FWHM). The width of the band, as measured at half the maximum transmission, in micrometers (μm). Returns: [float] """ return self.properties.get('full_width_half_max') @full_width_half_max.setter def full_width_half_max(self, v): if v is not None: self.properties['full_width_half_max'] = v else: self.properties.pop('full_width_half_max', None) def __repr__(self): return '<Band name={}>'.format(self.name)
[docs] def to_dict(self): """Returns the dictionary representing the JSON of this Band. Returns: dict: The wrapped dict of the Band that can be written out as JSON. """ return self.properties
[docs] @staticmethod def band_range(common_name): """Gets the band range for a common band name. Args: common_name (str): The common band name. Must be one of the `list of accepted common names <https://github.com/radiantearth/stac-spec/tree/v0.8.1/extensions/eo#common-band-names>`_. Returns: Tuple[float, float] or None: The band range for this name as (min, max), or None if this is not a recognized common name. """ # noqa E501 name_to_range = { 'coastal': (0.40, 0.45), 'blue': (0.45, 0.50), 'green': (0.50, 0.60), 'red': (0.60, 0.70), 'yellow': (0.58, 0.62), 'pan': (0.50, 0.70), 'rededge': (0.70, 0.75), 'nir': (0.75, 1.00), 'nir08': (0.75, 0.90), 'nir09': (0.85, 1.05), 'cirrus': (1.35, 1.40), 'swir16': (1.55, 1.75), 'swir22': (2.10, 2.30), 'lwir': (10.5, 12.5), 'lwir11': (10.5, 11.5), 'lwir12': (11.5, 12.5) } return name_to_range.get(common_name)
[docs] @staticmethod def band_description(common_name): """Returns a description of the band for one with a common name. Args: common_name (str): The common band name. Must be one of the `list of accepted common names <https://github.com/radiantearth/stac-spec/tree/v0.8.1/extensions/eo#common-band-names>`_. Returns: str or None: If a recognized common name, returns a description including the band range. Otherwise returns None. """ # noqa E501 r = Band.band_range(common_name) if r is not None: r = "Common name: {}, Range: {} to {}".format(common_name, r[0], r[1]) return r
EO_EXTENSION_DEFINITION = ExtensionDefinition(Extensions.EO, [ExtendedObject(Item, EOItemExt)])