Exemple #1
0
    def _get_band_url(self, band: str) -> str:
        """Validate band name and return band's url."""
        if band not in self.bands:
            raise InvalidBandName(f"{band} is not valid")

        prefix = self._prefix.format(**self.scene_params)
        return f"{self._scheme}://{self._hostname}/{prefix}/measurement/{self.scene_params['beam'].lower()}-{band}.tiff"
Exemple #2
0
    def _get_href(self, assets: Sequence[str]) -> Sequence[str]:
        """Validate asset names and return asset's url."""
        for asset in assets:
            if asset not in self.assets:
                raise InvalidBandName(f"{asset} is not a valid asset name.")

        return [self.item["assets"][asset]["href"] for asset in assets]
 def _get_band_url(self, band: str) -> str:
     """Validate band name and return band's url."""
     if band not in self.bands:
         raise InvalidBandName(f"{band} is not valid")
     prefix = self._prefix.format(**self.scene_params)
     res = self._get_resolution(band)
     return f"{self._scheme}://{self._hostname}/{prefix}/R{res}m/{band}.jp2"
Exemple #4
0
    def _get_band_url(self, band: str) -> str:
        """Validate band's name and return band's url."""
        if band not in self.bands:
            raise InvalidBandName(f"{band} is not valid")

        index = self.bands.index(band)
        return self.files[index]
Exemple #5
0
    def _get_asset_url(self, asset: str) -> str:
        """Validate band's name and return band's url."""
        if asset not in self.assets:
            raise InvalidBandName(f"{asset} is not valid")

        index = self.assets.index(asset)
        return self.files[index]
Exemple #6
0
    def _get_band_url(self, band: str) -> str:
        """Validate band's name and return band's url."""
        if band not in self.bands:
            raise InvalidBandName(f"{band} is not valid")

        prefix = self._prefix.format(**self.scene_params)
        band = band.replace("B", "BAND")
        return f"{self._scheme}://{self._hostname}/{prefix}/{self.sceneid}_{band}.tif"
Exemple #7
0
def _get_href(stac: Dict, assets: Sequence[str]) -> Sequence[str]:
    """Validate asset names and return asset's url."""
    _assets = list(stac["assets"].keys())
    for asset in assets:
        if asset not in _assets:
            raise InvalidBandName(f"{asset} is not a valid asset name.")

    return [stac["assets"][asset]["href"] for asset in assets]
def tile(sceneid, tile_x, tile_y, tile_z, bands=("04", "03", "02"), tilesize=256):
    """
    Create mercator tile from Sentinel-2 data.

    Attributes
    ----------
    sceneid : str
        Sentinel-2 sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, str, optional (default: ('04', '03', '02'))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not isinstance(bands, tuple):
        bands = tuple((bands,))

    for band in bands:
        if band not in SENTINEL_BANDS:
            raise InvalidBandName("{} is not a valid Sentinel band name".format(band))

    scene_params = _sentinel_parse_scene_id(sceneid)
    sentinel_address = "{}/{}".format(SENTINEL_BUCKET, scene_params["key"])

    sentinel_preview = "{}/preview.jp2".format(sentinel_address)
    with rasterio.open(sentinel_preview) as src:
        wgs_bounds = transform_bounds(
            *[src.crs, "epsg:4326"] + list(src.bounds), densify_pts=21
        )

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds(
            "Tile {}/{}/{} is outside image bounds".format(tile_z, tile_x, tile_y)
        )

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    addresses = ["{}/B{}.jp2".format(sentinel_address, band) for band in bands]

    _tiler = partial(utils.tile_read, bounds=tile_bounds, tilesize=tilesize, nodata=0)
    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

    return np.concatenate(data), mask
Exemple #9
0
    def _get_band_url(self, band: str) -> str:
        """Validate band name and return band's url."""
        band = band if len(band) == 3 else f"B0{band[-1]}"

        if band not in self.bands:
            raise InvalidBandName(f"{band} is not valid.\nValid bands: {self.bands}")

        prefix = self._prefix.format(
            year=self.year, month=self.month, day=self.day, grid=self.grid
        )
        return f"{self._scheme}://{self._hostname}/{prefix}/{band}.tif"
