<filename>geowombat/core/properties.py<gh_stars>0
from pathlib import Path
from collections import namedtuple

from .util import n_rows_cols

import pandas as pd
import geopandas as gpd
from rasterio.coords import BoundingBox
from affine import Affine
import shapely
from shapely.geometry import Polygon

try:
    from shapely import speedups
    speedups.enable()
except:
    pass


WavelengthsPan = namedtuple('WavelengthsPan', 'pan')
WavelengthsBGR = namedtuple('WavelengthsBGR', 'blue green red')
WavelengthsRGB = namedtuple('WavelengthsRGB', 'red green blue')
WavelengthsBGRN = namedtuple('WavelengthsBGRN', 'blue green red nir')
WavelengthsRGBN = namedtuple('WavelengthsRGBN', 'red green blue nir')
WavelengthsL57 = namedtuple('WavelengthsL57', 'blue green red nir swir1 swir2')
WavelengthsL57Thermal = namedtuple('WavelengthsL57Thermal', 'blue green red nir swir1 thermal swir2')
WavelengthsL57Pan = namedtuple('WavelengthsL57Pan', 'blue green red nir swir1 swir2 pan')
WavelengthsL8 = namedtuple('WavelengthsL8', 'coastal blue green red nir swir1 swir2 cirrus')
WavelengthsL8Thermal = namedtuple('WavelengthsL8Thermal', 'coastal blue green red nir swir1 swir2 cirrus tirs1 tirs2')
WavelengthsS2 = namedtuple('WavelengthsS2', 'blue green red nir1 nir2 nir3 nir rededge swir1 swir2')
WavelengthsS2Full = namedtuple('WavelengthsS2', 'coastal blue green red nir1 nir2 nir3 nir rededge water cirrus swir1 swir2')
WavelengthsS220 = namedtuple('WavelengthsS220', 'nir1 nir2 nir3 rededge swir1 swir2')
WavelengthsS2Cloudless = namedtuple('WavelengthsS2Cloudless', 'coastal blue red nir1 nir rededge water cirrus swir1 swir2')


