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"
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"
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]
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]
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"
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
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"
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))
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
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
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)
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
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
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)
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
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
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
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
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
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