def _make_mesh_to_grid_regridder(method="conservative",
                                 resolution=None,
                                 grid_dims=1,
                                 circular=True):
    src_lons = 3
    src_lats = 4
    tgt_lons = 5
    tgt_lats = 6
    lon_bounds = (-180, 180)
    lat_bounds = (-90, 90)
    if grid_dims == 1:
        tgt = _grid_cube(tgt_lons,
                         tgt_lats,
                         lon_bounds,
                         lat_bounds,
                         circular=circular)
    else:
        tgt = _curvilinear_cube(tgt_lons, tgt_lats, lon_bounds, lat_bounds)
    tgt.coord("longitude").var_name = "longitude"
    tgt.coord("latitude").var_name = "latitude"
    if method == "bilinear":
        location = "node"
    else:
        location = "face"
    src = _gridlike_mesh_cube(src_lons, src_lats, location=location)

    rg = MeshToGridESMFRegridder(src,
                                 tgt,
                                 method=method,
                                 mdtol=0.5,
                                 resolution=resolution)
    return rg, src
Beispiel #2
0
def test_curvilinear_equivalence():
    """
    Test initialisation of :func:`esmf_regrid.schemes.ESMFAreaWeightedRegridder`.

    Checks that equivalent curvilinear and rectilinear coordinates give the same
    results.
    """
    n_lons_src = 6
    n_lons_tgt = 3
    n_lats_src = 4
    n_lats_tgt = 2
    lon_bounds = (-180, 180)
    lat_bounds = (-90, 90)
    grid_src = _grid_cube(n_lons_src,
                          n_lats_src,
                          lon_bounds,
                          lat_bounds,
                          circular=True)
    grid_tgt = _grid_cube(n_lons_tgt,
                          n_lats_tgt,
                          lon_bounds,
                          lat_bounds,
                          circular=True)
    curv_src = _curvilinear_cube(n_lons_src, n_lats_src, lon_bounds,
                                 lat_bounds)
    curv_tgt = _curvilinear_cube(n_lons_tgt, n_lats_tgt, lon_bounds,
                                 lat_bounds)

    grid_to_grid = ESMFAreaWeightedRegridder(grid_src, grid_tgt)
    grid_to_curv = ESMFAreaWeightedRegridder(grid_src, curv_tgt)
    curv_to_grid = ESMFAreaWeightedRegridder(curv_src, grid_tgt)
    curv_to_curv = ESMFAreaWeightedRegridder(curv_src, curv_tgt)

    def extract_weights(regridder):
        return regridder.regridder.weight_matrix.todense()

    for regridder in [grid_to_curv, curv_to_grid, curv_to_curv]:
        assert np.allclose(extract_weights(grid_to_grid),
                           extract_weights(regridder))
Beispiel #3
0
def test_curvilinear():
    """
    Test for :func:`esmf_regrid.experimental.unstructured_scheme.MeshToGridESMFRegridder`.

    Tests with curvilinear source cube.
    """
    mesh = _full_mesh()
    mesh_length = mesh.connectivity(contains_face=True).shape[0]

    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, mesh_length, h])
    src_data[:] = np.arange(t * h).reshape([t, h])[:, np.newaxis, :]
    mesh_cube = Cube(src_data)
    mesh_coord_x, mesh_coord_y = mesh.to_MeshCoords("face")
    mesh_cube.add_aux_coord(mesh_coord_x, 1)
    mesh_cube.add_aux_coord(mesh_coord_y, 1)
    mesh_cube.add_dim_coord(time, 0)
    mesh_cube.add_dim_coord(height, 2)

    n_lons = 6
    n_lats = 5
    lon_bounds = (-180, 180)
    lat_bounds = (-90, 90)
    tgt = _curvilinear_cube(n_lons, n_lats, lon_bounds, lat_bounds)

    src_cube = mesh_cube.copy()
    src_cube.transpose([1, 0, 2])
    regridder = MeshToGridESMFRegridder(src_cube, tgt)
    result = regridder(mesh_cube)

    # Lenient check for data.
    expected_data = np.empty([t, n_lats, n_lons, h])
    expected_data[:] = np.arange(t * h).reshape(t, h)[:, np.newaxis,
                                                      np.newaxis, :]
    assert np.allclose(expected_data, result.data)

    expected_cube = Cube(expected_data)
    expected_cube.add_dim_coord(time, 0)
    expected_cube.add_aux_coord(tgt.coord("latitude"), [1, 2])
    expected_cube.add_aux_coord(tgt.coord("longitude"), [1, 2])
    expected_cube.add_dim_coord(height, 3)

    # Check metadata and scalar coords.
    result.data = expected_data
    assert expected_cube == result