class DataProperties(object):

    def __init__(self):
        self._footprint_grid = None

    @property
    def avail_sensors(self):
        """Get supported sensors"""
        return sorted(list(self.wavelengths.keys()))

    @property
    def altitude(self):

        """
        Get satellite altitudes (in km)
        """

        return dict(aster=705,
                    l5=705,
                    l7=705,
                    l8=705,
                    s2=786,
                    ps=475,
                    qb=482,
                    ik=681,
                    wv3=617)

    @property
    def central_um(self):

        """
        Get a dictionary of central wavelengths (in micrometers)
        """

        return dict(l5=WavelengthsL57(blue=0.485,
                                      green=0.56,
                                      red=0.66,
                                      nir=0.835,
                                      swir1=1.65,
                                      swir2=2.22),
                    l7=WavelengthsL57(blue=0.485,
                                      green=0.56,
                                      red=0.66,
                                      nir=0.835,
                                      swir1=1.65,
                                      swir2=2.22),
                    l7th=WavelengthsL57Thermal(blue=0.485,
                                               green=0.56,
                                               red=0.66,
                                               nir=0.835,
                                               swir1=1.65,
                                               thermal=11.45,
                                               swir2=2.22),
                    l7mspan=WavelengthsL57Pan(blue=0.485,
                                              green=0.56,
                                              red=0.66,
                                              nir=0.835,
                                              swir1=1.65,
                                              swir2=2.22,
                                              pan=0.71),
                    l7pan=WavelengthsPan(pan=0.71),
                    l8=WavelengthsL8(coastal=0.44,
                                     blue=0.48,
                                     green=0.56,
                                     red=0.655,
                                     nir=0.865,
                                     swir1=1.61,
                                     swir2=2.2,
                                     cirrus=1.37),
                    l8l7=WavelengthsL57(blue=0.48,
                                        green=0.56,
                                        red=0.655,
                                        nir=0.865,
                                        swir1=1.61,
                                        swir2=2.2),
                    l8l7mspan=WavelengthsL57Pan(blue=0.48,
                                                green=0.56,
                                                red=0.655,
                                                nir=0.865,
                                                swir1=1.61,
                                                swir2=2.2,
                                                pan=0.59),
                    l8pan=WavelengthsPan(pan=0.59),
                    l5bgrn=WavelengthsBGRN(blue=0.485,
                                           green=0.56,
                                           red=0.66,
                                           nir=0.835),
                    l7bgrn=WavelengthsBGRN(blue=0.485,
                                           green=0.56,
                                           red=0.66,
                                           nir=0.835),
                    l8bgrn=WavelengthsBGRN(blue=0.48,
                                           green=0.56,
                                           red=0.655,
                                           nir=0.865),
                    s2=WavelengthsS2(blue=0.4924,
                                     green=0.5598,
                                     red=0.6646,
                                     nir1=0.7041,
                                     nir2=0.7405,
                                     nir3=0.7828,
                                     nir=0.8328,
                                     rededge=0.8647,
                                     swir1=1.6137,
                                     swir2=2.2024),
                    s2a=WavelengthsS2(blue=0.4924,
                                      green=0.5598,
                                      red=0.6646,
                                      nir1=0.7041,
                                      nir2=0.7405,
                                      nir3=0.7828,
                                      nir=0.8328,
                                      rededge=0.8647,
                                      swir1=1.6137,
                                      swir2=2.2024),
                    s2b=WavelengthsS2(blue=0.4921,
                                      green=0.559,
                                      red=0.665,
                                      nir1=0.7038,
                                      nir2=0.7391,
                                      nir3=0.7797,
                                      nir=0.833,
                                      rededge=0.864,
                                      swir1=1.6104,
                                      swir2=2.1857),
                    s2f=WavelengthsS2Full(coastal=0.4427,
                                          blue=0.4924,
                                          green=0.5598,
                                          red=0.6646,
                                          nir1=0.7041,
                                          nir2=0.7405,
                                          nir3=0.7828,
                                          nir=0.8328,
                                          rededge=0.8647,
                                          water=0.9451,
                                          cirrus=1.3735,
                                          swir1=1.6137,
                                          swir2=2.2024),
                    s2af=WavelengthsS2Full(coastal=0.4427,
                                           blue=0.4924,
                                           green=0.5598,
                                           red=0.6646,
                                           nir1=0.7041,
                                           nir2=0.7405,
                                           nir3=0.7828,
                                           nir=0.8328,
                                           rededge=0.8647,
                                           water=0.9451,
                                           cirrus=1.3735,
                                           swir1=1.6137,
                                           swir2=2.2024),
                    s2bf=WavelengthsS2Full(coastal=0.4423,
                                           blue=0.4921,
                                           green=0.559,
                                           red=0.665,
                                           nir1=0.7038,
                                           nir2=0.7391,
                                           nir3=0.7797,
                                           nir=0.833,
                                           rededge=0.864,
                                           water=0.9432,
                                           cirrus=1.3769,
                                           swir1=1.6104,
                                           swir2=2.1857),
                    s2l7=WavelengthsL57(blue=0.49,
                                        green=0.56,
                                        red=0.665,
                                        nir=0.842,
                                        swir1=1.61,
                                        swir2=2.19),
                    s2al7=WavelengthsL57(blue=0.4924,
                                         green=0.5598,
                                         red=0.6646,
                                         nir=0.8328,
                                         swir1=1.6137,
                                         swir2=2.2024),
                    s2bl7=WavelengthsL57(blue=0.4921,
                                         green=0.559,
                                         red=0.665,
                                         nir=0.833,
                                         swir1=1.6104,
                                         swir2=2.1857),
                    s210=WavelengthsBGRN(blue=0.49,
                                         green=0.56,
                                         red=0.665,
                                         nir=0.842),
                    s2a10=WavelengthsBGRN(blue=0.4924,
                                          green=0.5598,
                                          red=0.6646,
                                          nir=0.8328),
                    s2b10=WavelengthsBGRN(blue=0.4921,
                                          green=0.559,
                                          red=0.665,
                                          nir=0.833),
                    s220=WavelengthsS220(nir1=0.705,
                                         nir2=0.74,
                                         nir3=0.783,
                                         rededge=0.865,
                                         swir1=1.61,
                                         swir2=2.19),
                    s2a20=WavelengthsS220(nir1=0.7041,
                                          nir2=0.7405,
                                          nir3=0.7828,
                                          rededge=0.8647,
                                          swir1=1.6137,
                                          swir2=2.2024),
                    s2b20=WavelengthsS220(nir1=0.7038,
                                          nir2=0.7391,
                                          nir3=0.7797,
                                          rededge=0.864,
                                          swir1=1.6104,
                                          swir2=2.1857),
                    s2cloudless=WavelengthsS2Cloudless(coastal=0.443,
                                                       blue=0.49,
                                                       red=0.665,
                                                       nir1=0.705,
                                                       nir=0.842,
                                                       rededge=0.865,
                                                       water=0.945,
                                                       cirrus=1.375,
                                                       swir1=1.61,
                                                       swir2=2.19),
                    s2acloudless=WavelengthsS2Cloudless(coastal=0.4427,
                                                        blue=0.4924,
                                                        red=0.6646,
                                                        nir1=0.7041,
                                                        nir=0.8328,
                                                        rededge=0.8647,
                                                        water=0.9451,
                                                        cirrus=1.3735,
                                                        swir1=1.6137,
                                                        swir2=2.2024),
                    s2bcloudless=WavelengthsS2Cloudless(coastal=0.4423,
                                                        blue=0.4921,
                                                        red=0.665,
                                                        nir1=0.7038,
                                                        nir=0.833,
                                                        rededge=0.864,
                                                        water=0.9432,
                                                        cirrus=1.3769,
                                                        swir1=1.6104,
                                                        swir2=2.1857),
                    ps=WavelengthsBGRN(blue=0.485,
                                       green=0.545,
                                       red=0.63,
                                       nir=0.82))

    @property
    def sensor_names(self):

        """
        Get sensor full names
        """

        return dict(rgb='red, green, and blue',
                    rgbn='red, green, blue, and NIR',
                    bgr='blue, green, and red',
                    bgrn='blue, green, red, and NIR',
                    l5='Landsat 5 Thematic Mapper (TM)',
                    l7='Landsat 7 Enhanced Thematic Mapper Plus (ETM+) without panchromatic and thermal bands',
                    l7th='Landsat 7 Enhanced Thematic Mapper Plus (ETM+) with thermal band',
                    l7mspan='Landsat 7 Enhanced Thematic Mapper Plus (ETM+) with panchromatic band',
                    l7pan='Landsat 7 panchromatic band',
                    l8='Landsat 8 Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS) without panchromatic and thermal bands',
                    l8l7='Landsat 8 Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS) with 6 Landsat 7-like bands',
                    l8l7mspan='Landsat 8 Operational Land Imager (OLI) and panchromatic band with 6 Landsat 7-like bands',
                    l8th='Landsat 8 Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS) with thermal band',
                    l8pan='Landsat 8 panchromatic band',
                    s2='Sentinel 2 Multi-Spectral Instrument (MSI) without 3 60m bands (coastal, water vapor, cirrus)',
                    s2f='Sentinel 2 Multi-Spectral Instrument (MSI) with 3 60m bands (coastal, water vapor, cirrus)',
                    s2l7='Sentinel 2 Multi-Spectral Instrument (MSI) with 6 Landsat 7-like bands',
                    s210='Sentinel 2 Multi-Spectral Instrument (MSI) with 4 10m (visible + NIR) bands',
                    s220='Sentinel 2 Multi-Spectral Instrument (MSI) with 6 20m bands',
                    s2cloudless='Sentinel 2 Multi-Spectral Instrument (MSI) with 10 bands for s2cloudless',
                    ps='PlanetScope with 4 (visible + NIR) bands',
                    qb='Quickbird with 4 (visible + NIR) bands',
                    ik='IKONOS with 4 (visible + NIR) bands')

    @property
    def wavelengths(self):

        """
        Get a dictionary of sensor wavelengths
        """

        return dict(rgb=WavelengthsRGB(red=1,
                                       green=2,
                                       blue=3),
                    rgbn=WavelengthsRGBN(red=1,
                                         green=2,
                                         blue=3,
                                         nir=4),
                    bgr=WavelengthsBGR(blue=1,
                                       green=2,
                                       red=3),
                    bgrn=WavelengthsBGRN(blue=1,
                                         green=2,
                                         red=3,
                                         nir=4),
                    l5=WavelengthsL57(blue=1,
                                      green=2,
                                      red=3,
                                      nir=4,
                                      swir1=5,
                                      swir2=6),
                    l7=WavelengthsL57(blue=1,
                                      green=2,
                                      red=3,
                                      nir=4,
                                      swir1=5,
                                      swir2=6),
                    l7th=WavelengthsL57Thermal(blue=1,
                                               green=2,
                                               red=3,
                                               nir=4,
                                               swir1=5,
                                               thermal=6,
                                               swir2=7),
                    l7mspan=WavelengthsL57Pan(blue=1,
                                              green=2,
                                              red=3,
                                              nir=4,
                                              swir1=5,
                                              swir2=6,
                                              pan=7),
                    l7pan=WavelengthsPan(pan=1),
                    l8=WavelengthsL8(coastal=1,
                                     blue=2,
                                     green=3,
                                     red=4,
                                     nir=5,
                                     swir1=6,
                                     swir2=7,
                                     cirrus=8),
                    l8th=WavelengthsL8Thermal(coastal=1,
                                              blue=2,
                                              green=3,
                                              red=4,
                                              nir=5,
                                              swir1=6,
                                              swir2=7,
                                              cirrus=8,
                                              tirs1=9,
                                              tirs2=10),
                    l8l7=WavelengthsL57(blue=1,
                                        green=2,
                                        red=3,
                                        nir=4,
                                        swir1=5,
                                        swir2=6),
                    l8l7mspan=WavelengthsL57Pan(blue=1,
                                                green=2,
                                                red=3,
                                                nir=4,
                                                swir1=5,
                                                swir2=6,
                                                pan=7),
                    l8pan=WavelengthsPan(pan=1),
                    l5bgrn=WavelengthsBGRN(blue=1,
                                           green=2,
                                           red=3,
                                           nir=4),
                    l7bgrn=WavelengthsBGRN(blue=1,
                                           green=2,
                                           red=3,
                                           nir=4),
                    l8bgrn=WavelengthsBGRN(blue=1,
                                           green=2,
                                           red=3,
                                           nir=4),
                    s2=WavelengthsS2(blue=1,
                                     green=2,
                                     red=3,
                                     nir1=4,
                                     nir2=5,
                                     nir3=6,
                                     nir=7,
                                     rededge=8,
                                     swir1=9,
                                     swir2=10),
                    s2a=WavelengthsS2(blue=1,
                                      green=2,
                                      red=3,
                                      nir1=4,
                                      nir2=5,
                                      nir3=6,
                                      nir=7,
                                      rededge=8,
                                      swir1=9,
                                      swir2=10),
                    s2b=WavelengthsS2(blue=1,
                                      green=2,
                                      red=3,
                                      nir1=4,
                                      nir2=5,
                                      nir3=6,
                                      nir=7,
                                      rededge=8,
                                      swir1=9,
                                      swir2=10),
                    s2f=WavelengthsS2Full(coastal=1,
                                          blue=2,
                                          green=3,
                                          red=4,
                                          nir1=5,
                                          nir2=6,
                                          nir3=7,
                                          nir=8,
                                          rededge=9,
                                          water=10,
                                          cirrus=11,
                                          swir1=12,
                                          swir2=13),
                    s2af=WavelengthsS2Full(coastal=1,
                                           blue=2,
                                           green=3,
                                           red=4,
                                           nir1=5,
                                           nir2=6,
                                           nir3=7,
                                           nir=8,
                                           rededge=9,
                                           water=10,
                                           cirrus=11,
                                           swir1=12,
                                           swir2=13),
                    s2bf=WavelengthsS2Full(coastal=1,
                                           blue=2,
                                           green=3,
                                           red=4,
                                           nir1=5,
                                           nir2=6,
                                           nir3=7,
                                           nir=8,
                                           rededge=9,
                                           water=10,
                                           cirrus=11,
                                           swir1=12,
                                           swir2=13),
                    s2l7=WavelengthsL57(blue=1,
                                        green=2,
                                        red=3,
                                        nir=4,
                                        swir1=5,
                                        swir2=6),
                    s2al7=WavelengthsL57(blue=1,
                                         green=2,
                                         red=3,
                                         nir=4,
                                         swir1=5,
                                         swir2=6),
                    s2bl7=WavelengthsL57(blue=1,
                                         green=2,
                                         red=3,
                                         nir=4,
                                         swir1=5,
                                         swir2=6),
                    s210=WavelengthsBGRN(blue=1,
                                         green=2,
                                         red=3,
                                         nir=4),
                    s2a10=WavelengthsBGRN(blue=1,
                                          green=2,
                                          red=3,
                                          nir=4),
                    s2b10=WavelengthsBGRN(blue=1,
                                          green=2,
                                          red=3,
                                          nir=4),
                    s220=WavelengthsS220(nir1=1,
                                         nir2=2,
                                         nir3=3,
                                         rededge=4,
                                         swir1=5,
                                         swir2=6),
                    s2a20=WavelengthsS220(nir1=1,
                                          nir2=2,
                                          nir3=3,
                                          rededge=4,
                                          swir1=5,
                                          swir2=6),
                    s2b20=WavelengthsS220(nir1=1,
                                          nir2=2,
                                          nir3=3,
                                          rededge=4,
                                          swir1=5,
                                          swir2=6),
                    s2cloudless=dict(coastal=1,
                                     blue=2,
                                     red=3,
                                     nir1=4,
                                     nir=5,
                                     rededge=6,
                                     water=7,
                                     cirrus=8,
                                     swir1=9,
                                     swir2=10),
                    s2acloudless=dict(coastal=1,
                                      blue=2,
                                      red=3,
                                      nir1=4,
                                      nir=5,
                                      rededge=6,
                                      water=7,
                                      cirrus=8,
                                      swir1=9,
                                      swir2=10),
                    s2bcloudless=dict(coastal=1,
                                      blue=2,
                                      red=3,
                                      nir1=4,
                                      nir=5,
                                      rededge=6,
                                      water=7,
                                      cirrus=8,
                                      swir1=9,
                                      swir2=10),
                    ps=WavelengthsBGRN(blue=1,
                                       green=2,
                                       red=3,
                                       nir=4),
                    qb=WavelengthsBGRN(blue=1,
                                       green=2,
                                       red=3,
                                       nir=4),
                    ik=WavelengthsBGRN(blue=1,
                                       green=2,
                                       red=3,
                                       nir=4))

    @property
    def ndims(self):
        """Get the number of array dimensions"""
        return len(self._obj.shape)

    @property
    def row_chunks(self):
        """Get the row chunk size"""
        return self._obj.data.chunksize[-2]

    @property
    def col_chunks(self):
        """Get the column chunk size"""
        return self._obj.data.chunksize[-1]

    @property
    def band_chunks(self):

        """
        Get the band chunk size
        """

        if self.ndims > 2:
            return self._obj.data.chunksize[-3]
        else:
            return 1

    @property
    def time_chunks(self):

        """
        Get the time chunk size
        """

        if self.ndims > 3:
            return self._obj.data.chunksize[-4]
        else:
            return 1

    @property
    def ntime(self):

        """
        Get the number of time dimensions
        """

        if self.ndims > 3:
            return self._obj.shape[-4]
        else:
            return 1

    @property
    def nbands(self):

        """
        Get the number of array bands
        """

        if self.ndims > 2:
            return self._obj.shape[-3]
        else:
            return 1

    @property
    def nrows(self):
        """Get the number of array rows"""
        return self._obj.shape[-2]

    @property
    def ncols(self):
        """Get the number of array columns"""
        return self._obj.shape[-1]

    @property
    def left(self):

        """
        Get the array bounding box left coordinate

        Pixel shift reference:
            https://github.com/pydata/xarray/blob/master/xarray/backends/rasterio_.py
            http://web.archive.org/web/20160326194152/http://remotesensing.org/geotiff/spec/geotiff2.5.html#2.5.2
        """

        return float(self._obj.x.min().values) - self.cellxh

    @property
    def right(self):
        """Get the array bounding box right coordinate"""
        return float(self._obj.x.max().values) + self.cellxh

    @property
    def top(self):
        """Get the array bounding box top coordinate"""
        return float(self._obj.y.max().values) + self.cellyh

    @property
    def bottom(self):
        """Get the array bounding box bottom coordinate"""
        return float(self._obj.y.min().values) - self.cellyh

    @property
    def bounds(self):
        """Get the array bounding box (left, bottom, right, top)"""
        return self.left, self.bottom, self.right, self.top

    @property
    def bounds_as_namedtuple(self):
        """Get the array bounding box as a ``rasterio.coords.BoundingBox``"""
        return BoundingBox(left=self.left, bottom=self.bottom, right=self.right, top=self.top)

    @property
    def celly(self):
        """Get the cell size in the y direction"""
        return self._obj.res[1]

    @property
    def cellx(self):
        """Get the cell size in the x direction"""
        return self._obj.res[0]

    @property
    def cellyh(self):
        """Get the half width of the cell size in the y direction"""
        return self.celly / 2.0

    @property
    def cellxh(self):
        """Get the half width of the cell size in the x direction"""
        return self.cellx / 2.0

    @property
    def pydatetime(self):
        """Get Python datetime objects from the time dimension"""
        return pd.to_datetime(self._obj.time.values).to_pydatetime()

    @property
    def chunk_grid(self):

        """Get the image chunk grid"""

        geometries = []

        top = self.top
        for i in range(0, self.nrows, self.row_chunks):

            i_csize = n_rows_cols(i, self.row_chunks, self.nrows)
            bottom = top - (i_csize * abs(self.celly))
            left = self.left

            for j in range(0, self.ncols, self.col_chunks):

                j_csize = n_rows_cols(j, self.col_chunks, self.ncols)
                right = left + (j_csize * abs(self.cellx))

                geom = Polygon([(left, bottom),
                                (left, top),
                                (right, top),
                                (right, bottom),
                                (left, bottom)])

                geometries.append(geom)

                left += self.col_chunks * abs(self.cellx)
            top -= self.row_chunks * abs(self.celly)

        return gpd.GeoDataFrame(data=list(range(1, len(geometries)+1)),
                                columns=['chunk'],
                                geometry=geometries,
                                crs=self._obj.crs)

    @property
    def footprint_grid(self):
        """Get the image footprint grid"""
        return self._footprint_grid

    @footprint_grid.setter
    def footprint_grid(self, geometries):

        self._footprint_grid = gpd.GeoDataFrame(data=[fn for fn in self._obj.filename],
                                                columns=['footprint'],
                                                geometry=geometries,
                                                crs=self._obj.crs)

    @property
    def geometry(self):

        """
        Get the polygon geometry of the array bounding box
        """

        return Polygon([(self.left, self.bottom),
                        (self.left, self.top),
                        (self.right, self.top),
                        (self.right, self.bottom),
                        (self.left, self.bottom)])

    @property
    def has_band_coord(self):
        """Check whether the DataArray has a band coordinate"""
        return True if 'band' in self._obj.coords else False

    @property
    def has_band_dim(self):
        """Check whether the DataArray has a band dimension"""
        return True if self.ndims == 3 else False

    @property
    def has_band(self):
        """Check whether the DataArray has a band attribute"""
        return True if ('band' in self._obj.coords) and (self.ndims == 3) else False

    @property
    def has_time_coord(self):
        """Check whether the DataArray has a time coordinate"""
        return True if 'time' in self._obj.coords else False

    @property
    def has_time_dim(self):
        """Check whether the DataArray has a time dimension"""
        return True if self.ndims == 4 else False

    @property
    def has_time(self):
        """Check whether the DataArray has a time attribute"""
        return True if ('time' in self._obj.coords) and (self.ndims == 4) else False

    @property
    def geodataframe(self):

        """
        Get a ``geopandas.GeoDataFrame`` of the array bounds
        """

        return gpd.GeoDataFrame(data=[Path(self._obj.filename).name if hasattr(self._obj, 'filename') else 1],
                                columns=['grid'],
                                geometry=[self.geometry],
                                crs=self._obj.crs)

    @property
    def unary_union(self):
        """Get a representation of the union of the image bounds"""
        return shapely.ops.unary_union(self.geometry)

    @property
    def transform(self):
        """Get the data transform (cell x, 0, left, 0, cell y, top)"""
        return self.cellx, 0.0, self.left, 0.0, -self.celly, self.top

    @property
    def affine(self):
        """Get the affine transform object"""
        return Affine(*self.transform)

    @property
    def meta(self):

        """
        Get the array metadata
        """

        Meta = namedtuple('Meta', 'left right top bottom bounds affine geometry')

        return Meta(left=self.left,
                    right=self.right,
                    top=self.top,
                    bottom=self.bottom,
                    bounds=self.bounds,
                    affine=self.affine,
                    geometry=self.geometry)

