def test_resolution(): """ Test for :func:`esmf_regrid.experimental.unstructured_scheme.MeshToGridESMFRegridder`. Tests for the resolution keyword. """ mesh_cube = _flat_mesh_cube() lon_bounds = (-180, 180) lat_bounds = (-90, 90) lon_bands = _grid_cube(1, 4, lon_bounds, lat_bounds) lat_bands = _grid_cube(4, 1, lon_bounds, lat_bounds) resolution = 8 lon_band_rg = MeshToGridESMFRegridder(mesh_cube, lon_bands, resolution=resolution) assert lon_band_rg.resolution == resolution assert lon_band_rg.regridder.tgt.resolution == resolution lat_band_rg = MeshToGridESMFRegridder(mesh_cube, lat_bands, resolution=resolution) assert lat_band_rg.resolution == resolution assert lat_band_rg.regridder.tgt.resolution == resolution
def test_flat_cubes(): """ Basic test for :func:`esmf_regrid.experimental.unstructured_scheme.MeshToGridESMFRegridder`. Tests with flat cubes as input (a 1D mesh cube and a 2D grid cube). """ src = _flat_mesh_cube() n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) tgt = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) # Ensure data in the target grid is different to the expected data. # i.e. target grid data is all zero, expected data is all one tgt.data[:] = 0 src = _add_metadata(src) src.data[:] = 1 # Ensure all data in the source is one. regridder = MeshToGridESMFRegridder(src, tgt) result = regridder(src) expected_data = np.ones([n_lats, n_lons]) expected_cube = _add_metadata(tgt) # Lenient check for data. assert np.allclose(expected_data, result.data) # Check metadata and scalar coords. expected_cube.data = result.data assert expected_cube == result
def test_mask_handling(): """ Test masked data handling for :func:`esmf_regrid.experimental.unstructured_scheme.GridToMeshESMFRegridder`. Tests masked data handling for multiple valid values for mdtol. """ tgt = _flat_mesh_cube() n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) src = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) data = np.ones([n_lats, n_lons]) mask = np.zeros([n_lats, n_lons]) mask[0, 0] = 1 masked_data = ma.array(data, mask=mask) src.data = masked_data regridder_0 = GridToMeshESMFRegridder(src, tgt, mdtol=0) regridder_05 = GridToMeshESMFRegridder(src, tgt, mdtol=0.05) regridder_1 = GridToMeshESMFRegridder(src, tgt, mdtol=1) result_0 = regridder_0(src) result_05 = regridder_05(src) result_1 = regridder_1(src) expected_data = np.ones(tgt.shape) expected_0 = ma.array(expected_data) expected_05 = ma.array(expected_data, mask=[0, 0, 1, 0, 0, 0]) expected_1 = ma.array(expected_data, mask=[1, 0, 1, 0, 0, 0]) assert ma.allclose(expected_0, result_0.data) assert ma.allclose(expected_05, result_05.data) assert ma.allclose(expected_1, result_1.data)
def test_mistmatched_mesh(): """ Test the calling of :func:`esmf_regrid.experimental.unstructured_scheme.MeshToGridESMFRegridder`. Checks that an error is raised when the regridder is called with a cube whose mesh does not match the one used for initialisation. """ n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) tgt = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) src = _gridlike_mesh_cube(n_lons, n_lats) other_loc = _gridlike_mesh_cube(n_lons, n_lats, location="node") other_src = _flat_mesh_cube() rg = MeshToGridESMFRegridder(src, tgt) with pytest.raises(ValueError) as excinfo: _ = rg(tgt) expected_message = "The given cube is not defined on a mesh." assert expected_message in str(excinfo.value) with pytest.raises(ValueError) as excinfo: _ = rg(other_loc) expected_message = ("The given cube is not defined on a the same " "mesh location as this regridder.") assert expected_message in str(excinfo.value) with pytest.raises(ValueError) as excinfo: _ = rg(other_src) expected_message = ( "The given cube is not defined on the same source mesh as this regridder." ) assert expected_message in str(excinfo.value)
def test_resolution(): """ Basic test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_unstructured_to_rectilinear`. Tests the resolution keyword with grids that would otherwise not work. """ src = _flat_mesh_cube() # The resulting grid has full latitude bounds and cells must be split up. n_lons = 1 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) tgt = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds) # Ensure data in the target grid is different to the expected data. # i.e. target grid data is all zero, expected data is all one tgt.data[:] = 0 src = _add_metadata(src) src.data[:] = 1 # Ensure all data in the source is one. result = regrid_unstructured_to_rectilinear(src, tgt, resolution=8) expected_data = np.ones([n_lats, n_lons]) expected_cube = _add_metadata(tgt) # Lenient check for data. # Note that when resolution=None, this would be a fully masked array. assert np.allclose(expected_data, result.data) # Check metadata and scalar coords. expected_cube.data = result.data assert expected_cube == result
def test_mismatched_grids(): """ Test error handling in calling of :func:`esmf_regrid.experimental.unstructured_scheme.GridToMeshESMFRegridder`. Checks that an error is raised when the regridder is called with a cube whose grid does not match with the one used when initialising the regridder. """ tgt = _flat_mesh_cube() n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) src = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) regridder = GridToMeshESMFRegridder(src, tgt) n_lons_other = 3 n_lats_other = 10 src_other = _grid_cube(n_lons_other, n_lats_other, lon_bounds, lat_bounds, circular=True) with pytest.raises(ValueError): _ = regridder(src_other)
def test_multidim_cubes(): """ Test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_rectilinear_to_unstructured`. Tests with multidimensional cubes. The source cube contains coordinates on the dimensions before and after the grid dimensions. """ tgt = _flat_mesh_cube() mesh = tgt.mesh mesh_length = mesh.connectivity(contains_face=True).shape[0] n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) grid = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) h = 2 t = 3 height = DimCoord(np.arange(h), standard_name="height") time = DimCoord(np.arange(t), standard_name="time") src_data = np.empty([t, n_lats, n_lons, h]) src_data[:] = np.arange(t * h).reshape([t, h])[:, np.newaxis, np.newaxis, :] cube = Cube(src_data) cube.add_dim_coord(grid.coord("latitude"), 1) cube.add_dim_coord(grid.coord("longitude"), 2) cube.add_dim_coord(time, 0) cube.add_dim_coord(height, 3) regridder = GridToMeshESMFRegridder(grid, tgt) result = regridder(cube) # Lenient check for data. expected_data = np.empty([t, mesh_length, h]) expected_data[:] = np.arange(t * h).reshape(t, h)[:, np.newaxis, :] assert np.allclose(expected_data, result.data) mesh_coord_x, mesh_coord_y = mesh.to_MeshCoords("face") expected_cube = Cube(expected_data) expected_cube.add_dim_coord(time, 0) expected_cube.add_aux_coord(mesh_coord_x, 1) expected_cube.add_aux_coord(mesh_coord_y, 1) expected_cube.add_dim_coord(height, 2) # Check metadata and scalar coords. result.data = expected_data assert expected_cube == result
def test_invalid_mdtol(): """ Test initialisation of :func:`esmf_regrid.experimental.unstructured_scheme.MeshToGridESMFRegridder`. Checks that an error is raised when mdtol is out of range. """ src = _flat_mesh_cube() n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) tgt = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) with pytest.raises(ValueError): _ = MeshToGridESMFRegridder(src, tgt, mdtol=2) with pytest.raises(ValueError): _ = MeshToGridESMFRegridder(src, tgt, mdtol=-1)
def test_resolution(): """ Test for :func:`esmf_regrid.experimental.unstructured_scheme.GridToMeshESMFRegridder`. Tests for the resolution keyword. """ tgt = _flat_mesh_cube() n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) grid = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) resolution = 8 result = GridToMeshESMFRegridder(grid, tgt, resolution=resolution) assert result.resolution == resolution assert result.regridder.src.resolution == resolution
def test_flat_cubes(): """ Basic test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_rectilinear_to_unstructured`. Tests with flat cubes as input (a 2D grid cube and a 1D mesh cube). """ tgt = _flat_mesh_cube() n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) src = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) # Ensure data in the target grid is different to the expected data. # i.e. target grid data is all zero, expected data is all one tgt.data[:] = 0 src = _add_metadata(src) src.data[:] = 1 # Ensure all data in the source is one. result = regrid_rectilinear_to_unstructured(src, tgt) src_T = src.copy() src_T.transpose() result_transposed = regrid_rectilinear_to_unstructured(src_T, tgt) expected_data = np.ones_like(tgt.data) expected_cube = _add_metadata(tgt) # Lenient check for data. assert np.allclose(expected_data, result.data) assert np.allclose(expected_data, result_transposed.data) # Check metadata and scalar coords. expected_cube.data = result.data assert expected_cube == result expected_cube.data = result_transposed.data assert expected_cube == result_transposed
def test_multidim_cubes(): """ Test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_rectilinear_to_unstructured`. Tests with multidimensional cubes. The source cube contains coordinates on the dimensions before and after the grid dimensions. """ tgt = _flat_mesh_cube() mesh = tgt.mesh mesh_length = mesh.connectivity(contains_face=True).shape[0] n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) grid = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) h = 2 p = 4 t = 3 height = DimCoord(np.arange(h), standard_name="height") pressure = DimCoord(np.arange(p), standard_name="air_pressure") time = DimCoord(np.arange(t), standard_name="time") spanning = AuxCoord(np.ones([t, p, h]), long_name="spanning dim") ignore = AuxCoord(np.ones([n_lats, h]), long_name="ignore") src_data = np.empty([t, n_lats, p, n_lons, h]) src_data[:] = np.arange(t * p * h).reshape([t, p, h])[:, np.newaxis, :, np.newaxis, :] cube = Cube(src_data) cube.add_dim_coord(grid.coord("latitude"), 1) cube.add_dim_coord(grid.coord("longitude"), 3) cube.add_dim_coord(time, 0) cube.add_dim_coord(pressure, 2) cube.add_dim_coord(height, 4) cube.add_aux_coord(spanning, [0, 2, 4]) cube.add_aux_coord(ignore, [1, 4]) result = regrid_rectilinear_to_unstructured(cube, tgt) cube_transposed = cube.copy() cube_transposed.transpose([0, 3, 2, 1, 4]) result_transposed = regrid_rectilinear_to_unstructured( cube_transposed, tgt) # Lenient check for data. expected_data = np.empty([t, mesh_length, p, h]) expected_data[:] = np.arange(t * p * h).reshape(t, p, h)[:, np.newaxis, :, :] assert np.allclose(expected_data, result.data) assert np.allclose(expected_data, result_transposed.data) mesh_coord_x, mesh_coord_y = mesh.to_MeshCoords("face") expected_cube = Cube(expected_data) expected_cube.add_dim_coord(time, 0) expected_cube.add_aux_coord(mesh_coord_x, 1) expected_cube.add_aux_coord(mesh_coord_y, 1) expected_cube.add_dim_coord(pressure, 2) expected_cube.add_dim_coord(height, 3) expected_cube.add_aux_coord(spanning, [0, 2, 3]) # Check metadata and scalar coords. result.data = expected_data assert expected_cube == result result_transposed.data = expected_data assert expected_cube == result_transposed