Exemple #10
0
def _l2_prefixed_band(band: str) -> str:
    """Return L2A prefixed bands name."""
    if band in SENTINEL_L2_BANDS["60"]:
        for res, bands in SENTINEL_L2_BANDS.items():
            if band in bands:
                return "R{}m/B{}".format(res, band)
    elif band in SENTINEL_L2_PRODUCTS["60"]:
        for res, bands in SENTINEL_L2_PRODUCTS.items():
            if band in bands:
                return "R{}m/{}".format(res, band)

    raise InvalidBandName("{} is not a valid Sentinel band name".format(band))
Exemple #11
0
def tile(sceneid,
         tile_x,
         tile_y,
         tile_z,
         bands=("4", "3", "2"),
         tilesize=256,
         pan=False):
    """
    Create mercator tile from Landsat-8 data.

    Attributes
    ----------
    sceneid : str
        Landsat sceneid. For scenes after May 2017,
        sceneid have to be LANDSAT_PRODUCT_ID.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, str, optional (default: ("4", "3", "2"))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    pan : boolean, optional (default: False)
        If True, apply pan-sharpening.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in LANDSAT_BANDS:
            raise InvalidBandName(
                "{} is not a valid Landsat band name".format(band))

    scene_params = _landsat_parse_scene_id(sceneid)
    meta_data = _landsat_get_mtl(sceneid).get("L1_METADATA_FILE")
    landsat_address = "{}/{}".format(LANDSAT_BUCKET, scene_params["key"])

    wgs_bounds = toa_utils._get_bounds_from_metadata(
        meta_data["PRODUCT_METADATA"])

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    ms_tile_size = int(tilesize / 2) if pan else tilesize
    addresses = ["{}_B{}.TIF".format(landsat_address, band) for band in bands]

    _tiler = partial(utils.tile_read,
                     bounds=tile_bounds,
                     tilesize=ms_tile_size,
                     nodata=0)
    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        data = np.concatenate(data)
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

        if pan:
            pan_address = "{}_B8.TIF".format(landsat_address)
            matrix_pan, mask = utils.tile_read(pan_address,
                                               tile_bounds,
                                               tilesize,
                                               nodata=0)

            w, s, e, n = tile_bounds
            pan_transform = transform.from_bounds(w, s, e, n, tilesize,
                                                  tilesize)
            vis_transform = pan_transform * Affine.scale(2.0)
            data = pansharpen(
                data,
                vis_transform,
                matrix_pan,
                pan_transform,
                np.int16,
                "EPSG:3857",
                "EPSG:3857",
                0.2,
                method="Brovey",
                src_nodata=0,
            )

        sun_elev = meta_data["IMAGE_ATTRIBUTES"]["SUN_ELEVATION"]

        for bdx, band in enumerate(bands):
            if int(band) > 9:  # TIRS
                multi_rad = meta_data["RADIOMETRIC_RESCALING"].get(
                    "RADIANCE_MULT_BAND_{}".format(band))

                add_rad = meta_data["RADIOMETRIC_RESCALING"].get(
                    "RADIANCE_ADD_BAND_{}".format(band))

                k1 = meta_data["TIRS_THERMAL_CONSTANTS"].get(
                    "K1_CONSTANT_BAND_{}".format(band))

                k2 = meta_data["TIRS_THERMAL_CONSTANTS"].get(
                    "K2_CONSTANT_BAND_{}".format(band))

                data[bdx] = brightness_temp.brightness_temp(
                    data[bdx], multi_rad, add_rad, k1, k2)

            else:
                multi_reflect = meta_data["RADIOMETRIC_RESCALING"].get(
                    "REFLECTANCE_MULT_BAND_{}".format(band))

                add_reflect = meta_data["RADIOMETRIC_RESCALING"].get(
                    "REFLECTANCE_ADD_BAND_{}".format(band))

                data[bdx] = 10000 * reflectance.reflectance(
                    data[bdx], multi_reflect, add_reflect, sun_elev)

        return data, mask
Exemple #12
0
def tile(
    sceneid: str,
    tile_x: int,
    tile_y: int,
    tile_z: int,
    bands: Union[Sequence[str], str] = None,
    tilesize: int = 256,
    **kwargs: Any,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Create mercator tile from Sentinel-1 data.

    Attributes
    ----------
        sceneid : str
            Sentinel-2 sceneid.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands: tuple, str, required
            Bands name (e.g vv, vh).
        tilesize : int, optional (default: 256)
            Output image size.

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    if not bands:
        raise InvalidBandName("bands is required")

    if isinstance(bands, str):
        bands = (bands, )

    for band in bands:
        if band not in SENTINEL_BANDS:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    scene_params = sentinel1_parser(sceneid)
    sentinel_prefix = "{scheme}://{bucket}/{prefix}/measurement".format(
        **scene_params)

    def worker(band: str):
        asset = "{}/{}-{}.tiff".format(sentinel_prefix,
                                       scene_params["beam"].lower(), band)
        with rasterio.open(asset) as src_dst:
            with WarpedVRT(
                    src_dst,
                    src_crs=src_dst.gcps[1],
                    src_transform=transform.from_gcps(src_dst.gcps[0]),
                    src_nodata=0,
            ) as vrt_dst:
                return reader.tile(vrt_dst,
                                   tile_x,
                                   tile_y,
                                   tile_z,
                                   tilesize=tilesize,
                                   **kwargs)

    with futures.ThreadPoolExecutor(
            max_workers=constants.MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(worker, bands)))
        data = numpy.concatenate(data)
        mask = numpy.all(masks, axis=0).astype(numpy.uint8) * 255

    return data, mask
Exemple #13
0
def tile(
    sceneid: str,
    tile_x: int,
    tile_y: int,
    tile_z: int,
    bands: Union[Sequence[str], str] = ("04", "03", "02"),
    tilesize: int = 256,
    **kwargs: Dict,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Create mercator tile from Sentinel-2 data.

    Attributes
    ----------
        sceneid : str
            Sentinel-2 sceneid.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands : tuple, str, optional (default: ('04', '03', '02'))
            Bands index for the RGB combination.
        tilesize : int, optional (default: 256)
            Output image size.
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    if isinstance(bands, str):
        bands = (bands, )

    scene_params = sentinel2_parser(sceneid)
    for band in bands:
        if band not in scene_params["valid_bands"]:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    sentinel_prefix = "{scheme}://{bucket}/{prefix}".format(**scene_params)

    preview_file = os.path.join(sentinel_prefix, scene_params["preview_file"])
    with rasterio.open(preview_file) as src:
        bounds = transform_bounds(src.crs,
                                  constants.WGS84_CRS,
                                  *src.bounds,
                                  densify_pts=21)
        if not tile_exists(bounds, tile_z, tile_x, tile_y):
            raise TileOutsideBounds(
                "Tile {}/{}/{} is outside image bounds".format(
                    tile_z, tile_x, tile_y))

    if scene_params["processingLevel"] == "L2A":
        bands = [_l2_prefixed_band(b) for b in bands]
    else:
        bands = ["B{}".format(b) for b in bands]

    addresses = [f"{sentinel_prefix}/{band}.jp2" for band in bands]
    return reader.multi_tile(addresses,
                             tile_x,
                             tile_y,
                             tile_z,
                             tilesize=tilesize,
                             nodata=0)
Exemple #14
0
def sentinel2_tile(sceneid,
                   tile_x,
                   tile_y,
                   tile_z,
                   bands=("04", "03", "02"),
                   tilesize=256,
                   percents='',
                   **kwargs):
    """
    Create mercator tile from Sentinel-2 data.

    Attributes
    ----------
    sceneid : str
        Sentinel-2 sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, str, optional (default: ('04', '03', '02'))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    kwargs: dict, optional
        These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in SENTINEL_BANDS:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    scene_params = sentinel2._sentinel_parse_scene_id(sceneid)
    sentinel_address = "{}/{}".format(SENTINEL_BUCKET, scene_params["key"])

    addresses = ["{}/B{}.jp2".format(sentinel_address, band) for band in bands]

    values = []
    percents = percents.split(',')
    i = 0
    for address in addresses:
        with rasterio.open(address) as src:
            bounds = warp.transform_bounds(src.crs,
                                           "epsg:4326",
                                           *src.bounds,
                                           densify_pts=21)
            if int(percents[i]) != 0 and int(percents[i + 1]) != 100:
                overviews = src.overviews(1)
                if len(overviews) > 0:
                    d = src.read(
                        out_shape=(1,
                                   int(src.height /
                                       overviews[len(overviews) - 1]),
                                   int(src.width /
                                       overviews[len(overviews) - 1])))
                else:
                    d = src.read()

                dflatten_full = numpy.array(d.flatten())
                dflatten = dflatten_full[dflatten_full > 0]

                p_start, p_end = numpy.percentile(dflatten,
                                                  (int(percents[i]),
                                                   (int(percents[i + 1]))))
                values.append([p_start, p_end])
            else:
                values.append([None, None])
            i += 2

    if not utils.tile_exists(bounds, tile_z, tile_x, tile_y):
        # raise TileOutsideBounds(
        #     "Tile {}/{}/{} is outside image bounds".format(tile_z, tile_x, tile_y)
        # )
        return None, None

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    _tiler = partial(utils.tile_read,
                     bounds=tile_bounds,
                     tilesize=tilesize,
                     nodata=0,
                     **kwargs)
    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        mask = numpy.all(masks, axis=0).astype(numpy.uint8) * 255

    new_data = list(data)
    has_modification = False
    for ds in range(0, len(new_data)):
        if values[ds][0] is not None and values[ds][1] is not None:
            has_modification = True
            new_data[ds] = rescale_intensity(new_data[ds],
                                             in_range=(values[ds][0],
                                                       values[ds][1]),
                                             out_range=(0, 255))

    if has_modification == True:
        data = numpy.array(new_data).astype(numpy.uint8)

    return numpy.concatenate(data), mask