<filename>geowombat/core/properties.py<gh_stars>0
from pathlib import Path
from collections import namedtuple

from .util import n_rows_cols

import pandas as pd
import geopandas as gpd
from rasterio.coords import BoundingBox
from affine import Affine
import shapely
from shapely.geometry import Polygon

try:
    from shapely import speedups
    speedups.enable()
except:
    pass


WavelengthsPan = namedtuple('WavelengthsPan', 'pan')
WavelengthsBGR = namedtuple('WavelengthsBGR', 'blue green red')
WavelengthsRGB = namedtuple('WavelengthsRGB', 'red green blue')
WavelengthsBGRN = namedtuple('WavelengthsBGRN', 'blue green red nir')
WavelengthsRGBN = namedtuple('WavelengthsRGBN', 'red green blue nir')
WavelengthsL57 = namedtuple('WavelengthsL57', 'blue green red nir swir1 swir2')
WavelengthsL57Thermal = namedtuple('WavelengthsL57Thermal', 'blue green red nir swir1 thermal swir2')
WavelengthsL57Pan = namedtuple('WavelengthsL57Pan', 'blue green red nir swir1 swir2 pan')
WavelengthsL8 = namedtuple('WavelengthsL8', 'coastal blue green red nir swir1 swir2 cirrus')
WavelengthsL8Thermal = namedtuple('WavelengthsL8Thermal', 'coastal blue green red nir swir1 swir2 cirrus tirs1 tirs2')
WavelengthsS2 = namedtuple('WavelengthsS2', 'blue green red nir1 nir2 nir3 nir rededge swir1 swir2')
WavelengthsS2Full = namedtuple('WavelengthsS2', 'coastal blue green red nir1 nir2 nir3 nir rededge water cirrus swir1 swir2')
WavelengthsS220 = namedtuple('WavelengthsS220', 'nir1 nir2 nir3 rededge swir1 swir2')
WavelengthsS2Cloudless = namedtuple('WavelengthsS2Cloudless', 'coastal blue red nir1 nir rededge water cirrus swir1 swir2')


