def test_reprojection_failure(): ds = generate_test_dataset() transform = warp.get_transform(ds) extent = warp.get_extent(ds) with assert_raises_regex( ValueError, ".* must also specify the `width` and `height`.*"): _ = warp.Reprojection(crs=epsg4326, transform=transform) with assert_raises_regex( ValueError, "Need to provide either `width` and `height` .*"): _ = warp.Reprojection(crs=epsg4326, extent=extent)
def test_reprojection_nan_values(): src_crs = epsg4326 dst_crs = sinusoidal ds = generate_test_dataset(crs=src_crs) bounds = warp.get_bounds(ds) proj = warp.Reprojection(crs=dst_crs) warped = proj.apply(ds) xgrid, ygrid = np.meshgrid(warped.x, warped.y) lon, lat = rasterio.warp.transform(dst_crs, src_crs, xgrid.flatten(), ygrid.flatten()) lon = np.array(lon).reshape(xgrid.shape) lat = np.array(lat).reshape(ygrid.shape) inside_bounds = np.logical_and( np.logical_and(lon >= bounds.left, lon <= bounds.right), np.logical_and(lat >= bounds.bottom, lat <= bounds.top) ) for v in warped.data_vars: if not set(warped[v].dims).issuperset({'y', 'x'}): continue dim_order = tuple(set(warped[v].dims) - {'y', 'x'}) + ('y', 'x') values = warped[v].transpose(*dim_order, transpose_coords=True).values # Check that pixels strictly inside the original bounds are not NaN assert np.isnan(values[..., inside_bounds]).sum() == 0 # Pixel outside of the original bounds should be mostly NaN, # although some pixels near the edges may have values. outside_values = values[..., ~inside_bounds] assert np.isnan(outside_values).sum() / outside_values.size > 0.5
def test_reprojection_with_target(generator): src_crs = epsg4326 dst_crs = sinusoidal ds = generator(crs=src_crs) src_bounds = warp.get_bounds(ds) dst_bounds_latlon = BoundingBox( left=src_bounds.left - 1, bottom=src_bounds.bottom - 1, right=src_bounds.right + 1, top=src_bounds.top + 1, ) dst_bounds = BoundingBox(*rasterio.warp.transform_bounds( src_crs, dst_crs, **dst_bounds_latlon._asdict() )) dst_width, dst_height = 35, 21 resx = (dst_bounds.right - dst_bounds.left) / (dst_width - 1) resy = (dst_bounds.bottom - dst_bounds.top) / (dst_height - 1) res = (abs(resx), abs(resy)) xoff = dst_bounds.left yoff = dst_bounds.top dst_transform = Affine(resx, 0, xoff, 0, resy, yoff) target = generator( dims={'x': dst_width, 'y': dst_height, 'time': 1}, extent=dst_bounds, crs=dst_crs ) projected = [ warp.Reprojection(crs=dst_crs, transform=dst_transform, width=dst_width, height=dst_height).apply(ds), warp.Reprojection(crs=dst_crs, extent=dst_bounds, res=res).apply(ds), warp.Reprojection(crs=dst_crs, extent=dst_bounds, width=dst_width, height=dst_height).apply(ds), warp.Reprojection(target=target).apply(ds), ] for i, proj in enumerate(projected[1:]): print(i) xr_assert_equal(proj, projected[0]) assert_almost_equal(warp.get_resolution(proj), res) assert_almost_equal(warp.get_bounds(proj), dst_bounds) assert_almost_equal(warp.get_transform(proj), dst_transform) assert_equal_crs(warp.get_crs(proj), dst_crs)
def test_reprojection_with_src_crs(): src_crs = epsg4326 dst_crs = sinusoidal # Set up test dataset with and without CRS information ds = generate_test_dataset(crs=src_crs) assert_equal_crs(src_crs, ds.nd.crs) ds_nocrs = ds.copy() del ds_nocrs.attrs['crs'] assert ds_nocrs.nd.crs is None with assert_raises_regex( CRSError, "Could not infer projection from input data. " "Please provide the parameter `src_crs`."): warp.Reprojection(dst_crs=dst_crs).apply(ds_nocrs) xr_assert_equal( warp.Reprojection(dst_crs=dst_crs).apply(ds), warp.Reprojection(src_crs=src_crs, dst_crs=dst_crs).apply(ds_nocrs) )
def test_reproject_coordinates(): ds = generate_test_dataset(crs=epsg4326) dims = warp.get_dim_sizes(ds) ds.coords['lat'] = ds['y'] ds.coords['lon'] = ds['x'] ds.coords['altitude'] = (('y', 'x'), np.zeros((dims['y'], dims['x']))) proj = warp.Reprojection(crs=sinusoidal) warped = proj.apply(ds) for c in ds.coords: if c in ['lat', 'lon']: continue assert c in warped.coords assert_equal(sorted(ds[c].dims), sorted(warped[c].dims))
def test_reproject_one_dimensional_coords(): ds = generate_test_dataset(crs=epsg4326) # Add coordinates that are not dimensions ds.coords['longitude'] = (('x',), ds.x.values) ds.coords['latitude'] = (('y',), ds.y.values) warped = warp.Reprojection( crs=warp.get_crs(ds), width=15, height=15, resampling=rasterio.warp.Resampling.bilinear ).apply(ds) # Check that xvar and yvar are still proportional to longitude # and latitude for coord, dim in [ ('longitude', 'x'), ('latitude', 'y') ]: assert_array_almost_equal( warped.coords[coord], warped.coords[dim])
def test_reproject_with_extra_dims(dims): crs1 = warp._parse_crs('epsg:4326') crs2 = warp._parse_crs('epsg:3395') ds = generate_test_dataset( dims=dims, crs=crs1 ) proj = warp.Reprojection(crs=crs2) reprojected = proj.apply(ds) # Check that a reprojected slice of the dataset is the same as # the slice of the reprojection of the entire dataset. slices = [ {'band': 3}, {'time': slice(1, 3)} ] for s in slices: xr_assert_equal( proj.apply(ds.isel(**s)), reprojected.isel(**s) )
def test_reproject_one_dimensional_vars(): ds = generate_test_dataset(crs=epsg4326) ds['xvar'] = (('x',), ds.x.values * 10) ds['yvar'] = (('y',), ds.y.values * 10) ds['timevar'] = (('time',), np.random.rand(ds.dims['time'])) warped = warp.Reprojection( crs=sinusoidal, resampling=rasterio.warp.Resampling.bilinear ).apply(ds) xr_assert_equal( warped['timevar'], ds['timevar']) # Check that xvar and yvar are still proportional to longitude # and latitude for v, coord in [ ('xvar', 'lon'), ('yvar', 'lat') ]: ratios = warped[v].values / warped[coord].values print(v, coord) print(np.nanmin(ratios), np.nanmax(ratios), np.nanstd(ratios)) # There is quite a bit of error, for now accept relatively # high error. assert np.nanstd(ratios) < 1.5
def test_get_common_extent(): bounds = [ (-10.0, 50.0, 0.0, 60.0), (-12.0, 40.0, -2.0, 52.0), (-13.0, 50.0, -3.0, 60.0), (-9.0, 51.0, 1.0, 61.0) ] common_extent = (-13.0, 40.0, 1.0, 61.0) datasets = [generate_test_dataset(extent=ext) for ext in bounds] # Reproject such that the projected bounds change, # but the extent remains the same: proj = warp.Reprojection(crs=sinusoidal) datasets_sinu = [proj.apply(ds) for ds in datasets] common_bounds = warp.get_common_bounds(datasets_sinu) expected_result = BoundingBox(*rasterio.warp.transform_bounds( sinusoidal, epsg4326, **common_bounds._asdict() )) assert_raises(AssertionError, assert_equal, common_bounds, common_extent) assert_almost_equal(warp.get_common_extent(datasets_sinu), expected_result)
def test_reprojection(name, kwargs): ds = generate_test_dataset(**kwargs) crs = warp._parse_crs('epsg:4326') proj = warp.Reprojection(crs=crs) reprojected = proj.apply(ds) assert_equal_crs(crs, warp.get_crs(reprojected))