def test_tile_band_worker_nodatalpha(): """ Should work as expected (read rgb) """ bounds = (-8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001) tilesize = 16 with pytest.raises(RioTilerError): utils.tile_band_worker(S3_PATH, bounds, tilesize, indexes=(3, 2, 1), nodata=0, alpha=3)
def tile(address, tile_x, tile_y, tile_z, rgb=None, tilesize=256, nodata=None, alpha=None): """Create mercator tile from any images. Attributes ---------- address : str file url. tile_x : int Mercator tile X index. tile_y : int Mercator tile Y index. tile_z : int Mercator tile ZOOM level. rgb : tuple, int, optional (default: (1, 2, 3)) Bands index for the RGB combination. tilesize : int, optional (default: 256) Output image size. nodata: int or float, optional (defaults: None) alpha: int, optional (defaults: None) Force alphaband if not present in the dataset metadata Returns ------- data : numpy ndarray mask: numpy array """ with rasterio.open(address) as src: wgs_bounds = transform_bounds(*[src.crs, 'epsg:4326'] + list(src.bounds), densify_pts=21) nodata = nodata if nodata is not None else src.nodata if not rgb: rgb = src.indexes 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) return utils.tile_band_worker(address, tile_bounds, tilesize, indexes=rgb, nodata=nodata, alpha=alpha)
def test_tile_band_worker_rgb(): """ Should work as expected (read rgb) """ bounds = (-8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001) tilesize = 16 arr = utils.tile_band_worker(S3_PATH, bounds, tilesize, indexes=(3, 2, 1)) assert arr.shape == (3, 16, 16)
def test_tile_band_worker_int_index(): """ Should work as expected """ bounds = (-8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001) tilesize = 16 arr, mask = utils.tile_band_worker(S3_PATH, bounds, tilesize, indexes=1) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
def tile(bucket, key, tile_x, tile_y, tile_z, rgb=(1, 2, 3), tilesize=256, prefix='s3:/'): """Create mercator tile from AWS hosted images and encodes it in base64. Attributes ---------- bucket : str AWS bucket's name. key : str AWS file's key. tile_x : int Mercator tile X index. tile_y : int Mercator tile Y index. tile_z : int Mercator tile ZOOM level. tileformat : str Image format to return (Accepted: "jpg" or "png") rgb : tuple, int, optional (default: (1, 2, 3)) Bands index for the RGB combination. tilesize : int, optional (default: 256) Output image size. Returns ------- out : numpy ndarray """ source_address = '{}/{}/{}'.format(prefix, bucket, key) with rasterio.open(source_address) as src: wgs_bounds = transform_bounds( *[src.crs, 'epsg:4326'] + list(src.bounds), densify_pts=21) nodata = src.nodata 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) w, s, e, n = tile_bounds out = utils.tile_band_worker(source_address, tile_bounds, tilesize, indexes=rgb, nodata=nodata) return out
def test_tile_band_worker_valid(): """ Should work as expected (read landsat band) """ address = '{}_B2.TIF'.format(LANDSAT_PATH) bounds = (-8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001) tilesize = 16 arr = utils.tile_band_worker(address, bounds, tilesize) assert arr.shape == (16, 16)
def tile(sceneid, tile_x, tile_y, tile_z, rgb=(4, 3, 2), r_bds=(0, 16000), g_bds=(0, 16000), b_bds=(0, 16000), tilesize=256, pan=False): """Create mercator tile from Landsat-8 data and encodes it in base64. 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. rgb : tuple, int, optional (default: (4, 3, 2)) Bands index for the RGB combination. r_bds : tuple, int, optional (default: (0, 16000)) First band (red) DN min and max values (DN * 10,000) used for the linear rescaling. g_bds : tuple, int, optional (default: (0, 16000)) Second band (green) DN min and max values (DN * 10,000) used for the linear rescaling. b_bds : tuple, int, optional (default: (0, 16000)) Third band (blue) DN min and max values (DN * 10,000) used for the linear rescaling. tilesize : int, optional (default: 256) Output image size. pan : boolean, optional (default: False) If True, apply pan-sharpening. Returns ------- out : numpy ndarray (type: uint8) """ scene_params = utils.landsat_parse_scene_id(sceneid) meta_data = utils.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) # define a list of bands Min and Max Values (from input) histo_cuts = dict(zip(rgb, [r_bds, g_bds, b_bds])) ms_tile_size = int(tilesize / 2) if pan else tilesize addresses = ['{}_B{}.TIF'.format(landsat_address, band) for band in rgb] _tiler = partial(utils.tile_band_worker, bounds=tile_bounds, tilesize=ms_tile_size) with futures.ThreadPoolExecutor(max_workers=3) as executor: out = np.stack(list(executor.map(_tiler, addresses))) if pan: pan_address = '{}_B8.TIF'.format(landsat_address) matrix_pan = utils.tile_band_worker(pan_address, tile_bounds, tilesize) w, s, e, n = tile_bounds pan_transform = transform.from_bounds(w, s, e, n, tilesize, tilesize) vis_transform = pan_transform * Affine.scale(2.) out = pansharpen(out, 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(rgb): multi_reflect = meta_data['RADIOMETRIC_RESCALING'].get( 'REFLECTANCE_MULT_BAND_{}'.format(band)) add_reflect = meta_data['RADIOMETRIC_RESCALING'].get( 'REFLECTANCE_ADD_BAND_{}'.format(band)) out[bdx] = 10000 * reflectance.reflectance( out[bdx], multi_reflect, add_reflect, sun_elev, src_nodata=0) out[bdx] = np.where( out[bdx] > 0, utils.linear_rescale(out[bdx], in_range=histo_cuts.get(band), out_range=[1, 255]), 0) return out.astype(np.uint8)
def tile(sceneid, tile_x, tile_y, tile_z, rgb=(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. rgb : tuple, int, 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(rgb, tuple): rgb = tuple((rgb, )) scene_params = utils.landsat_parse_scene_id(sceneid) meta_data = utils.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 rgb] _tiler = partial(utils.tile_band_worker, bounds=tile_bounds, tilesize=ms_tile_size, nodata=0) with futures.ThreadPoolExecutor(max_workers=3) 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_band_worker(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.) 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(rgb): 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