class DataProperties(object):

    def __init__(self):
        self._footprint_grid = None

    @property
    def avail_sensors(self):
        """Get supported sensors"""
        return sorted(list(self.wavelengths.keys()))

    @property
    def altitude(self):

        """
        Get satellite altitudes (in km)
        """

        return dict(aster=705,
                    l5=705,
                    l7=705,
                    l8=705,
                    s2=786,
                    ps=475,
                    qb=482,
                    ik=681,
                    wv3=617)

    @property
    def central_um(self):

        """
        Get a dictionary of central wavelengths (in micrometers)
        """

        return dict(l5=WavelengthsL57(blue=0.485,
                                      green=0.56,
                                      red=0.66,
                                      nir=0.835,
                                      swir1=1.65,
                                      swir2=2.22),
                    l7=WavelengthsL57(blue=0.485,
                                      green=0.56,
                                      red=0.66,
                                      nir=0.835,
                                      swir1=1.65,
                                      swir2=2.22),
                    l7th=WavelengthsL57Thermal(blue=0.485,
                                               green=0.56,
                                               red=0.66,
                                               nir=0.835,
                                               swir1=1.65,
                                               thermal=11.45,
                                               swir2=2.22),
                    l7mspan=WavelengthsL57Pan(blue=0.485,
                                              green=0.56,
                                              red=0.66,
                                              nir=0.835,
                                              swir1=1.65,
                                              swir2=2.22,
                                              pan=0.71),
                    l7pan=WavelengthsPan(pan=0.71),
                    l8=WavelengthsL8(coastal=0.44,
                                     blue=0.48,
                                     green=0.56,
                                     red=0.655,
                                     nir=0.865,
                                     swir1=1.61,
                                     swir2=2.2,
                                     cirrus=1.37),
                    l8l7=WavelengthsL57(blue=0.48,
                                        green=0.56,
                                        red=0.655,
                                        nir=0.865,
                                        swir1=1.61,
                                        swir2=2.2),
                    l8l7mspan=WavelengthsL57Pan(blue=0.48,
                                                green=0.56,
                                                red=0.655,
                                                nir=0.865,
                                                swir1=1.61,
                                                swir2=2.2,
                                                pan=0.59),
                    l8pan=WavelengthsPan(pan=0.59),
                    l5bgrn=WavelengthsBGRN(blue=0.485,
                                           green=0.56,
                                           red=0.66,
                                           nir=0.835),
                    l7bgrn=WavelengthsBGRN(blue=0.485,
                                           green=0.56,
                                           red=0.66,
                                           nir=0.835),
                    l8bgrn=WavelengthsBGRN(blue=0.48,
                                           green=0.56,
                                           red=0.655,
                                           nir=0.865),
                    s2=WavelengthsS2(blue=0.4924,
                                     green=0.5598,
                                     red=0.6646,
                                     nir1=0.7041,
                                     nir2=0.7405,
                                     nir3=0.7828,
                                     nir=0.8328,
                                     rededge=0.8647,
                                     swir1=1.6137,
                                     swir2=2.2024),
                    s2a=WavelengthsS2(blue=0.4924,
                                      green=0.5598,
                                      red=0.6646,
                                      nir1=0.7041,
                                      nir2=0.7405,
                                      nir3=0.7828,
                                      nir=0.8328,
                                      rededge=0.8647,
                                      swir1=1.6137,
                                      swir2=2.2024),
                    s2b=WavelengthsS2(blue=0.4921,
                                      green=0.559,
                                      red=0.665,
                                      nir1=0.7038,
                                      nir2=0.7391,
                                      nir3=0.7797,
                                      nir=0.833,
                                      rededge=0.864,
                                      swir1=1.6104,
                                      swir2=2.1857),
                    s2f=WavelengthsS2Full(coastal=0.4427,
                                          blue=0.4924,
                                          green=0.5598,
                                          red=0.6646,
                                          nir1=0.7041,
                                          nir2=0.7405,
                                          nir3=0.7828,
                                          nir=0.8328,
                                          rededge=0.8647,
                                          water=0.9451,
                                          cirrus=1.3735,
                                          swir1=1.6137,
                                          swir2=2.2024),
                    s2af=WavelengthsS2Full(coastal=0.4427,
                                           blue=0.4924,
                                           green=0.5598,
                                           red=0.6646,
                                           nir1=0.7041,
                                           nir2=0.7405,
                                           nir3=0.7828,
                                           nir=0.8328,
                                           rededge=0.8647,
                                           water=0.9451,
                                           cirrus=1.3735,
                                           swir1=1.6137,
                                           swir2=2.2024),
                    s2bf=WavelengthsS2Full(coastal=0.4423,
                                           blue=0.4921,
                                           green=0.559,
                                           red=0.665,
                                           nir1=0.7038,
                                           nir2=0.7391,
                                           nir3=0.7797,
                                           nir=0.833,
                                           rededge=0.864,
                                           water=0.9432,
                                           cirrus=1.3769,
                                           swir1=1.6104,
                                           swir2=2.1857),
                    s2l7=WavelengthsL57(blue=0.49,
                                        green=0.56,
                                        red=0.665,
                                        nir=0.842,
                                        swir1=1.61,
                                        swir2=2.19),
                    s2al7=WavelengthsL57(blue=0.4924,
                                         green=0.5598,
                                         red=0.6646,
                                         nir=0.8328,
                                         swir1=1.6137,
                                         swir2=2.2024),
                    s2bl7=WavelengthsL57(blue=0.4921,
                                         green=0.559,
                                         red=0.665,
                                         nir=0.833,
                                         swir1=1.6104,
                                         swir2=2.1857),
                    s210=WavelengthsBGRN(blue=0.49,
                                         green=0.56,
                                         red=0.665,
                                         nir=0.842),
                    s2a10=WavelengthsBGRN(blue=0.4924,
                                          green=0.5598,
                                          red=0.6646,
                                          nir=0.8328),
                    s2b10=WavelengthsBGRN(blue=0.4921,
                                          green=0.559,
                                          red=0.665,
                                          nir=0.833),
                    s220=WavelengthsS220(nir1=0.705,
                                         nir2=0.74,
                                         nir3=0.783,
                                         rededge=0.865,
                                         swir1=1.61,
                                         swir2=2.19),
                    s2a20=WavelengthsS220(nir1=0.7041,
                                          nir2=0.7405,
                                          nir3=0.7828,
                                          rededge=0.8647,
                                          swir1=1.6137,
                                          swir2=2.2024),
                    s2b20=WavelengthsS220(nir1=0.7038,
                                          nir2=0.7391,
                                          nir3=0.7797,
                                          rededge=0.864,
                                          swir1=1.6104,
                                          swir2=2.1857),
                    s2cloudless=WavelengthsS2Cloudless(coastal=0.443,
                                                       blue=0.49,
                                                       red=0.665,
                                                       nir1=0.705,
                                                       nir=0.842,
                                                       rededge=0.865,
                                                       water=0.945,
                                                       cirrus=1.375,
                                                       swir1=1.61,
                                                       swir2=2.19),
                    s2acloudless=WavelengthsS2Cloudless(coastal=0.4427,
                                                        blue=0.4924,
                                                        red=0.6646,
                                                        nir1=0.7041,
                                                        nir=0.8328,
                                                        rededge=0.8647,
                                                        water=0.9451,
                                                        cirrus=1.3735,
                                                        swir1=1.6137,
                                                        swir2=2.2024),
                    s2bcloudless=WavelengthsS2Cloudless(coastal=0.4423,
                                                        blue=0.4921,
                                                        red=0.665,
                                                        nir1=0.7038,
                                                        nir=0.833,
                                                        rededge=0.864,
                                                        water=0.9432,
                                                        cirrus=1.3769,
                                                        swir1=1.6104,
                                                        swir2=2.1857),
                    ps=WavelengthsBGRN(blue=0.485,
                                       green=0.545,
                                       red=0.63,
                                       nir=0.82))

    @property
    def sensor_names(self):

        """
        Get sensor full names
        """

        return dict(rgb='red, green, and blue',
                    rgbn='red, green, blue, and NIR',
                    bgr='blue, green, and red',
                    bgrn='blue, green, red, and NIR',
                    l5='Landsat 5 Thematic Mapper (TM)',
                    l7='Landsat 7 Enhanced Thematic Mapper Plus (ETM+) without panchromatic and thermal bands',
                    l7th='Landsat 7 Enhanced Thematic Mapper Plus (ETM+) with thermal band',
                    l7mspan='Landsat 7 Enhanced Thematic Mapper Plus (ETM+) with panchromatic band',
                    l7pan='Landsat 7 panchromatic band',
                    l8='Landsat 8 Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS) without panchromatic and thermal bands',
                    l8l7='Landsat 8 Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS) with 6 Landsat 7-like bands',
                    l8l7mspan='Landsat 8 Operational Land Imager (OLI) and panchromatic band with 6 Landsat 7-like bands',
                    l8th='Landsat 8 Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS) with thermal band',
                    l8pan='Landsat 8 panchromatic band',
                    s2='Sentinel 2 Multi-Spectral Instrument (MSI) without 3 60m bands (coastal, water vapor, cirrus)',
                    s2f='Sentinel 2 Multi-Spectral Instrument (MSI) with 3 60m bands (coastal, water vapor, cirrus)',
                    s2l7='Sentinel 2 Multi-Spectral Instrument (MSI) with 6 Landsat 7-like bands',
                    s210='Sentinel 2 Multi-Spectral Instrument (MSI) with 4 10m (visible + NIR) bands',
                    s220='Sentinel 2 Multi-Spectral Instrument (MSI) with 6 20m bands',
                    s2cloudless='Sentinel 2 Multi-Spectral Instrument (MSI) with 10 bands for s2cloudless',
                    ps='PlanetScope with 4 (visible + NIR) bands',
                    qb='Quickbird with 4 (visible + NIR) bands',
                    ik='IKONOS with 4 (visible + NIR) bands')

    @property
    def wavelengths(self):

        """
        Get a dictionary of sensor wavelengths
        """

        return dict(rgb=WavelengthsRGB(red=1,
                                       green=2,
                                       blue=3),
                    rgbn=WavelengthsRGBN(red=1,
                                         green=2,
                                         blue=3,
                                         nir=4),
                    bgr=WavelengthsBGR(blue=1,
                                       green=2,
                                       red=3),
                    bgrn=WavelengthsBGRN(blue=1,
                                         green=2,
                                         red=3,
                                         nir=4),
                    l5=WavelengthsL57(blue=1,
                                      green=2,
                                      red=3,
                                      nir=4,
                                      swir1=5,
                                      swir2=6),
                    l7=WavelengthsL57(blue=1,
                                      green=2,
                                      red=3,
                                      nir=4,
                                      swir1=5,
                                      swir2=6),
                    l7th=WavelengthsL57Thermal(blue=1,
                                               green=2,
                                               red=3,
                                               nir=4,
                                               swir1=5,
                                               thermal=6,
                                               swir2=7),
                    l7mspan=WavelengthsL57Pan(blue=1,
                                              green=2,
                                              red=3,
                                              nir=4,
                                              swir1=5,
                                              swir2=6,
                                              pan=7),
                    l7pan=WavelengthsPan(pan=1),
                    l8=WavelengthsL8(coastal=1,
                                     blue=2,
                                     green=3,
                                     red=4,
                                     nir=5,
                                     swir1=6,
                                     swir2=7,
                                     cirrus=8),
                    l8th=WavelengthsL8Thermal(coastal=1,
                                              blue=2,
                                              green=3,
                                              red=4,
                                              nir=5,
                                              swir1=6,
                                              swir2=7,
                                              cirrus=8,
                                              tirs1=9,
                                              tirs2=10),
                    l8l7=WavelengthsL57(blue=1,
                                        green=2,
                                        red=3,
                                        nir=4,
                                        swir1=5,
                                        swir2=6),
                    l8l7mspan=WavelengthsL57Pan(blue=1,
                                                green=2,
                                                red=3,
                                                nir=4,
                                                swir1=5,
                                                swir2=6,
                                                pan=7),
                    l8pan=WavelengthsPan(pan=1),
                    l5bgrn=WavelengthsBGRN(blue=1,
                                           green=2,
                                           red=3,
                                           nir=4),
                    l7bgrn=WavelengthsBGRN(blue=1,
                                           green=2,
                                           red=3,
                                           nir=4),
                    l8bgrn=WavelengthsBGRN(blue=1,
                                           green=2,
                                           red=3,
                                           nir=4),
                    s2=WavelengthsS2(blue=1,
                                     green=2,
                                     red=3,
                                     nir1=4,
                                     nir2=5,
                                     nir3=6,
                                     nir=7,
                                     rededge=8,
                                     swir1=9,
                                     swir2=10),
                    s2a=WavelengthsS2(blue=1,
                                      green=2,
                                      red=3,
                                      nir1=4,
                                      nir2=5,
                                      nir3=6,
                                      nir=7,
                                      rededge=8,
                                      swir1=9,
                                      swir2=10),
                    s2b=WavelengthsS2(blue=1,
                                      green=2,
                                      red=3,
                                      nir1=4,
                                      nir2=5,
                                      nir3=6,
                                      nir=7,
                                      rededge=8,
                                      swir1=9,
                                      swir2=10),
                    s2f=WavelengthsS2Full(coastal=1,
                                          blue=2,
                                          green=3,
                                          red=4,
                                          nir1=5,
                                          nir2=6,
                                          nir3=7,
                                          nir=8,
                                          rededge=9,
                                          water=10,
                                          cirrus=11,
                                          swir1=12,
                                          swir2=13),
                    s2af=WavelengthsS2Full(coastal=1,
                                           blue=2,
                                           green=3,
                                           red=4,
                                           nir1=5,
                                           nir2=6,
                                           nir3=7,
                                           nir=8,
                                           rededge=9,
                                           water=10,
                                           cirrus=11,
                                           swir1=12,
                                           swir2=13),
                    s2bf=WavelengthsS2Full(coastal=1,
                                           blue=2,
                                           green=3,
                                           red=4,
                                           nir1=5,
                                           nir2=6,
                                           nir3=7,
                                           nir=8,
                                           rededge=9,
                                           water=10,
                                           cirrus=11,
                                           swir1=12,
                                           swir2=13),
                    s2l7=WavelengthsL57(blue=1,
                                        green=2,
                                        red=3,
                                        nir=4,
                                        swir1=5,
                                        swir2=6),
                    s2al7=WavelengthsL57(blue=1,
                                         green=2,
                                         red=3,
                                         nir=4,
                                         swir1=5,
                                         swir2=6),
                    s2bl7=WavelengthsL57(blue=1,
                                         green=2,
                                         red=3,
                                         nir=4,
                                         swir1=5,
                                         swir2=6),
                    s210=WavelengthsBGRN(blue=1,
                                         green=2,
                                         red=3,
                                         nir=4),
                    s2a10=WavelengthsBGRN(blue=1,
                                          green=2,
                                          red=3,
                                          nir=4),
                    s2b10=WavelengthsBGRN(blue=1,
                                          green=2,
                                          red=3,
                                          nir=4),
                    s220=WavelengthsS220(nir1=1,
                                         nir2=2,
                                         nir3=3,
                                         rededge=4,
                                         swir1=5,
                                         swir2=6),
                    s2a20=WavelengthsS220(nir1=1,
                                          nir2=2,
                                          nir3=3,
                                          rededge=4,
                                          swir1=5,
                                          swir2=6),
                    s2b20=WavelengthsS220(nir1=1,
                                          nir2=2,
                                          nir3=3,
                                          rededge=4,
                                          swir1=5,
                                          swir2=6),
                    s2cloudless=dict(coastal=1,
                                     blue=2,
                                     red=3,
                                     nir1=4,
                                     nir=5,
                                     rededge=6,
                                     water=7,
                                     cirrus=8,
                                     swir1=9,
                                     swir2=10),
                    s2acloudless=dict(coastal=1,
                                      blue=2,
                                      red=3,
                                      nir1=4,
                                      nir=5,
                                      rededge=6,
                                      water=7,
                                      cirrus=8,
                                      swir1=9,
                                      swir2=10),
                    s2bcloudless=dict(coastal=1,
                                      blue=2,
                                      red=3,
                                      nir1=4,
                                      nir=5,
                                      rededge=6,
                                      water=7,
                                      cirrus=8,
                                      swir1=9,
                                      swir2=10),
                    ps=WavelengthsBGRN(blue=1,
                                       green=2,
                                       red=3,
                                       nir=4),
                    qb=WavelengthsBGRN(blue=1,
                                       green=2,
                                       red=3,
                                       nir=4),
                    ik=WavelengthsBGRN(blue=1,
                                       green=2,
                                       red=3,
                                       nir=4))

    @property
    def ndims(self):
        """Get the number of array dimensions"""
        return len(self._obj.shape)

    @property
    def row_chunks(self):
        """Get the row chunk size"""
        return self._obj.data.chunksize[-2]

    @property
    def col_chunks(self):
        """Get the column chunk size"""
        return self._obj.data.chunksize[-1]

    @property
    def band_chunks(self):

        """
        Get the band chunk size
        """

        if self.ndims > 2:
            return self._obj.data.chunksize[-3]
        else:
            return 1

    @property
    def time_chunks(self):

        """
        Get the time chunk size
        """

        if self.ndims > 3:
            return self._obj.data.chunksize[-4]
        else:
            return 1

    @property
    def ntime(self):

        """
        Get the number of time dimensions
        """

        if self.ndims > 3:
            return self._obj.shape[-4]
        else:
            return 1

    @property
    def nbands(self):

        """
        Get the number of array bands
        """

        if self.ndims > 2:
            return self._obj.shape[-3]
        else:
            return 1

    @property
    def nrows(self):
        """Get the number of array rows"""
        return self._obj.shape[-2]

    @property
    def ncols(self):
        """Get the number of array columns"""
        return self._obj.shape[-1]

    @property
    def left(self):

        """
        Get the array bounding box left coordinate

        Pixel shift reference:
            https://github.com/pydata/xarray/blob/master/xarray/backends/rasterio_.py
            http://web.archive.org/web/20160326194152/http://remotesensing.org/geotiff/spec/geotiff2.5.html#2.5.2
        """

        return float(self._obj.x.min().values) - self.cellxh

    @property
    def right(self):
        """Get the array bounding box right coordinate"""
        return float(self._obj.x.max().values) + self.cellxh

    @property
    def top(self):
        """Get the array bounding box top coordinate"""
        return float(self._obj.y.max().values) + self.cellyh

    @property
    def bottom(self):
        """Get the array bounding box bottom coordinate"""
        return float(self._obj.y.min().values) - self.cellyh

    @property
    def bounds(self):
        """Get the array bounding box (left, bottom, right, top)"""
        return self.left, self.bottom, self.right, self.top

    @property
    def bounds_as_namedtuple(self):
        """Get the array bounding box as a ``rasterio.coords.BoundingBox``"""
        return BoundingBox(left=self.left, bottom=self.bottom, right=self.right, top=self.top)

    @property
    def celly(self):
        """Get the cell size in the y direction"""
        return self._obj.res[1]

    @property
    def cellx(self):
        """Get the cell size in the x direction"""
        return self._obj.res[0]

    @property
    def cellyh(self):
        """Get the half width of the cell size in the y direction"""
        return self.celly / 2.0

    @property
    def cellxh(self):
        """Get the half width of the cell size in the x direction"""
        return self.cellx / 2.0

    @property
    def pydatetime(self):
        """Get Python datetime objects from the time dimension"""
        return pd.to_datetime(self._obj.time.values).to_pydatetime()

    @property
    def chunk_grid(self):

        """Get the image chunk grid"""

        geometries = []

        top = self.top
        for i in range(0, self.nrows, self.row_chunks):

            i_csize = n_rows_cols(i, self.row_chunks, self.nrows)
            bottom = top - (i_csize * abs(self.celly))
            left = self.left

            for j in range(0, self.ncols, self.col_chunks):

                j_csize = n_rows_cols(j, self.col_chunks, self.ncols)
                right = left + (j_csize * abs(self.cellx))

                geom = Polygon([(left, bottom),
                                (left, top),
                                (right, top),
                                (right, bottom),
                                (left, bottom)])

                geometries.append(geom)

                left += self.col_chunks * abs(self.cellx)
            top -= self.row_chunks * abs(self.celly)

        return gpd.GeoDataFrame(data=list(range(1, len(geometries)+1)),
                                columns=['chunk'],
                                geometry=geometries,
                                crs=self._obj.crs)

    @property
    def footprint_grid(self):
        """Get the image footprint grid"""
        return self._footprint_grid

    @footprint_grid.setter
    def footprint_grid(self, geometries):

        self._footprint_grid = gpd.GeoDataFrame(data=[fn for fn in self._obj.filename],
                                                columns=['footprint'],
                                                geometry=geometries,
                                                crs=self._obj.crs)

    @property
    def geometry(self):

        """
        Get the polygon geometry of the array bounding box
        """

        return Polygon([(self.left, self.bottom),
                        (self.left, self.top),
                        (self.right, self.top),
                        (self.right, self.bottom),
                        (self.left, self.bottom)])

    @property
    def has_band_coord(self):
        """Check whether the DataArray has a band coordinate"""
        return True if 'band' in self._obj.coords else False

    @property
    def has_band_dim(self):
        """Check whether the DataArray has a band dimension"""
        return True if self.ndims == 3 else False

    @property
    def has_band(self):
        """Check whether the DataArray has a band attribute"""
        return True if ('band' in self._obj.coords) and (self.ndims == 3) else False

    @property
    def has_time_coord(self):
        """Check whether the DataArray has a time coordinate"""
        return True if 'time' in self._obj.coords else False

    @property
    def has_time_dim(self):
        """Check whether the DataArray has a time dimension"""
        return True if self.ndims == 4 else False

    @property
    def has_time(self):
        """Check whether the DataArray has a time attribute"""
        return True if ('time' in self._obj.coords) and (self.ndims == 4) else False

    @property
    def geodataframe(self):

        """
        Get a ``geopandas.GeoDataFrame`` of the array bounds
        """

        return gpd.GeoDataFrame(data=[Path(self._obj.filename).name if hasattr(self._obj, 'filename') else 1],
                                columns=['grid'],
                                geometry=[self.geometry],
                                crs=self._obj.crs)

    @property
    def unary_union(self):
        """Get a representation of the union of the image bounds"""
        return shapely.ops.unary_union(self.geometry)

    @property
    def transform(self):
        """Get the data transform (cell x, 0, left, 0, cell y, top)"""
        return self.cellx, 0.0, self.left, 0.0, -self.celly, self.top

    @property
    def affine(self):
        """Get the affine transform object"""
        return Affine(*self.transform)

    @property
    def meta(self):

        """
        Get the array metadata
        """

        Meta = namedtuple('Meta', 'left right top bottom bounds affine geometry')

        return Meta(left=self.left,
                    right=self.right,
                    top=self.top,
                    bottom=self.bottom,
                    bounds=self.bounds,
                    affine=self.affine,
                    geometry=self.geometry)

