Source code for eoreader.bands.band_names

from typing import Union

from sertit import misc, types

from eoreader.exceptions import InvalidTypeError
from eoreader.stac import StacCommonNames


[docs] class BandNames(misc.ListEnum): """Super class for band names, **do not use it**."""
[docs] @classmethod def from_list(cls, name_list: Union[list, str]) -> list: """ Get the band enums from list of band names .. code-block:: python >>> SarBandNames.from_list("VV") [<SarBandNames.VV: 'VV'>] Args: name_list (Union[list, str]): List of names Returns: list: List of enums """ name_list = types.make_iterable(name_list) try: band_names = [cls(name) for name in name_list] except ValueError as ex: raise InvalidTypeError( f"Band names ({name_list}) should be chosen among: {cls.list_names()}" ) from ex return band_names
[docs] @classmethod def to_value_list(cls, name_list: list = None) -> list: """ Get a list from the values of the bands .. code-block:: python >>> SarBandNames.to_name_list([SarBandNames.HV_DSPK, SarBandNames.VV]) ['HV_DSPK', 'VV'] >>> SarBandNames.to_name_list() ['VV', 'VV_DSPK', 'HH', 'HH_DSPK', 'VH', 'VH_DSPK', 'HV', 'HV_DSPK'] Args: name_list (list): List of band names Returns: list: List of band values """ if name_list: out_list = [] for key in name_list: if isinstance(key, str): out_list.append(getattr(cls, key).value) elif isinstance(key, cls): out_list.append(key.value) else: raise InvalidTypeError( "The list should either contain strings or BandNames" ) else: out_list = cls.list_values() return out_list
def __gt__(self, other) -> bool: """ Overload greater than for BandNames -> compare the names in string. Args: other (BandNames): Other products to be compared with this one Returns: bool: True if this product has been acquired after the other """ try: return self.name > other.name except AttributeError: return str(self) > str(other) def __ge__(self, other) -> bool: """ Overload greater than for BandNames -> compare the names in string. Args: other (Product): Other products to be compared with this one Returns: bool: True if this product has been acquired after or in the same time as the other """ try: return self.name >= other.name except AttributeError: return str(self) >= str(other) def __le__(self, other) -> bool: """ Overload greater than for BandNames -> compare the names in string. Args: other (BandNames): Other products to be compared with this one Returns: bool: True if this product has been acquired before or in the same time as the other """ try: return self.name <= other.name except AttributeError: return str(self) <= str(other) def __lt__(self, other) -> bool: """ Overload greater than for BandNames -> compare the names in string. Args: other (BandNames): Other products to be compared with this one Returns: bool: True if this product has been acquired before the other """ try: return self.name < other.name except AttributeError: return str(self) < str(other)
[docs] class SpectralBandNames(BandNames): """ This class aims to regroup equivalent bands under the same nomenclature. Each product will set their band number in regard to their corresponding name. **Note**: The mapping is based on Sentinel-2 spectral bands. More information can be retrieved here: - `Overall comparison <http://blog.imagico.de/wp-content/uploads/2016/11/sat_spectra_full4a.png>`_ - L8/S2: - `Resource 1 <https://reader.elsevier.com/reader/sd/pii/S0034425718301883>`_ - `Resource 2 <https://landsat.gsfc.nasa.gov/wp-content/uploads/2015/06/Landsat.v.Sentinel-2.png>`_ - `L4/L5, MSS-TM <https://landsat.gsfc.nasa.gov/the-multispectral-scanner-system/>`_ - `All Landsats <https://landsat.gsfc.nasa.gov/wp-content/uploads/2016/10/all_Landsat_bands.png>`_ - `S2 <https://discovery.creodias.eu/dataset/72181b08-a577-4d55-8ece-d8485167beb7/resource/d8f5dd92-b35c-46ee-98a2-0879dad03fce/download/res_band_s2_1.png>`_ - `S3 OLCI <https://discovery.creodias.eu/dataset/a0960a9b-c9c4-46db-bca5-ec79d0dda32b/resource/de8300a4-08cd-41aa-96ec-d9813115cc08/download/s3_res_band_ol.png>`_ - `S3 SLSTR <https://discovery.creodias.eu/dataset/ea8f247e-d193-4368-8cf6-8687a03a5306/resource/8e5c485a-d832-42be-ad9c-af500b468f29/download/s3_slcs.png>`_ - `Index consistency <https://www.indexdatabase.de/>`_ This classification allows index computation and algorithms to run without knowing the band nb of every satellite. If None, then the band does not exist for the satellite. """ CA = "COASTAL_AEROSOL" """Coastal aerosol""" BLUE = "BLUE" """Blue""" GREEN = "GREEN" """Green""" YELLOW = "YELLOW" """Yellow""" RED = "RED" """Red""" VRE_1 = "VEGETATION_RED_EDGE_1" """Vegetation red edge, Band 1""" VRE_2 = "VEGETATION_RED_EDGE_2" """Vegetation red edge, Band 2""" VRE_3 = "VEGETATION_RED_EDGE_3" """Vegetation red edge, Band 3""" NIR = "NIR" """NIR (B8 for Sentinel-2)""" NARROW_NIR = "NARROW_NIR" """Narrow NIR, spectrally narrow NIR band, equivalent to B8A (gsd 20m) for Sentinel-2 products, equivalent to NIR band for other products""" WV = "WATER_VAPOUR" """Water vapour""" SWIR_CIRRUS = "SWIR_CIRRUS" """SWIR Cirrus""" SWIR_1 = "SWIR_1" """SWIR, Band 1""" SWIR_2 = "SWIR_2" """SWIR, Band 2""" TIR_1 = "THERMAL_IR_1" """Thermal IR, Band 1""" TIR_2 = "THERMAL_IR_2" """Thermal IR, Band 2""" PAN = "PANCHROMATIC" """Panchromatic""" # SLSTR additional band names S7 = "S7" """ S7 """ F1 = "F1" """ F1 """ F2 = "F2" """ F2 """ # S3-OLCI additional band names Oa01 = "Oa01" """ Oa01 """ Oa02 = "Oa02" """ Oa02 """ Oa09 = "Oa09" """ Oa09 """ Oa10 = "Oa10" """ Oa10 """ Oa13 = "Oa13" """ Oa13 """ Oa14 = "Oa14" """ Oa14 """ Oa15 = "Oa15" """ Oa15 """ Oa18 = "Oa18" """ Oa18 """ Oa19 = "Oa19" """ Oa01 """ Oa21 = "Oa21" """ Oa01 """ # -- PlanetScope PSB.SD instrument additional band -- GREEN_1 = "GREEN_I" """ GREEN I """ # old alias, to be deprecated GREEN1 = "GREEN_I" """ GREEN I """
[docs] @classmethod def stac_to_eoreader(cls, common_name: str, name: str) -> "SpectralBandNames": """ Convert STAC common names or name to EOReader bands Args: common_name (str): STAC common name name (str): STAC name Returns: SpectralBandNames: EOReader name """ # Try directly from raw name (especially for Sentinel-3 raw bands etc.) try: return cls.from_value(name) except ValueError: eoreader_name = None stac_common_name = StacCommonNames.from_value(common_name) for key, val in EOREADER_STAC_MAP.items(): if val == stac_common_name: eoreader_name = key break return eoreader_name
[docs] @classmethod def eoreader_to_stac(cls, eoreader_name: "SpectralBandNames") -> StacCommonNames: """ Convert EOReader bands to STAC common names Args: eoreader_name (SpectralBandNames): EOReader name Returns: StacCommonNames: STAC common name """ return EOREADER_STAC_MAP.get(eoreader_name, "")
# -- SPECTRAL BANDS -- CA = SpectralBandNames.CA # Coastal aerosol BLUE = SpectralBandNames.BLUE GREEN = SpectralBandNames.GREEN YELLOW = SpectralBandNames.YELLOW RED = SpectralBandNames.RED VRE_1 = SpectralBandNames.VRE_1 VRE_2 = SpectralBandNames.VRE_2 VRE_3 = SpectralBandNames.VRE_3 NIR = SpectralBandNames.NIR NARROW_NIR = SpectralBandNames.NARROW_NIR WV = SpectralBandNames.WV # Water vapour SWIR_CIRRUS = SpectralBandNames.SWIR_CIRRUS # Spectral band based on cirrus SWIR_1 = SpectralBandNames.SWIR_1 SWIR_2 = SpectralBandNames.SWIR_2 TIR_1 = SpectralBandNames.TIR_1 TIR_2 = SpectralBandNames.TIR_2 PAN = SpectralBandNames.PAN # -- S3-SLSTR Additional bands -- S7 = SpectralBandNames.S7 F1 = SpectralBandNames.F1 F2 = SpectralBandNames.F2 # -- S3-OCLI Additional bands -- Oa01 = SpectralBandNames.Oa01 Oa02 = SpectralBandNames.Oa02 Oa09 = SpectralBandNames.Oa09 Oa10 = SpectralBandNames.Oa10 Oa13 = SpectralBandNames.Oa13 Oa14 = SpectralBandNames.Oa14 Oa15 = SpectralBandNames.Oa15 Oa18 = SpectralBandNames.Oa18 Oa19 = SpectralBandNames.Oa19 Oa21 = SpectralBandNames.Oa21 # -- PlanetScope PSB.SD instrument additional band -- GREEN_1 = SpectralBandNames.GREEN_1 GREEN1 = SpectralBandNames.GREEN_1 # To be deprecated EOREADER_STAC_MAP = { CA: StacCommonNames.COASTAL, BLUE: StacCommonNames.BLUE, GREEN: StacCommonNames.GREEN, RED: StacCommonNames.RED, YELLOW: StacCommonNames.YELLOW, PAN: StacCommonNames.PAN, VRE_1: StacCommonNames.RE, VRE_2: StacCommonNames.RE, VRE_3: StacCommonNames.RE, NIR: StacCommonNames.NIR, NARROW_NIR: StacCommonNames.NIR08, WV: StacCommonNames.NIR09, SWIR_CIRRUS: StacCommonNames.CIRRUS, SWIR_1: StacCommonNames.SWIR16, SWIR_2: StacCommonNames.SWIR22, TIR_1: StacCommonNames.LWIR11, TIR_2: StacCommonNames.LWIR12, }
[docs] class SarBandNames(BandNames): """SAR Band names""" VV = "VV" """ Vertical Transmit-Vertical Receive Polarisation """ VV_DSPK = "VV_DSPK" """ Vertical Transmit-Vertical Receive Polarisation (Despeckled) """ HH = "HH" """ Horizontal Transmit-Horizontal Receive Polarisation """ HH_DSPK = "HH_DSPK" """ Horizontal Transmit-Horizontal Receive Polarisation (Despeckled) """ VH = "VH" """ Vertical Transmit-Horizontal Receive Polarisation """ VH_DSPK = "VH_DSPK" """ Vertical Transmit-Horizontal Receive Polarisation (Despeckled) """ HV = "HV" """ Horizontal Transmit-Vertical Receive Polarisation """ HV_DSPK = "HV_DSPK" """ Horizontal Transmit-Vertical Receive Polarisation (Despeckled) """ RH = "RH" """ Compact polarization: right circular transmit, horizontal receive """ RH_DSPK = "RH_DSPK" """ Compact polarization: right circular transmit, horizontal receive """ RV = "RV" """ Compact polarization: right circular transmit, vertical receive (Despeckled) """ RV_DSPK = "RV_DSPK" """ Compact polarization: right circular transmit, horizontal receive (Despeckled) """
[docs] @classmethod def corresponding_despeckle(cls, band: "SarBandNames"): """ Corresponding despeckled band. .. code-block:: python >>> SarBandNames.corresponding_despeckle(SarBandNames.VV) <SarBandNames.VV_DSPK: 'VV_DSPK'> >>> SarBandNames.corresponding_despeckle(SarBandNames.VV_DSPK) <SarBandNames.VV_DSPK: 'VV_DSPK'> Args: band (SarBandNames): Noisy (speckle) band Returns: SarBandNames: Despeckled band """ if cls.is_despeckle(band): dspk = band else: dspk = cls.from_value(f"{band.name}_DSPK") return dspk
[docs] @classmethod def corresponding_speckle(cls, band: "SarBandNames"): """ Corresponding speckle (noisy) band. .. code-block:: python >>> SarBandNames.corresponding_speckle(SarBandNames.VV) <SarBandNames.VV: 'VV'> >>> SarBandNames.corresponding_speckle(SarBandNames.VV_DSPK) <SarBandNames.VV: 'VV'> Args: band (SarBandNames): Noisy (speckle) band Returns: SarBandNames: Despeckled band """ return cls.from_value(f"{band.name[:2]}")
[docs] @classmethod def is_despeckle(cls, band: "SarBandNames"): """ Returns True if the band corresponds to a despeckled one. .. code-block:: python >>> SarBandNames.is_despeckle(SarBandNames.VV) False >>> SarBandNames.is_despeckle(SarBandNames.VV_DSPK) True Args: band (SarBandNames): Band to test Returns: SarBandNames: Despeckled band """ return "DSPK" in band.name
[docs] @classmethod def speckle_list(cls): return [band for band in cls if not cls.is_despeckle(band)]
VV = SarBandNames.VV VV_DSPK = SarBandNames.VV_DSPK HH = SarBandNames.HH HH_DSPK = SarBandNames.HH_DSPK VH = SarBandNames.VH VH_DSPK = SarBandNames.VH_DSPK HV = SarBandNames.HV HV_DSPK = SarBandNames.HV_DSPK RH = SarBandNames.RH RH_DSPK = SarBandNames.RH_DSPK RV = SarBandNames.RV RV_DSPK = SarBandNames.RV_DSPK
[docs] class CloudsBandNames(BandNames): """Clouds Band names""" RAW_CLOUDS = "RAW CLOUDS" """ Raw cloud raster (can be either QA raster, rasterized cloud vectors...) """ CLOUDS = "CLOUDS" """ Binary mask of clouds (High confidence) """ SHADOWS = "SHADOWS" """ Binary mask of shadows (High confidence) """ CIRRUS = "CIRRUS" """ Binary mask of cirrus (High confidence) """ ALL_CLOUDS = "ALL CLOUDS" """ All clouds (Including all high confidence clouds, shadows and cirrus) """
RAW_CLOUDS = CloudsBandNames.RAW_CLOUDS CLOUDS = CloudsBandNames.CLOUDS SHADOWS = CloudsBandNames.SHADOWS CIRRUS = CloudsBandNames.CIRRUS # Cirrus detected ALL_CLOUDS = CloudsBandNames.ALL_CLOUDS
[docs] class DemBandNames(BandNames): """DEM Band names""" DEM = "DEM" """ DEM """ SLOPE = "SLOPE" """ Slope """ HILLSHADE = "HILLSHADE" """ Hillshade """
DEM = DemBandNames.DEM SLOPE = DemBandNames.SLOPE HILLSHADE = DemBandNames.HILLSHADE