def test_availability_matrix_rastered_repro(ref, raster_reproject): """ Availability matrix with a non-zero raster must have less available area than the Indicator matrix. Test this with a raster of a different crs. """ shapes = gpd.GeoSeries( [ box(X0 + 1, Y0 + 1, X1 - 1, Y0 / 2 + Y1 / 2), box(X0 + 1, Y0 / 2 + Y1 / 2, X1 - 1, Y1 - 1), ], crs=ref.crs, ).rename_axis("shape") I = np.asarray(ref.indicatormatrix(shapes).todense()) I = I.reshape(shapes.shape + ref.shape) I = xr.DataArray(I, coords=[shapes.index, ref.coords["y"], ref.coords["x"]]) excluder = ExclusionContainer() excluder.add_raster(raster_reproject) ds = ref.availabilitymatrix(shapes, excluder) eligible_share = 1 - raster_clip assert isclose(I.sum() * eligible_share, ds.sum(), atol=5) assert_allclose(I.sum(["x", "y"]) * eligible_share, ds.sum(["x", "y"]), atol=5)
def test_availability_matrix_rastered(ref, raster): """ Availability matrix with a non-zero raster must have less available area than the Indicator matrix. """ shapes = gpd.GeoSeries([ box(X0 + 1, Y0 + 1, X1 - 1, Y0 / 2 + Y1 / 2), box(X0 + 1, Y0 / 2 + Y1 / 2, X1 - 1, Y1 - 1) ], crs=ref.crs).rename_axis('shape') I = np.asarray(ref.indicatormatrix(shapes).todense()) I = I.reshape(shapes.shape + ref.shape) I = xr.DataArray(I, coords=[('shape', shapes.index), ref.coords['y'], ref.coords['x']]) excluder = ExclusionContainer(ref.crs, res=0.01) excluder.add_raster(raster) ds = ref.availabilitymatrix(shapes, excluder) eligible_share = 1 - raster_clip assert isclose(I.sum() * eligible_share, ds.sum(), atol=5) assert_allclose(I.sum(['x', 'y']) * eligible_share, ds.sum(['x', 'y']), atol=5) # check parallel mode excluder = ExclusionContainer(ref.crs, res=0.01) excluder.add_raster(raster) assert_equal(ds, ref.availabilitymatrix(shapes, excluder, 2))
def test_availability_matrix_flat_parallel_wo_progressbar(ref): """ Same as `test_availability_matrix_flat` but parallel and without progressbar. """ shapes = gpd.GeoSeries([box(X0+1, Y0+1, X1-1, Y1-1)], crs=ref.crs).rename_axis('shape') I = ref.indicatormatrix(shapes).sum(0).reshape(ref.shape) I = xr.DataArray(I, coords=[ref.coords['y'], ref.coords['x']]) excluder = ExclusionContainer(ref.crs, res=0.01) ds = ref.availabilitymatrix(shapes, excluder, nprocesses=2, disable_progressbar=True) assert np.allclose(I, ds.sum('shape'))
def test_availability_matrix_flat(ref): """ Indicator matrix and availability matrix for an empty excluder must be the same. """ shapes = gpd.GeoSeries([box(X0+1, Y0+1, X1-1, Y1-1)], crs=ref.crs).rename_axis('shape') I = ref.indicatormatrix(shapes).sum(0).reshape(ref.shape) I = xr.DataArray(I, coords=[ref.coords['y'], ref.coords['x']]) excluder = ExclusionContainer(ref.crs, res=0.01) ds = ref.availabilitymatrix(shapes, excluder) assert np.allclose(I, ds.sum('shape'))
def test_shape_availability_area(ref): """Area of the mask and the shape must be close.""" shapes = gpd.GeoSeries([box(X0+1, Y0+1, X1-1, Y1-1)], crs=ref.crs) res = 100 excluder = ExclusionContainer(res=res) with pytest.raises(AssertionError): masked, transform = shape_availability(shapes, excluder) shapes = shapes.to_crs(3035) masked, transform = shape_availability(shapes, excluder) assert np.isclose(shapes.area, masked.sum() * res ** 2)
def test_shape_availability_exclude_geometry(ref): """ When excluding the quarter of the geometry, the eligible area must be a forth. Test the inverted case too. """ shapes = gpd.GeoSeries([box(X0, Y0, X1, Y1)], crs=ref.crs) exclude = gpd.GeoSeries([box(X0/2+X1/2, Y0/2+Y1/2, X1, Y1)], crs=ref.crs) res = 0.01 excluder = ExclusionContainer(ref.crs, res=res) excluder.add_geometry(exclude) masked, transform = shape_availability(shapes, excluder) area = shapes.geometry[0].area # get area without warning assert isclose(3*area/4, masked.sum() * res ** 2) excluder = ExclusionContainer(ref.crs, res=res) excluder.add_geometry(exclude, invert=True) masked, transform = shape_availability(shapes, excluder) area = shapes.geometry[0].area # get area without warning assert isclose(area/4, masked.sum() * res ** 2)
def test_shape_availability_exclude_raster_codes(ref, raster_codes): """Test exclusion of multiple raster codes.""" shapes = gpd.GeoSeries([box(X0, Y0, X1, Y1)], crs=ref.crs) res = 0.01 excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster_codes, codes=range(20)) masked, transform = shape_availability(shapes, excluder) ratio = masked.sum() / masked.size assert round(ratio, 1) == 0.8 excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster_codes, codes=range(20), invert=True) masked, transform = shape_availability(shapes, excluder) ratio = masked.sum() / masked.size assert round(ratio, 1) == 0.2 # test with a function excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster_codes, codes=lambda x: x<20, invert=True) masked, transform = shape_availability(shapes, excluder) assert ratio == masked.sum() / masked.size
def test_shape_availability_excluder_raster_no_overlap(ref, raster): """Check if the allow_no_overlap flag works.""" bounds = X0-10., Y0-10., X0-2., Y0-2. area = abs((bounds[2] - bounds[0]) * (bounds[3] - bounds[1])) shapes = gpd.GeoSeries([box(*bounds)], crs=ref.crs) res = 0.01 excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster) with pytest.raises(ValueError): masked, transform = shape_availability(shapes, excluder) excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, allow_no_overlap=True) masked, transform = shape_availability(shapes, excluder) assert (masked == 0).all() excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, allow_no_overlap=True, codes=[1, 255], invert=True) masked, transform = shape_availability(shapes, excluder) assert (masked.sum() * (res ** 2) == area) excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, allow_no_overlap=True, nodata=0) masked, transform = shape_availability(shapes, excluder) assert (masked.sum() * (res ** 2) == area)
def test_shape_availability_excluder_partial_overlap(ref, raster): """Test behavior, when a raster only overlaps half of the geometry.""" bounds = X0-2, Y0, X0+2, Y1 area = abs((bounds[2] - bounds[0]) * (bounds[3] - bounds[1])) shapes = gpd.GeoSeries([box(*bounds)], crs=ref.crs) res = 0.01 excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, codes=[0, 1]) masked, transform = shape_availability(shapes, excluder) assert (masked.sum() * (res ** 2) == area/2) excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, nodata=0) masked, transform = shape_availability(shapes, excluder) assert (masked.sum() * (res ** 2) > area/2) excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, nodata=1) masked, transform = shape_availability(shapes, excluder) assert (masked.sum() * (res ** 2) < area/2)
def test_shape_availability_exclude_raster(ref, raster): """When excluding the half of the geometry, the eligible area must be half.""" shapes = gpd.GeoSeries([box(X0, Y0, X1, Y1)], crs=ref.crs) res = 0.01 excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster) masked, transform = shape_availability(shapes, excluder) ratio = masked.sum() / masked.size assert round(ratio, 2) == (1 - raster_clip) excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, invert=True) masked, transform = shape_availability(shapes, excluder) ratio = masked.sum() / masked.size assert round(ratio, 2) == raster_clip excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, buffer=res) masked, transform = shape_availability(shapes, excluder) ratio = masked.sum() / masked.size # should be close to zero assert round(ratio, 2) < (1-raster_clip) excluder = ExclusionContainer(ref.crs, res=res) excluder.add_raster(raster, buffer=res, invert=True) masked, transform = shape_availability(shapes, excluder) ratio2 = masked.sum() / masked.size # for the case that we have more excluded area and this is buffered if raster_clip < 0.5: assert ratio >= ratio2 else: assert ratio <= ratio2
def test_exclusioncontainer_geometries(): crs = 3035 shapes = gpd.GeoSeries([box(X0, Y0, X1, Y1)], crs=crs) exclude = gpd.GeoSeries([box(X0/2+X1/2, Y0/2+Y1/2, X1, Y1)], crs=crs) res = 0.01 excluder = ExclusionContainer(crs, res=res) excluder.add_geometry(exclude, buffer=1) excluder.open_files() assert (excluder.geometries[0]['geometry'] != exclude).all() excluder.open_files() buffered = excluder.geometries[0]['geometry'] # open again and check that the buffer remains the same assert (excluder.geometries[0]['geometry'] == buffered).all() # should take GeoDataFrames and the result is the same excluder = ExclusionContainer(crs, res=res) excluder.add_geometry(exclude.to_frame('geometry'), buffer=1) excluder.open_files() assert (excluder.geometries[0]['geometry'] == buffered).all()