Get supported sensors Get satellite altitudes (in km) Get a dictionary of central wavelengths (in micrometers) Get sensor full names Get a dictionary of sensor wavelengths Get the number of array dimensions Get the row chunk size Get the column chunk size Get the band chunk size Get the time chunk size Get the number of time dimensions Get the number of array bands Get the number of array rows Get the number of array columns Get the array bounding box left coordinate          Pixel shift reference:             https://github.com/pydata/xarray/blob/master/xarray/backends/rasterio_.py             http://web.archive.org/web/20160326194152/http://remotesensing.org/geotiff/spec/geotiff2.5.html#2.5.2 Get the array bounding box right coordinate Get the array bounding box top coordinate Get the array bounding box bottom coordinate Get the array bounding box (left, bottom, right, top) Get the array bounding box as a ``rasterio.coords.BoundingBox`` Get the cell size in the y direction Get the cell size in the x direction Get the half width of the cell size in the y direction Get the half width of the cell size in the x direction Get Python datetime objects from the time dimension Get the image chunk grid Get the image footprint grid Get the polygon geometry of the array bounding box Check whether the DataArray has a band coordinate Check whether the DataArray has a band dimension Check whether the DataArray has a band attribute Check whether the DataArray has a time coordinate Check whether the DataArray has a time dimension Check whether the DataArray has a time attribute Get a ``geopandas.GeoDataFrame`` of the array bounds Get a representation of the union of the image bounds Get the data transform (cell x, 0, left, 0, cell y, top) Get the affine transform object Get the array metadata