def test_tile_read_crs(): """Read tile using different target CRS and bounds CRS.""" bounds = ( -11663507.036777973, 4715018.0897710975, -11663487.927520901, 4715037.199028169, ) tilesize = 16 # Test target CRS with input bounds in bounds_crs arr, mask = utils.tile_read( S3_PATH, bounds, tilesize, indexes=(3, 2, 1), dst_crs="epsg:4326", bounds_crs="epsg:3857", ) assert arr.shape == (3, 16, 16) assert mask.shape == (16, 16) # Test target CRS with input bounds in target CRS bounds = ( -104.7750663757324, 38.95353532141203, -104.77489471435543, 38.95366881479646, ) arr_crs, mask_crs = utils.tile_read(S3_PATH, bounds, tilesize, indexes=(3, 2, 1), dst_crs="epsg:4326") assert np.array_equal(arr, arr_crs)
def test_that_tiling_ignores_padding_if_web_friendly_internal_tiles_exist(): address = COG_WEB_TILED bounds = mercantile.bounds(147, 182, 9) tilesize = 256 arr, mask = utils.tile_read(address, bounds, tilesize) arr2, mask2 = utils.tile_read(address, bounds, tilesize, tile_edge_padding=0) assert np.array_equal(arr, arr2)
def test_tile_read_nodatalpha(): """ Should work as expected (read rgb) """ bounds = (-8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001) tilesize = 16 with pytest.raises(RioTilerError): utils.tile_read(S3_PATH, bounds, tilesize, indexes=(3, 2, 1), nodata=0, alpha=3)
def test_resampling_with_diff_padding_returns_different_results(): address = "{}_B2.TIF".format(LANDSAT_PATH) bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) tilesize = 16 arr, mask = utils.tile_read(address, bounds, tilesize) arr2, mask2 = utils.tile_read(address, bounds, tilesize, tile_edge_padding=0) assert not np.array_equal(arr, arr2)
def test_tile_read_not_covering_the_whole_tile(): """Should raise an error when dataset doesn't cover more than 50% of the tile.""" address = "{}_B2.TIF".format(LANDSAT_PATH) bounds = ( -9079495.967826376, 3991847.365165044, -9001224.450862356, 4070118.882129065, ) tilesize = 16 with pytest.raises(TileOutsideBounds): utils.tile_read(address, bounds, tilesize, minimum_tile_cover=0.6)
def test_tile_padding_only_effects_edge_pixels(): """Adding tile padding should effect edge pixels only.""" address = "{}_B2.TIF".format(LANDSAT_PATH) bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) tilesize = 16 arr, mask = utils.tile_read(address, bounds, tilesize) arr2, mask2 = utils.tile_read(address, bounds, tilesize, tile_edge_padding=0) assert not np.array_equal(arr[0][0], arr2[0][0]) assert np.array_equal(arr[0][5:-5][5:-5], arr2[0][5:-5][5:-5])
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)
def test_tile_read_extmask(): """Read masked area.""" # non-boundless tile covering the masked part mercator_tile = mercantile.Tile(x=876431, y=1603669, z=22) bounds = mercantile.xy_bounds(mercator_tile) arr, mask = utils.tile_read(S3_EXTMASK_PATH, bounds, 256) assert arr.shape == (3, 256, 256) assert mask.shape == (256, 256) assert not mask.all() # boundless tile covering the masked part mercator_tile = mercantile.Tile(x=876431, y=1603668, z=22) bounds = mercantile.xy_bounds(mercator_tile) arr, mask = utils.tile_read(S3_MASK_PATH, bounds, 256) assert arr.shape == (3, 256, 256) assert not mask.all()
def tile(address, tile_x, tile_y, tile_z, tilesize=256, **kwargs): """ 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. 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 """ with rasterio.open(address) as src: mercator_tile = EPSG5514_TMS.tile(x=tile_x, y=tile_y, z=tile_z) tile_bounds = EPSG5514_TMS.xy_bounds(mercator_tile) return utils.tile_read(src, tile_bounds, tilesize, **kwargs)
def test_tile_read_alpha(): """Read masked area.""" # non-boundless tile covering the alpha masked part mercator_tile = mercantile.Tile(x=876432, y=1603670, z=22) bounds = mercantile.xy_bounds(mercator_tile) arr, mask = utils.tile_read(S3_ALPHA_PATH, bounds, 256, indexes=(1, 2, 3)) assert arr.shape == (3, 256, 256) assert not mask.all()
def test_tile_read_internal_nodata(): """Read masked area.""" # non-boundless tile covering the nodata part mercator_tile = mercantile.Tile(x=876431, y=1603670, z=22) bounds = mercantile.xy_bounds(mercator_tile) arr, mask = utils.tile_read(S3_NODATA_PATH, bounds, 256, indexes=(1, 2, 3)) assert arr.shape == (3, 256, 256) assert not mask.all()
def test_tile_read_alpha(): """ Should work as expected """ bounds = (-11663507.036777973, 4715018.0897710975, -11663487.927520901, 4715037.199028169) tilesize = 16 arr, mask = utils.tile_read(S3_ALPHA_PATH, bounds, tilesize, indexes=(1, 2, 3)) assert arr.shape == (3, 16, 16) assert mask.shape == (16, 16) with rasterio.open(S3_ALPHA_PATH) as src: arr, mask = utils.tile_read(src, bounds, tilesize, indexes=(1, 2, 3)) assert arr.shape == (3, 16, 16) assert mask.shape == (16, 16)
def test_tile_read_wrong_nodata(): """Return empty mask on wrong nodata.""" # non-boundless tile covering the nodata part mercator_tile = mercantile.Tile(x=438217, y=801835, z=21) bounds = mercantile.xy_bounds(mercator_tile) arr, mask = utils.tile_read( S3_NODATA_PATH, bounds, 256, indexes=(1, 2, 3), nodata=1000 ) assert arr.shape == (3, 256, 256) assert mask.all() # Mask boundless values mercator_tile = mercantile.Tile(x=109554, y=200458, z=19) bounds = mercantile.xy_bounds(mercator_tile) arr, mask = utils.tile_read( S3_NODATA_PATH, bounds, 256, indexes=(1, 2, 3), nodata=1000 ) assert arr.shape == (3, 256, 256) assert not mask.all()
def read_tile(self, z, x, y): """Read raster tile data and mask.""" mercator_tile = mercantile.Tile(x=x, y=y, z=z) tile_bounds = mercantile.xy_bounds(mercator_tile) return tile_read( self.path, tile_bounds, self.tiles_size, indexes=self.indexes, nodata=self.nodata, )
def test_tile_read_list_index(): """ Should work as expected """ bounds = (-11663507.036777973, 4715018.0897710975, -11663487.927520901, 4715037.199028169) tilesize = 16 arr, mask = utils.tile_read(S3_PATH, bounds, tilesize, indexes=(1)) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
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)
def test_tile_read_list_index(): """ Should work as expected """ bounds = (-8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001) tilesize = 16 arr, mask = utils.tile_read(S3_PATH, bounds, tilesize, indexes=(1)) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
def tile(address, tile_x, tile_y, tile_z, indexes=None, tilesize=256, nodata=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. indexes : tuple, int, optional (default: (1, 2, 3)) Bands indexes for the RGB combination. tilesize : int, optional (default: 256) Output image size. nodata: int or float, optional Overwrite nodata value for mask creation. 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) indexes = indexes if indexes is not None else 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_read(src, tile_bounds, tilesize, indexes=indexes, nodata=nodata)
def test_tile_read_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, mask = utils.tile_read(address, bounds, tilesize) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
def test_tile_read_nodata(): """Should work as expected when forcing nodata value""" address = '{}_B4.TIF'.format(LANDSAT_PATH) bounds = (-9040360.209344367, 3991847.365165044, -9001224.450862356, 4030983.1236470537) tilesize = 16 nodata = 0 arr, mask = utils.tile_read(address, bounds, tilesize, nodata=nodata) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16) assert not mask.all()
def test_tile_read_nodata_and_alpha(): """Should work as expected when forcing nodata value""" bounds = (13604568.04230881, -333876.9395496497, 13605791.034761373, -332653.9470970885) tilesize = 16 arr, mask = utils.tile_read(PIX4D_PATH, bounds, tilesize, indexes=[1, 2, 3]) assert arr.shape == (3, 16, 16) assert mask.shape == (16, 16) assert not mask.all()
def test_tile_read_invalidResampling(): """Should raise an error on invalid resampling method name.""" address = "{}_B2.TIF".format(LANDSAT_PATH) bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) tilesize = 16 with pytest.raises(KeyError): arr, mask = utils.tile_read( address, bounds, tilesize, resampling_method="jacques" )
def test_tile_read_validResampling(): """Should return a 1 band array and a mask.""" address = "{}_B2.TIF".format(LANDSAT_PATH) bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) tilesize = 16 arr, mask = utils.tile_read(address, bounds, tilesize, resampling_method="nearest") assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
def read_tile(self, z, x, y): """Read raster tile data and mask.""" mercator_tile = mercantile.Tile(x=x, y=y, z=z) tile_bounds = mercantile.xy_bounds(mercator_tile) data, mask = tile_read( self.path, tile_bounds, self.tiles_size, indexes=self.indexes, nodata=self.nodata, ) data = (data[0] + data[1]) / 2 return data.astype(numpy.uint8), mask
def test_tile_read_dataset(): """ Should work as expected (read rgb) """ address = '{}_B2.TIF'.format(LANDSAT_PATH) bounds = (-8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001) tilesize = 16 with rasterio.open(address) as src: arr, mask = utils.tile_read(src, bounds, tilesize) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16) assert src.closed
def test_tile_read_vrt_option(): """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, mask = utils.tile_read( address, bounds, tilesize, warp_vrt_option=dict(source_extra=10, num_threads=10) ) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
def test_tile_read_dataset_nodata(): """ Should work as expected (read rgb) """ # non-boundless tile covering the nodata part 22-876431-1603670 bounds = ( -11663535.70066358, 4715027.644399633, -11663526.146035044, 4715037.199028169, ) tilesize = 16 with rasterio.open(S3_NODATA_PATH) as src: arr, mask = utils.tile_read(src, bounds, tilesize) assert arr.shape == (3, 16, 16) assert not mask.all() assert src.closed
def main(input): """Read tile.""" tile = "9-150-183" tile_z, tile_x, tile_y = list(map(int, tile.split('-'))) mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z) tile_bounds = mercantile.xy_bounds(mercator_tile) with rasterio.open(input) as src: mask = src.dataset_mask() rRead = "OK" if mask[0][0] == 0 else "NOK" _, mask = utils.tile_read(src, tile_bounds, 512, indexes=src.indexes) rTiler = "OK" if mask[0][0] == 0 else "NOK" with WarpedVRT(src, add_alpha=True) as vrt: mask = vrt.dataset_mask() rVrt = "OK" if mask[0][0] == 0 else "NOK" click.echo(f"Read: {rRead} Tiler: {rTiler} VRT: {rVrt}")
def tile(address, tile_x, tile_y, tile_z, tilesize=256, **kwargs): """ 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. 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 """ with rasterio.open(address) 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) return utils.tile_read(src, tile_bounds, tilesize, **kwargs)
def test_cog_translate_Internal(): """ Test Web-Optimized COG. - Test COG size is a multiple of 256 (mercator tile size) - Test COG bounds are aligned with mercator grid at max zoom - Test high resolution internal tiles are equal to mercator tile using cogdumper and rio-tiler - Test overview internal tiles are equal to mercator tile using cogdumper and rio-tiler """ from cogdumper.cog_tiles import COGTiff from cogdumper.filedumper import Reader as FileReader runner = CliRunner() with runner.isolated_filesystem(): web_profile = cog_profiles.get("raw") web_profile.update({"blockxsize": 256, "blockysize": 256}) config = dict(GDAL_TIFF_OVR_BLOCKSIZE="128") cog_translate( raster_path_web, "cogeo.tif", web_profile, quiet=True, web_optimized=True, config=config, ) with rasterio.open(raster_path_web) as src_dst: with rasterio.open("cogeo.tif") as out_dst: blocks = list(set(out_dst.block_shapes)) assert len(blocks) == 1 ts = blocks[0][0] assert not out_dst.width % ts assert not out_dst.height % ts max_zoom = get_max_zoom(out_dst) bounds = list( transform_bounds( *[src_dst.crs, "epsg:4326"] + list(src_dst.bounds), densify_pts=21 ) ) leftTile = mercantile.tile(bounds[0], bounds[3], max_zoom) tbounds = mercantile.xy_bounds(leftTile) west, north = tbounds.left, tbounds.top assert out_dst.transform.xoff == west assert out_dst.transform.yoff == north rightTile = mercantile.tile(bounds[2], bounds[1], max_zoom) tbounds = mercantile.xy_bounds(rightTile) east, south = tbounds.right, tbounds.bottom lrx = round( out_dst.transform.xoff + out_dst.transform.a * out_dst.width, 6 ) lry = round( out_dst.transform.yoff + out_dst.transform.e * out_dst.height, 6 ) assert lrx == round(east, 6) assert lry == round(south, 6) with open("cogeo.tif", "rb") as out_body: reader = FileReader(out_body) cog = COGTiff(reader.read) # High resolution # Top Left tile mime_type, tile = cog.get_tile(0, 0, 0) tile_length = 256 * 256 * 3 t = struct.unpack_from("{}b".format(tile_length), tile) arr = numpy.array(t).reshape(256, 256, 3).astype(numpy.uint8) arr = numpy.transpose(arr, [2, 0, 1]) tbounds = mercantile.xy_bounds(leftTile) data, mask = tile_read( "cogeo.tif", tbounds, 256, resampling_method="nearest" ) numpy.testing.assert_array_equal(data, arr) # Bottom right tile mime_type, tile = cog.get_tile(4, 3, 0) tile_length = 256 * 256 * 3 t = struct.unpack_from("{}b".format(tile_length), tile) arr = numpy.array(t).reshape(256, 256, 3).astype(numpy.uint8) arr = numpy.transpose(arr, [2, 0, 1]) tbounds = mercantile.xy_bounds(rightTile) data, mask = tile_read( "cogeo.tif", tbounds, 256, resampling_method="nearest" ) numpy.testing.assert_array_equal(data, arr) # Low resolution (overview 1) # Top Left tile # NOTE: overview internal tile size is 128px # We need to stack two internal tiles to compare with # the 256px mercator tile fetched by rio-tiler # ref: https://github.com/cogeotiff/rio-cogeo/issues/60 mime_type, tile = cog.get_tile(1, 0, 1) tile_length = 128 * 128 * 3 t = struct.unpack_from("{}b".format(tile_length), tile) arr1 = numpy.array(t).reshape(128, 128, 3).astype(numpy.uint8) arr1 = numpy.transpose(arr1, [2, 0, 1]) mime_type, tile = cog.get_tile(2, 0, 1) tile_length = 128 * 128 * 3 t = struct.unpack_from("{}b".format(tile_length), tile) arr2 = numpy.array(t).reshape(128, 128, 3).astype(numpy.uint8) arr2 = numpy.transpose(arr2, [2, 0, 1]) arr = numpy.dstack((arr1, arr2)) lowTile = mercantile.Tile(118594, 60034, 17) tbounds = mercantile.xy_bounds(lowTile) data, mask = tile_read( "cogeo.tif", tbounds, 256, resampling_method="nearest" ) data = data[:, 128:, :] numpy.testing.assert_array_equal(data, arr)