def test_resampling_with_diff_padding_returns_different_results(): bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, _ = reader.part( src_dst, bounds, 32, 32, nodata=0, dst_crs=constants.WEB_MERCATOR_CRS, resampling_method="bilinear", ) arr2, _ = reader.part( src_dst, bounds, 32, 32, nodata=0, padding=10, dst_crs=constants.WEB_MERCATOR_CRS, resampling_method="bilinear", ) assert not numpy.array_equal(arr, arr2)
def test_resampling_with_diff_padding_returns_different_results(): """Test result is different with different padding.""" bounds = [ -6574807.42497772, 12210356.646387195, -6261721.357121638, 12523442.714243278, ] with rasterio.open(COG) as src_dst: arr, _ = reader.part( src_dst, bounds, 32, 32, nodata=0, dst_crs=constants.WEB_MERCATOR_CRS, resampling_method="bilinear", ) arr2, _ = reader.part( src_dst, bounds, 32, 32, nodata=0, padding=10, dst_crs=constants.WEB_MERCATOR_CRS, resampling_method="bilinear", ) assert not numpy.array_equal(arr, arr2)
def test_tile_read_vrt_option(): """Should work as expected (read landsat band).""" bounds = [ -6887893.4928338025, 12210356.646387195, -6574807.424977721, 12523442.714243278, ] tilesize = 16 with pytest.warns(DeprecationWarning): with rasterio.open(COG) as src_dst: arr, mask = reader.part( src_dst, bounds, tilesize, tilesize, warp_vrt_option=dict(source_extra=10, num_threads=10), ) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16) with rasterio.open(COG) as src_dst: arr, mask = reader.part( src_dst, bounds, tilesize, tilesize, vrt_options=dict(source_extra=10, num_threads=10), ) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
def test_tile_read_valid(): """Should work as expected (read landsat band).""" # Tile 7-43-24 - Full tile bounds = [ -6574807.42497772, 12210356.646387195, -6261721.357121638, 12523442.714243278, ] with rasterio.open(COG) as src_dst: arr, mask = reader.part(src_dst, bounds, 16, 16, dst_crs=constants.WEB_MERCATOR_CRS) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16) # Read bounds at full resolution with rasterio.open(COG) as src_dst: arr, mask = reader.part(src_dst, bounds, dst_crs=constants.WEB_MERCATOR_CRS) assert arr.shape == (1, 893, 893) assert mask.shape == (893, 893) # set max_size for the returned array with rasterio.open(COG) as src_dst: arr, mask = reader.part(src_dst, bounds, max_size=50, dst_crs=constants.WEB_MERCATOR_CRS) assert arr.shape == (1, 50, 50) assert mask.shape == (50, 50) # If max_size is bigger than actual size, there is no effect with rasterio.open(COG) as src_dst: arr, mask = reader.part(src_dst, bounds, max_size=1000, dst_crs=constants.WEB_MERCATOR_CRS) assert arr.shape == (1, 893, 893) assert mask.shape == (893, 893) # Incompatible max_size with height and width with pytest.warns(UserWarning): with rasterio.open(COG) as src_dst: arr, mask = reader.part( src_dst, bounds, max_size=50, width=25, height=25, dst_crs=constants.WEB_MERCATOR_CRS, ) assert arr.shape == (1, 25, 25) assert mask.shape == (25, 25)
def test_tile_read_invalidResampling(): """Should raise an error on invalid resampling method name.""" bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) with pytest.raises(KeyError): with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: reader.part(src_dst, bounds, 16, 16, resampling_method="jacques")
def test_tile_read_invalidResampling(): """Should raise an error on invalid resampling method name.""" bounds = [ -6574807.42497772, 12210356.646387195, -6261721.357121638, 12523442.714243278, ] with pytest.raises(KeyError): with rasterio.open(COG) as src_dst: reader.part(src_dst, bounds, 16, 16, resampling_method="jacques")
def test_tile_read_not_covering_the_whole_tile(): """Should raise an error when dataset doesn't cover more than 50% of the tile.""" bounds = ( -11271098.442818949, 12210356.646387195, -10958012.374962866, 12523442.714243278, ) tilesize = 16 with pytest.raises(TileOutsideBounds): with rasterio.open(COG) as src_dst: reader.part(src_dst, bounds, tilesize, tilesize, minimum_overlap=0.6)
def test_tile_read_not_covering_the_whole_tile(): """Should raise an error when dataset doesn't cover more than 50% of the tile.""" bounds = ( -9079495.967826376, 3991847.365165044, -9001224.450862356, 4070118.882129065, ) tilesize = 16 with pytest.raises(TileOutsideBounds): with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: reader.part(src_dst, bounds, tilesize, tilesize, minimum_overlap=0.6)
def test_tile_read_valid(): """Should work as expected (read landsat band).""" bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, mask = reader.part( src_dst, bounds, 16, 16, dst_crs=constants.WEB_MERCATOR_CRS ) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16) # Read bounds at full resolution with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, mask = reader.part(src_dst, bounds, dst_crs=constants.WEB_MERCATOR_CRS) assert arr.shape == (1, 73, 73) assert mask.shape == (73, 73) # set max_size for the returned array with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, mask = reader.part( src_dst, bounds, max_size=50, dst_crs=constants.WEB_MERCATOR_CRS ) assert arr.shape == (1, 50, 50) assert mask.shape == (50, 50) # If max_size is bigger than actual size, there is no effect with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, mask = reader.part( src_dst, bounds, max_size=80, dst_crs=constants.WEB_MERCATOR_CRS ) assert arr.shape == (1, 73, 73) assert mask.shape == (73, 73) # Incompatible max_size with height and width with pytest.warns(UserWarning): with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, mask = reader.part( src_dst, bounds, max_size=50, width=25, height=25, dst_crs=constants.WEB_MERCATOR_CRS, ) assert arr.shape == (1, 25, 25) assert mask.shape == (25, 25)
def test_resampling_returns_different_results(): bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, _ = reader.part(src_dst, bounds, 16, 16) arr2, _ = reader.part(src_dst, bounds, 16, 16, resampling_method="nearest") assert not numpy.array_equal(arr, arr2)
def read_tile(src_path, tile): """Benchmark rio-tiler.utils._tile_read.""" tile_bounds = mercantile.xy_bounds(tile) # We make sure to not store things in cache. with rasterio.Env(GDAL_CACHEMAX=0, NUM_THREADS="all"): with rasterio.open(src_path) as src_dst: return reader.part( src_dst, tile_bounds, 256, 256, resampling_method="nearest" )
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) with rasterio.Env(GDAL_DISABLE_READDIR_ON_OPEN="TRUE"): with rasterio.open(S3_EXTMASK_PATH) as src_dst: arr, mask = reader.part(src_dst, bounds, 256, 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) with rasterio.Env(GDAL_DISABLE_READDIR_ON_OPEN="EMPTY_DIR"): with rasterio.open(S3_MASK_PATH) as src_dst: arr, mask = reader.part(src_dst, bounds, 256, 256) assert arr.shape == (3, 256, 256) assert not mask.all()
def test_tile_read_validResampling(): """Should return a 1 band array and a mask.""" bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, mask = reader.part(src_dst, bounds, 16, 16, resampling_method="bilinear") assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
def test_tile_read_bgr(): """Should work as expected (read rgb)""" bounds = ( -11663507.036777973, 4715018.0897710975, -11663487.927520901, 4715037.199028169, ) with rasterio.open(S3_PATH) as src_dst: arr, mask = reader.part(src_dst, bounds, 16, 16, indexes=(3, 2, 1)) assert arr.shape == (3, 16, 16) assert mask.shape == (16, 16)
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 with rasterio.open(S3_PATH) as src_dst: # Test target CRS with input bounds in bounds_crs arr, mask = reader.part( src_dst, bounds, tilesize, tilesize, indexes=(3, 2, 1), dst_crs=constants.WGS84_CRS, bounds_crs=constants.WEB_MERCATOR_CRS, ) 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, _ = reader.part( src_dst, bounds, tilesize, tilesize, indexes=(3, 2, 1), dst_crs=constants.WGS84_CRS, ) assert numpy.array_equal(arr, arr_crs)
def test_tile_read_validMask(): """Dataset mask should be the same as the actual mask.""" bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) tilesize = 128 with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, mask = reader.part(src_dst, bounds, tilesize, tilesize, nodata=0) masknodata = (arr[0] != 0).astype(numpy.uint8) * 255 numpy.testing.assert_array_equal(mask, masknodata)
def test_tile_read_validMask(): """Dataset mask should be the same as the actual mask.""" bounds = [ -6887893.4928338025, 12210356.646387195, -6574807.424977721, 12523442.714243278, ] tilesize = 128 with rasterio.open(COG) as src_dst: arr, mask = reader.part(src_dst, bounds, tilesize, tilesize, nodata=1) masknodata = (arr[0] != 1).astype(numpy.uint8) * 255 numpy.testing.assert_array_equal(mask, masknodata)
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_dst: arr, mask = reader.part(src_dst, bounds, tilesize, tilesize) assert arr.shape == (3, 16, 16) assert not mask.all()
def test_tile_read_dataset(): """Should work as expected""" address = f"{LANDSAT_PATH}_B2.TIF" bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) tilesize = 16 with rasterio.open(address) as src_dst: arr, mask = reader.part(src_dst, bounds, tilesize, 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.""" # Partial Tile 7-42-24 bounds = [ -6887893.4928338025, 12210356.646387195, -6574807.424977721, 12523442.714243278, ] tilesize = 16 with rasterio.open(COG) as src_dst: arr, mask = reader.part(src_dst, bounds, tilesize, tilesize, nodata=1) 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 with rasterio.open(PIX4D_PATH) as src_dst: arr, mask = reader.part(src_dst, bounds, tilesize, tilesize, indexes=[1, 2, 3]) assert arr.shape == (3, 16, 16) assert mask.shape == (16, 16) assert not mask.all()
def test_tile_read_nodata(): """Should work as expected when forcing nodata value.""" bounds = ( -9040360.209344367, 3991847.365165044, -9001224.450862356, 4030983.1236470537, ) tilesize = 16 with rasterio.open(f"{LANDSAT_PATH}_B4.TIF") as src_dst: arr, mask = reader.part(src_dst, bounds, tilesize, tilesize, nodata=0) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16) assert not mask.all()
def read_tile(self, z, x, y): """Read raster tile data and mask.""" with rasterio.open(self.path) as src: mercator_tile = mercantile.Tile(x=x, y=y, z=z) tile_bounds = mercantile.xy_bounds(mercator_tile) data, mask = part( src, tile_bounds, self.tiles_size, self.tiles_size, indexes=self.indexes, nodata=self.nodata, ) data = (data[0] + data[1]) / 2 return data.astype(numpy.uint8), mask
def area( address: str, bbox: Tuple[float, float, float, float], dst_crs: Optional[CRS] = None, bounds_crs: CRS = constants.WGS84_CRS, max_size: int = 1024, **kwargs: Any, ) -> Tuple[numpy.ndarray, numpy.ndarray]: """ Read value from a bbox. Attributes ---------- address: str file url. bbox: tuple bounds to read (left, bottom, right, top) in "bounds_crs". dst_crs: CRS or str, optional Target coordinate reference system, default is the dataset CRS. bounds_crs: CRS or str, optional bounds coordinate reference system, default is "epsg:4326" max_size: int, optional Limit output size array, default is 1024. kwargs: dict, optional These will be passed to the 'rio_tiler.reader.part' function. Returns ------- data : numpy ndarray mask: numpy array """ with rasterio.open(address) as src_dst: if not dst_crs: dst_crs = src_dst.crs return reader.part( src_dst, bbox, max_size=max_size, bounds_crs=bounds_crs, dst_crs=dst_crs, **kwargs, )
def test_tile_read_vrt_option(): """Should work as expected (read landsat band).""" bounds = ( -8844681.416934313, 3757032.814272982, -8766409.899970293, 3835304.331237001, ) tilesize = 16 with rasterio.open(f"{LANDSAT_PATH}_B2.TIF") as src_dst: arr, mask = reader.part( src_dst, bounds, tilesize, tilesize, warp_vrt_option=dict(source_extra=10, num_threads=10), ) assert arr.shape == (1, 16, 16) assert mask.shape == (16, 16)
def tile( self, tile_x: int, tile_y: int, tile_z: int, tilesize: int = 256, indexes: Optional[Sequence] = None, expression: Optional[str] = "", **kwargs: Any, ) -> Tuple[numpy.ndarray, numpy.ndarray]: """Read a TMS map tile from a COG.""" kwargs = {**self._kwargs, **kwargs} if isinstance(indexes, int): indexes = (indexes, ) if expression: indexes = parse_expression(expression) tile = morecantile.Tile(x=tile_x, y=tile_y, z=tile_z) if not self._tile_exists(tile): raise TileOutsideBounds( "Tile {}/{}/{} is outside image bounds".format( tile_z, tile_x, tile_y)) tile_bounds = self.tms.xy_bounds(*tile) tile, mask = reader.part( self.dataset, tile_bounds, tilesize, tilesize, dst_crs=self.tms.crs, indexes=indexes, **kwargs, ) if expression: blocks = expression.lower().split(",") bands = [f"b{bidx}" for bidx in indexes] tile = apply_expression(blocks, bands, tile) return tile, mask