def test_curvilinear():
    """
    Test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_rectilinear_to_unstructured`.

    Tests with curvilinear target cube.
    """
    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 = _curvilinear_cube(n_lons, n_lats, lon_bounds, lat_bounds)

    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_aux_coord(grid.coord("latitude"), [1, 2])
    cube.add_aux_coord(grid.coord("longitude"), [1, 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
Beispiel #5
0
def test_unit_equivalence():
    """
    Test initialisation of :func:`esmf_regrid.schemes.ESMFAreaWeightedRegridder`.

    Checks that equivalent coordinates in degrees and radians give the same results.
    """
    n_lons_src = 6
    n_lons_tgt = 3
    n_lats_src = 4
    n_lats_tgt = 2
    lon_bounds = (-180, 180)
    lat_bounds = (-90, 90)
    lon_rad_bounds = (-np.pi, np.pi)
    lat_rad_bounds = (-np.pi / 2, np.pi / 2)

    def rad_coords(cube):
        cube.coord("latitude").units = Unit("radians")
        cube.coord("longitude").units = Unit("radians")

    grid_src = _grid_cube(n_lons_src,
                          n_lats_src,
                          lon_bounds,
                          lat_bounds,
                          circular=True)
    grid_src_rad = _grid_cube(n_lons_src,
                              n_lats_src,
                              lon_rad_bounds,
                              lat_rad_bounds,
                              circular=True)
    rad_coords(grid_src_rad)
    grid_tgt = _grid_cube(n_lons_tgt,
                          n_lats_tgt,
                          lon_bounds,
                          lat_bounds,
                          circular=True)
    grid_tgt_rad = _grid_cube(n_lons_tgt,
                              n_lats_tgt,
                              lon_rad_bounds,
                              lat_rad_bounds,
                              circular=True)
    rad_coords(grid_tgt_rad)
    curv_src = _curvilinear_cube(n_lons_src, n_lats_src, lon_bounds,
                                 lat_bounds)
    curv_src_rad = _curvilinear_cube(n_lons_src, n_lats_src, lon_rad_bounds,
                                     lat_rad_bounds)
    rad_coords(curv_src_rad)
    curv_tgt = _curvilinear_cube(n_lons_tgt, n_lats_tgt, lon_bounds,
                                 lat_bounds)
    curv_tgt_rad = _curvilinear_cube(n_lons_tgt, n_lats_tgt, lon_rad_bounds,
                                     lat_rad_bounds)
    rad_coords(curv_tgt_rad)

    grid_to_grid = ESMFAreaWeightedRegridder(grid_src, grid_tgt)
    grid_rad_to_grid = ESMFAreaWeightedRegridder(grid_src_rad, grid_tgt)
    grid_rad_to_curv = ESMFAreaWeightedRegridder(grid_src_rad, curv_tgt)
    curv_to_grid_rad = ESMFAreaWeightedRegridder(curv_src, grid_tgt_rad)
    curv_rad_to_grid = ESMFAreaWeightedRegridder(curv_src_rad, grid_tgt)
    curv_to_curv_rad = ESMFAreaWeightedRegridder(curv_src, curv_tgt_rad)

    def extract_weights(regridder):
        return regridder.regridder.weight_matrix.todense()

    for regridder in [
            grid_rad_to_grid,
            grid_rad_to_curv,
            curv_to_grid_rad,
            curv_rad_to_grid,
            curv_to_curv_rad,
    ]:
        assert np.allclose(extract_weights(grid_to_grid),
                           extract_weights(regridder))
Beispiel #6
0
def test_extra_dims_rectilinear_to_curvilinear():
    """
    Test for :func:`esmf_regrid.schemes.regrid_rectilinear_to_rectilinear`.

    Tests the handling of extra dimensions and metadata. Ensures that proper
    coordinates, attributes, names and units are copied over.
    """
    h = 2
    t = 4
    e = 6
    src_lats = 3
    src_lons = 5

    tgt_lats = 5
    tgt_lons = 3

    lon_bounds = (-180, 180)
    lat_bounds = (-90, 90)

    src_grid = _grid_cube(
        src_lons,
        src_lats,
        lon_bounds,
        lat_bounds,
    )
    tgt_grid = _curvilinear_cube(
        tgt_lons,
        tgt_lats,
        lon_bounds,
        lat_bounds,
    )

    height = DimCoord(np.arange(h), standard_name="height")
    time = DimCoord(np.arange(t), standard_name="time")
    extra = AuxCoord(np.arange(e), long_name="extra dim")
    spanning = AuxCoord(np.ones([h, t, e]), long_name="spanning dim")

    src_data = np.empty([h, src_lats, t, src_lons, e])
    src_data[:] = np.arange(t * h * e).reshape([h, t, e])[:, np.newaxis, :,
                                                          np.newaxis, :]

    src_cube = Cube(src_data)
    src_cube.add_dim_coord(height, 0)
    src_cube.add_dim_coord(src_grid.coord("latitude"), 1)
    src_cube.add_dim_coord(time, 2)
    src_cube.add_dim_coord(src_grid.coord("longitude"), 3)
    src_cube.add_aux_coord(extra, 4)
    src_cube.add_aux_coord(spanning, [0, 2, 4])

    def _add_metadata(cube):
        result = cube.copy()
        result.units = "K"
        result.attributes = {"a": 1}
        result.standard_name = "air_temperature"
        scalar_height = AuxCoord([5], units="m", standard_name="height")
        scalar_time = DimCoord([10], units="s", standard_name="time")
        result.add_aux_coord(scalar_height)
        result.add_aux_coord(scalar_time)
        return result

    src_cube = _add_metadata(src_cube)

    result = regrid_rectilinear_to_rectilinear(src_cube, tgt_grid)

    expected_data = np.empty([h, tgt_lats, t, tgt_lons, e])
    expected_data[:] = np.arange(t * h * e).reshape([h, t,
                                                     e])[:, np.newaxis, :,
                                                         np.newaxis, :]

    expected_cube = Cube(expected_data)
    expected_cube.add_dim_coord(height, 0)
    expected_cube.add_aux_coord(tgt_grid.coord("latitude"), (1, 3))
    expected_cube.add_dim_coord(time, 2)
    expected_cube.add_aux_coord(tgt_grid.coord("longitude"), (1, 3))
    expected_cube.add_aux_coord(extra, 4)
    expected_cube.add_aux_coord(spanning, [0, 2, 4])
    expected_cube = _add_metadata(expected_cube)

    # Lenient check for data.
    assert np.allclose(expected_data, result.data)

    # Check metadata and coords.
    result.data = expected_data
    assert expected_cube == result