Exemple #15
0
def tile(
    sceneid: str,
    tile_x: int,
    tile_y: int,
    tile_z: int,
    bands: Union[Sequence[str], str] = ["4", "3", "2"],
    tilesize: int = 256,
    pan: bool = False,
    **kwargs: Any,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Create mercator tile from Landsat-8 data.

    Attributes
    ----------
        sceneid : str
            Landsat sceneid. For scenes after May 2017,
            sceneid have to be LANDSAT_PRODUCT_ID.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands : tuple, str, optional (default: ("4", "3", "2"))
            Bands index for the RGB combination.
        tilesize : int, optional (default: 256)
            Output image size.
        pan : boolean, optional (default: False)
            If True, apply pan-sharpening.
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if isinstance(bands, str):
        bands = (bands,)

    for band in bands:
        if band not in LANDSAT_BANDS:
            raise InvalidBandName("{} is not a valid Landsat band name".format(band))

    scene_params = landsat_parser(sceneid)

    meta: Dict = _landsat_get_mtl(sceneid)["L1_METADATA_FILE"]

    landsat_prefix = "{scheme}://{bucket}/{prefix}/{scene}".format(**scene_params)

    bounds = toa_utils._get_bounds_from_metadata(meta["PRODUCT_METADATA"])
    if not tile_exists(bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds(
            "Tile {}/{}/{} is outside image bounds".format(tile_z, tile_x, tile_y)
        )

    def worker(band: str):
        asset = f"{landsat_prefix}_B{band}.TIF"

        if band == "QA":
            nodata = 1
            resamp = "nearest"
        else:
            nodata = 0
            resamp = "bilinear"

        with rasterio.open(asset) as src_dst:
            tile, mask = reader.tile(
                src_dst,
                tile_x,
                tile_y,
                tile_z,
                tilesize=tilesize,
                nodata=nodata,
                resampling_method=resamp,
            )

        return tile, mask

    with futures.ThreadPoolExecutor(max_workers=constants.MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(worker, bands)))
        data = numpy.concatenate(data)
        mask = numpy.all(masks, axis=0).astype(numpy.uint8) * 255

        if pan:
            pan_data, mask = worker("8")
            data = pansharpening_brovey(data, pan_data, 0.2, pan_data.dtype)

        if bands[0] != "QA" or len(bands) != 1:
            for bdx, band in enumerate(bands):
                data[bdx] = _convert(data[bdx], band, meta)

        return data, mask
Exemple #16
0
def tile(
    sceneid: str,
    tile_x: int,
    tile_y: int,
    tile_z: int,
    bands: Union[Sequence[str], str] = None,
    tilesize: int = 256,
    **kwargs: Dict,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Create mercator tile from CBERS data.

    Attributes
    ----------
        sceneid : str
            CBERS sceneid.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands : tuple or list or str, optional
            Bands index for the RGB combination. If None uses default
            defined for the instrument
        tilesize : int, optional
            Output image size. Default is 256
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.reader.tile' function.

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    if isinstance(bands, str):
        bands = (bands, )

    scene_params = cbers_parser(sceneid)

    if not bands:
        bands = scene_params["rgb"]

    for band in bands:
        if band not in scene_params["bands"]:
            raise InvalidBandName(
                "{} is not a valid band name for {} CBERS instrument".format(
                    band, scene_params["instrument"]))

    cbers_prefix = "{scheme}://{bucket}/{prefix}/{scene}".format(
        **scene_params)
    with rasterio.open("{}_BAND{}.tif".format(
            cbers_prefix, scene_params["reference_band"])) as src_dst:
        bounds = transform_bounds(src_dst.crs,
                                  constants.WGS84_CRS,
                                  *src_dst.bounds,
                                  densify_pts=21)

    if not tile_exists(bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    addresses = [f"{cbers_prefix}_BAND{band}.tif" for band in bands]
    return reader.multi_tile(addresses,
                             tile_x,
                             tile_y,
                             tile_z,
                             tilesize=tilesize,
                             nodata=0)
Exemple #17
0
def metadata(
    sceneid: str,
    pmin: float = 2.0,
    pmax: float = 98.0,
    bands: Union[Sequence[str], str] = None,
    hist_options: Dict = {},
    **kwargs,
) -> Dict:
    """
    Retrieve image bounds and band statistics.

    Attributes
    ----------
        sceneid : str
            Sentinel-1 sceneid.
        pmin : float, optional, (default: 2.)
            Histogram minimum cut.
        pmax : float, optional, (default: 98.)
            Histogram maximum cut.
        bands: tuple, str, required
            Bands name (e.g vv, vh).
        kwargs : optional
            These are passed to 'rio_tiler.utils._stats'
            e.g: bins=20, range=(0, 1000)

    Returns
    -------
        out : dict
            Dictionary with image bounds and bands statistics.

    """
    if not bands:
        raise InvalidBandName("bands is required")

    if isinstance(bands, str):
        bands = (bands, )

    for band in bands:
        if band not in SENTINEL_BANDS:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    scene_params = sentinel1_parser(sceneid)
    sentinel_prefix = "{scheme}://{bucket}/{prefix}/measurement".format(
        **scene_params)

    def worker(band: str):
        asset = "{}/{}-{}.tiff".format(sentinel_prefix,
                                       scene_params["beam"].lower(), band)
        with rasterio.open(asset) as src_dst:
            with WarpedVRT(
                    src_dst,
                    src_crs=src_dst.gcps[1],
                    src_transform=transform.from_gcps(src_dst.gcps[0]),
                    src_nodata=0,
            ) as vrt_dst:
                return reader.metadata(
                    vrt_dst,
                    percentiles=(pmin, pmax),
                    hist_options=hist_options,
                    **kwargs,
                )

    with futures.ThreadPoolExecutor(
            max_workers=constants.MAX_THREADS) as executor:
        responses = list(executor.map(worker, bands))

    info = dict(
        sceneid=sceneid,
        bounds=responses[0]["bounds"],
        band_descriptions=[(ix + 1, b) for ix, b in enumerate(bands)],
    )

    info["statistics"] = {
        b: v
        for b, d in zip(bands, responses) for _, v in d["statistics"].items()
    }
    return info
Exemple #18
0
def tile(sceneid,
         tile_x,
         tile_y,
         tile_z,
         bands=("04", "03", "02"),
         tilesize=256,
         **kwargs):
    """
    Create mercator tile from Sentinel-2 data.

    Attributes
    ----------
        sceneid : str
            Sentinel-2 sceneid.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands : tuple, str, optional (default: ('04', '03', '02'))
            Bands index for the RGB combination.
        tilesize : int, optional (default: 256)
            Output image size.
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    scene_params = _sentinel_parse_scene_id(sceneid)

    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in scene_params["valid_bands"]:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    preview_file = os.path.join(
        scene_params["aws_bucket"],
        scene_params["aws_prefix"],
        scene_params["preview_file"],
    )
    with rasterio.open(preview_file) as src:
        bounds = transform_bounds(src.crs,
                                  "epsg:4326",
                                  *src.bounds,
                                  densify_pts=21)

    if not utils.tile_exists(bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    path_prefix = os.path.join(scene_params["aws_bucket"],
                               scene_params["aws_prefix"])
    if scene_params["processingLevel"] == "L2A":
        bands = [_l2_prefixed_band(b) for b in bands]
    else:
        bands = ["B{}".format(b) for b in bands]

    def _read_tile(path):
        with rasterio.open(path) as src_dst:
            return utils.tile_read(src_dst,
                                   bounds=tile_bounds,
                                   tilesize=tilesize,
                                   nodata=0,
                                   **kwargs)

    addresses = ["{}/{}.jp2".format(path_prefix, band) for band in bands]
    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_read_tile, addresses)))
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

    return np.concatenate(data), mask
Exemple #19
0
def metadata(sceneid, pmin=2, pmax=98, bands=None, **kwargs):
    """
    Retrieve image bounds and band statistics.

    Attributes
    ----------
    sceneid : str
        Sentinel-1 sceneid.
    pmin : int, optional, (default: 2)
        Histogram minimum cut.
    pmax : int, optional, (default: 98)
        Histogram maximum cut.
    bands: tuple, str, required
        Bands name (e.g vv, vh).
    kwargs : optional
        These are passed to 'rio_tiler.sentinel1._stats'
        e.g: histogram_bins=20'

    Returns
    -------
    out : dict
        Dictionary with image bounds and bands statistics.

    """
    if not bands:
        raise InvalidBandName("bands is required")

    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in SENTINEL_BANDS:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    scene_params = _sentinel_parse_scene_id(sceneid)
    sentinel_address = "{}/{}/measurement".format(SENTINEL_BUCKET,
                                                  scene_params["key"])

    addresses = [
        "{}/{}-{}.tiff".format(sentinel_address, scene_params["beam"].lower(),
                               band) for band in bands
    ]

    def _s1_metadata(src_path, percentiles, **kwarg):
        with rasterio.open(src_path) as src_dst:
            with WarpedVRT(
                    src_dst,
                    src_crs=src_dst.gcps[1],
                    src_transform=transform.from_gcps(src_dst.gcps[0]),
                    src_nodata=0,
            ) as vrt_dst:
                return utils.raster_get_stats(vrt_dst,
                                              percentiles=percentiles,
                                              **kwarg)

    _stats_worker = partial(_s1_metadata, percentiles=(pmin, pmax), **kwargs)
    with futures.ThreadPoolExecutor() as executor:
        responses = list(executor.map(_stats_worker, addresses))

    info = {
        "sceneid": sceneid,
        "bounds": responses[0]["bounds"],
        "minzoom": responses[0]["minzoom"],
        "maxzoom": responses[0]["maxzoom"],
    }

    info["statistics"] = {
        b: v
        for b, d in zip(bands, responses) for k, v in d["statistics"].items()
    }
    return info
Exemple #20
0
def tile(sceneid, tile_x, tile_y, tile_z, bands=None, tilesize=256):
    """
    Create mercator tile from CBERS data.

    Attributes
    ----------
    sceneid : str
        CBERS sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, int, optional (default: None)
        Bands index for the RGB combination. If None uses default
        defined for the instrument
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    scene_params = _cbers_parse_scene_id(sceneid)

    if not bands:
        bands = scene_params["rgb"]

    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in scene_params["bands"]:
            raise InvalidBandName(
                "{} is not a valid band name for {} CBERS instrument".format(
                    band, scene_params["instrument"]))

    cbers_address = "{}/{}".format(CBERS_BUCKET, scene_params["key"])

    with rasterio.open("{}/{}_BAND{}.tif".format(
            cbers_address, sceneid, scene_params["reference_band"])) as src:
        wgs_bounds = transform_bounds(*[src.crs, "epsg:4326"] +
                                      list(src.bounds),
                                      densify_pts=21)

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    addresses = [
        "{}/{}_BAND{}.tif".format(cbers_address, sceneid, band)
        for band in bands
    ]

    _tiler = partial(utils.tile_read,
                     bounds=tile_bounds,
                     tilesize=tilesize,
                     nodata=0)
    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

    return np.concatenate(data), mask
Exemple #21
0
def tile(sceneid, tile_x, tile_y, tile_z, bands=None, tilesize=256, **kwargs):
    """
    Create mercator tile from Sentinel-1 data.

    Attributes
    ----------
    sceneid : str
        Sentinel-2 sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands: tuple, str, required
        Bands name (e.g vv, vh).
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not bands:
        raise InvalidBandName("bands is required")

    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in SENTINEL_BANDS:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    scene_params = _sentinel_parse_scene_id(sceneid)
    sentinel_address = "{}/{}/measurement".format(SENTINEL_BUCKET,
                                                  scene_params["key"])

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    addresses = [
        "{}/{}-{}.tiff".format(sentinel_address, scene_params["beam"].lower(),
                               band) for band in bands
    ]

    def _s1_tiler(src_path):
        with rasterio.open(src_path) as src_dst:
            with WarpedVRT(
                    src_dst,
                    src_crs=src_dst.gcps[1],
                    src_transform=transform.from_gcps(src_dst.gcps[0]),
                    src_nodata=0,
            ) as vrt_dst:
                if not utils.tile_exists(vrt_dst.bounds, tile_z, tile_x,
                                         tile_y):
                    raise TileOutsideBounds(
                        "Tile {}/{}/{} is outside image bounds".format(
                            tile_z, tile_x, tile_y))

                return utils._tile_read(vrt_dst,
                                        bounds=tile_bounds,
                                        tilesize=tilesize)

    with futures.ThreadPoolExecutor() as executor:
        data, masks = zip(*list(executor.map(_s1_tiler, addresses)))
        mask = numpy.all(masks, axis=0).astype(numpy.uint8) * 255

    return numpy.concatenate(data), mask
Exemple #22
0
def tile(sceneid,
         tile_x,
         tile_y,
         tile_z,
         bands=("4", "3", "2"),
         tilesize=256,
         pan=False,
         **kwargs):
    """
    Create mercator tile from Landsat-8 data.

    Attributes
    ----------
    sceneid : str
        Landsat sceneid. For scenes after May 2017,
        sceneid have to be LANDSAT_PRODUCT_ID.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, str, optional (default: ("4", "3", "2"))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    pan : boolean, optional (default: False)
        If True, apply pan-sharpening.
    kwargs: dict, optional
        These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in LANDSAT_BANDS:
            raise InvalidBandName(
                "{} is not a valid Landsat band name".format(band))

    scene_params = _landsat_parse_scene_id(sceneid)
    meta_data = _landsat_get_mtl(sceneid).get("L1_METADATA_FILE")
    landsat_address = "{}/{}".format(LANDSAT_BUCKET, scene_params["key"])

    wgs_bounds = toa_utils._get_bounds_from_metadata(
        meta_data["PRODUCT_METADATA"])

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    def _tiler(band):
        address = "{}_B{}.TIF".format(landsat_address, band)
        if band == "QA":
            nodata = 1
        else:
            nodata = 0

        return utils.tile_read(address,
                               bounds=tile_bounds,
                               tilesize=tilesize,
                               nodata=nodata,
                               **kwargs)

    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_tiler, bands)))
        data = np.concatenate(data)
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

        if pan:
            pan_address = "{}_B8.TIF".format(landsat_address)
            matrix_pan, mask = utils.tile_read(pan_address,
                                               tile_bounds,
                                               tilesize,
                                               nodata=0)
            data = utils.pansharpening_brovey(data, matrix_pan, 0.2,
                                              matrix_pan.dtype)

        sun_elev = meta_data["IMAGE_ATTRIBUTES"]["SUN_ELEVATION"]

        for bdx, band in enumerate(bands):
            if band in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:  # OLI
                multi_reflect = meta_data["RADIOMETRIC_RESCALING"].get(
                    "REFLECTANCE_MULT_BAND_{}".format(band))

                add_reflect = meta_data["RADIOMETRIC_RESCALING"].get(
                    "REFLECTANCE_ADD_BAND_{}".format(band))

                data[bdx] = 10000 * reflectance.reflectance(
                    data[bdx], multi_reflect, add_reflect, sun_elev)

            elif band in ["10", "11"]:  # TIRS
                multi_rad = meta_data["RADIOMETRIC_RESCALING"].get(
                    "RADIANCE_MULT_BAND_{}".format(band))

                add_rad = meta_data["RADIOMETRIC_RESCALING"].get(
                    "RADIANCE_ADD_BAND_{}".format(band))

                k1 = meta_data["TIRS_THERMAL_CONSTANTS"].get(
                    "K1_CONSTANT_BAND_{}".format(band))

                k2 = meta_data["TIRS_THERMAL_CONSTANTS"].get(
                    "K2_CONSTANT_BAND_{}".format(band))

                data[bdx] = brightness_temp.brightness_temp(
                    data[bdx], multi_rad, add_rad, k1, k2)

        return data, mask