def tiles(strata, target_crs): """Create rectangular polygons in required crs from raster bounds. Args: strata (list of str/Path): Full qualified path to raster files. target_crs (rasterio.crs.CRS): Reproject raster bounds to this crs. Returns: geopandas.GeoSeries: The convex hull of the rasters as a GeoSeries. """ total = len(strata) polygons = [] for idx, raster in enumerate(strata): with Env(): with open(raster) as src: crs = src.crs bounds = src.bounds if crs != target_crs: bounds = reproject_bounds(bounds, crs, target_crs) polygon = polygon_from(bounds) polygons.append(polygon) progress(pending=total - (idx + 1), total=total) geometry = gpd.GeoSeries(polygons) geometry.crs = target_crs return geometry
def transform(src_crs, dst_crs, xs, ys, zs=None, **options): """Transform vectors from source to target coordinate reference system. Transform vectors of x, y and optionally z from source coordinate reference system into target. Parameters ------------ src_crs: CRS or dict Source coordinate reference system, as a rasterio CRS object. Example: CRS({'init': 'EPSG:4326'}) dst_crs: CRS or dict Target coordinate reference system. xs: array_like Contains x values. Will be cast to double floating point values. ys: array_like Contains y values. zs: array_like, optional Contains z values. Assumed to be all 0 if absent. Returns --------- out: tuple of array_like, (xs, ys, [zs]) Tuple of x, y, and optionally z vectors, transformed into the target coordinate reference system. """ with Env(**options): return _transform(src_crs, dst_crs, xs, ys, zs)
def test_rasterize_shapes_out_dtype_mismatch(basic_geometry): """ Shape values must be able to fit in data type for out """ out = numpy.zeros(DEFAULT_SHAPE, dtype=numpy.uint8) with Env(): with pytest.raises(ValueError): rasterize([(basic_geometry, 10000000)], out=out)
def test_reproject_ndarray(): with Env(): with rasterio.open('tests/data/RGB.byte.tif') as src: source = src.read(1) dst_crs = dict(proj='merc', a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units='m', nadgrids='@null', wktext=True, no_defs=True) out = numpy.empty(src.shape, dtype=numpy.uint8) reproject(source, out, src_transform=src.transform, src_crs=src.crs, dst_transform=DST_TRANSFORM, dst_crs=dst_crs, resampling=Resampling.nearest) assert (out > 0).sum() == 438146
def test_sieve_large(basic_image): """ Setting the size larger than size of feature should leave us an empty image. """ with Env(): assert not numpy.any(sieve(basic_image, basic_image.sum() + 1))
def test_geometry_mask(basic_geometry, basic_image_2x2): with Env(): assert numpy.array_equal( basic_image_2x2 == 0, geometry_mask([basic_geometry], out_shape=DEFAULT_SHAPE, transform=Affine.identity()))
def test_rasterize_invalid_out_dtype(basic_geometry): """ A non-supported data type for out should raise an exception """ out = numpy.zeros(DEFAULT_SHAPE, dtype=numpy.int64) with Env(): with pytest.raises(ValueError): rasterize([basic_geometry], out=out)
def test_rasterize_supported_dtype(basic_geometry): """ Supported data types should return valid results """ with Env(): supported_types = (('int16', -32768), ('int32', -2147483648), ('uint8', 255), ('uint16', 65535), ('uint32', 4294967295), ('float32', 1.434532), ('float64', -98332.133422114)) for dtype, default_value in supported_types: truth = numpy.zeros(DEFAULT_SHAPE, dtype=dtype) truth[2:4, 2:4] = default_value result = rasterize([basic_geometry], out_shape=DEFAULT_SHAPE, default_value=default_value, dtype=dtype) assert numpy.array_equal(result, truth) assert numpy.dtype(result.dtype) == numpy.dtype(truth.dtype) result = rasterize([(basic_geometry, default_value)], out_shape=DEFAULT_SHAPE) if numpy.dtype(dtype).kind == 'f': assert numpy.allclose(result, truth) else: assert numpy.array_equal(result, truth)
def test_rasterize_all_touched(basic_geometry, basic_image): with Env(): assert numpy.array_equal( basic_image, rasterize([basic_geometry], out_shape=DEFAULT_SHAPE, all_touched=True))
def test_transform_bounds_no_change(): """ Make sure that going from and to the same crs causes no change """ with Env(): with rasterio.open('tests/data/RGB.byte.tif') as src: l, b, r, t = src.bounds assert numpy.allclose( transform_bounds(src.crs, src.crs, l, b, r, t), src.bounds)
def test_sieve_blank_mask(basic_image): """ A blank mask should have no effect """ mask = numpy.ones(basic_image.shape, dtype=rasterio.bool_) with Env(): assert numpy.array_equal( basic_image, sieve(basic_image, basic_image.sum(), mask=mask))
def test_reproject_multi(): """Ndarry to ndarray""" with Env(): with rasterio.open('tests/data/RGB.byte.tif') as src: source = src.read() dst_crs = dict(proj='merc', a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units='m', nadgrids='@null', wktext=True, no_defs=True) destin = numpy.empty(source.shape, dtype=numpy.uint8) reproject(source, destin, src_transform=src.transform, src_crs=src.crs, dst_transform=DST_TRANSFORM, dst_crs=dst_crs, resampling=Resampling.nearest) assert destin.any()
def test_rasterize_invalid_shapes(): """ Invalid shapes should raise an exception rather than be skipped """ with Env(): with pytest.raises(ValueError) as ex: rasterize([{'foo': 'bar'}], out_shape=DEFAULT_SHAPE) assert 'Invalid geometry object' in str(ex.value)
def test_shapes_connectivity_rook(diagonal_image): """ Diagonals are not connected, so there will be 1 feature per pixel plus background. """ with Env(): assert len(list(shapes(diagonal_image, connectivity=4))) == 12
def test_transform_bounds(): with Env(): with rasterio.open('tests/data/RGB.byte.tif') as src: l, b, r, t = src.bounds assert numpy.allclose( transform_bounds(src.crs, {'init': 'EPSG:4326'}, l, b, r, t), (-78.95864996545055, 23.564991210854686, -76.57492370013823, 25.550873767433984))
def test_rasterize_invalid_default_value(basic_geometry): """ A default value that requires an int64 should raise an exception """ with Env(): with pytest.raises(ValueError): rasterize([basic_geometry], out_shape=DEFAULT_SHAPE, default_value=1000000000000)
def test_shapes_connectivity_queen(diagonal_image): """ Diagonals are connected, so there will be 1 feature for all pixels plus background. """ with Env(): assert len(list(shapes(diagonal_image, connectivity=8))) == 2
def test_rasterize_missing_shapes(): """ Shapes are required for this operation """ with Env(): with pytest.raises(ValueError) as ex: rasterize([], out_shape=DEFAULT_SHAPE) assert 'No valid geometry objects' in str(ex.value)
def test_rasterize_invalid_value(basic_geometry): """ A shape value that requires an int64 should raise an exception """ with Env(): with pytest.raises(ValueError) as ex: rasterize([(basic_geometry, 1000000000000)], out_shape=DEFAULT_SHAPE) assert 'dtype must be one of' in str(ex.value)
def test_sieve_invalid_mask_dtype(basic_image): """ A mask that is the wrong dtype should fail """ with Env(): for dtype in ('int8', 'int16', 'int32'): with pytest.raises(ValueError): sieve(basic_image, basic_image.sum(), mask=numpy.ones(basic_image.shape, dtype=dtype))
def test_transform_bounds(): """CRSError is raised.""" with Env(): left, bottom, right, top = (-11740727.544603072, 4852834.0517692715, -11584184.510675032, 5009377.085697309) src_crs = 'EPSG:3857' dst_crs = {'proj': 'foobar'} with pytest.raises(CRSError): transform_bounds(src_crs, dst_crs, left, bottom, right, top)
def test_sieve_small(basic_image, pixelated_image): """ Setting the size smaller than or equal to the size of the feature in the image should not change the image. """ with Env(): assert numpy.array_equal(basic_image, sieve(pixelated_image, basic_image.sum()))
def test_sieve_out(basic_image): """ Output array passed in should match the returned array """ with Env(): output = numpy.zeros_like(basic_image) output[1:3, 1:3] = 5 sieved_image = sieve(basic_image, basic_image.sum(), out=output) assert numpy.array_equal(basic_image, sieved_image) assert numpy.array_equal(output, sieved_image)
def test_env_options(gdalenv): """Test env options.""" env = Env(foo='x') assert env.options == {'foo': 'x'} assert not env.previous_options assert getenv() == rasterio.env._env.options == {} with env: assert getenv() == rasterio.env._env.options == {'foo': 'x'} assert getenv() == rasterio.env._env.options == {}
def overview(ctx, input, build, ls, rebuild, resampling): """Construct overviews in an existing dataset. A pyramid of overviews computed once and stored in the dataset can improve performance in some applications. The decimation levels at which to build overviews can be specified as a comma separated list rio overview --build 2,4,8,16 or a base and range of exponents. rio overview --build 2^1..4 Note that overviews can not currently be removed and are not automatically updated when the dataset's primary bands are modified. Information about existing overviews can be printed using the --ls option. rio overview --ls """ verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1 with Env(CPL_DEBUG=(verbosity > 2)) as env: with rasterio.open(input, 'r+') as dst: if ls: resampling_method = dst.tags( ns='rio_overview').get('resampling') or 'unknown' click.echo("Overview factors:") for idx in dst.indexes: click.echo( " Band %d: %s (method: '%s')" % (idx, dst.overviews(idx) or 'None', resampling_method)) elif rebuild: # Build the same overviews for all bands. factors = reduce(operator.or_, [set(dst.overviews(i)) for i in dst.indexes]) # Attempt to recover the resampling method from dataset tags. resampling_method = dst.tags( ns='rio_overview').get('resampling') or resampling dst.build_overviews(list(factors), Resampling[resampling_method]) elif build: dst.build_overviews(build, Resampling[resampling]) # Save the resampling method to a tag. dst.update_tags(ns='rio_overview', resampling=resampling)
def test_rasterize_fill_value_dtype_mismatch(basic_geometry): """ A fill value that doesn't match dtype should fail """ with Env(): with pytest.raises(ValueError): rasterize([basic_geometry], out_shape=DEFAULT_SHAPE, fill=1000000, default_value=2, dtype=numpy.uint8)
def test_rasterize_geometries_symmetric(): """ Make sure that rasterize is symmetric with shapes """ transform = (1.0, 0.0, 0.0, 0.0, -1.0, 0.0) truth = numpy.zeros(DEFAULT_SHAPE, dtype=rasterio.ubyte) truth[2:5, 2:5] = 1 with Env(): s = shapes(truth, transform=transform) result = rasterize(s, out_shape=DEFAULT_SHAPE, transform=transform) assert numpy.array_equal(result, truth)
def test_shapes_blank_mask(basic_image): """ Mask is blank so results should mask shapes without mask """ with Env(): assert numpy.array_equal( list( shapes(basic_image, mask=numpy.ones(basic_image.shape, dtype=rasterio.bool_))), list(shapes(basic_image)))
def test_sieve_invalid_mask_shape(basic_image): """ A mask that is the wrong shape should fail """ with Env(): with pytest.raises(ValueError): sieve(basic_image, basic_image.sum(), mask=numpy.ones( (basic_image.shape[0] + 10, basic_image.shape[1] + 10), dtype=rasterio.bool_))
def test_gdal_transform_fail_src_crs(): with Env(): dt, dw, dh = _calculate_default_transform('+proj=foobar', {'init': 'EPSG:32610'}, width=80, height=80, left=-120, bottom=30, right=-80, top=70)
def _check_defaults(): for key in Env.default_options().keys(): assert get_gdal_config(key) is None