Пример #1
0
def _get_raster_spacing(coords):
    """Get the row and column spacing of a raster grid.

    Parameters
    ----------
    root : netcdf_file
        A NetCDF object.

    Returns
    -------
    (dy, dx)
        Spacing of grid rows and columns.
    """
    spacing = np.empty(len(coords), dtype=np.float64)

    for (axis, coord) in enumerate(coords):
        coord_spacing = np.diff(coord, axis=axis)
        if not np.all(coord_spacing == coord_spacing.flat[0]):
            raise NotRasterGridError()
        spacing[axis] = coord_spacing.flat[0]

    if not np.all(spacing == spacing[0]):
        raise NotRasterGridError()

    return spacing[0]
Пример #2
0
def read_netcdf(nc_file, reshape=False, just_grid=False):
    """
    Reads the NetCDF file *nc_file*, and writes it to the fields of a new
    RasterModelGrid, which it then returns.
    Check the names of the fields in the returned grid with
    grid.at_nodes.keys().
    """
    try:
        root = nc.netcdf_file(nc_file, 'r', version=2)
    except TypeError:
        root = nc4.Dataset(nc_file, 'r', format='NETCDF4')

    shape = _read_netcdf_grid_shape(root)
    spacing = _read_netcdf_grid_spacing(root)

    assert (len(shape) == 2)
    assert (len(spacing) == 2)
    if spacing[0] != spacing[1]:
        raise NotRasterGridError()

    grid = RasterModelGrid(num_rows=shape[0], num_cols=shape[1], dx=spacing[0])

    if not just_grid:
        fields = _read_netcdf_structured_data(root)
        for (name, values) in fields.items():
            grid.add_field('node', name, values)

    root.close()

    return grid
Пример #3
0
def _get_raster_spacing(coords):
    spacing = np.empty(len(coords), dtype=np.float64)

    for (axis, coord) in enumerate(coords):
        coord_spacing = np.diff(coord, axis=axis)
        try:
            assert (np.all(coord_spacing == coord_spacing.flat[0]))
        except AssertionError:
            raise NotRasterGridError()
        spacing[axis] = coord_spacing.flat[0]

    try:
        assert (np.all(spacing == spacing[0]))
    except AssertionError:
        raise NotRasterGridError()
    else:
        return spacing[0]
Пример #4
0
def read_netcdf(nc_file, just_grid=False):
    """Read a GEBCO-formatted NetCDF file.

    Reads the NetCDF file *nc_file*, and writes it to the fields of a new
    RasterModelGrid, which it then returns.  Check the names of the fields
    in the returned grid with grid.at_nodes.keys().

    Parameters
    ----------
    nc_file : str
        Name of the NetCDF file.
    just_grid : bool, optional
        If ``True``, just read the grid information and forget the data.
        Otherwise add the data as fields.

    Returns
    -------
    RasterModelGrid
        A newly-created :any:`RasterModelGrid`.
    """
    try:
        root = nc.netcdf_file(nc_file, 'r', version=2)
    except TypeError:
        root = nc4.Dataset(nc_file, 'r', format='NETCDF4')

    shape = _read_netcdf_grid_shape(root)
    spacing = _read_netcdf_grid_spacing(root)

    assert len(shape) == 2
    assert len(spacing) == 2
    if spacing[0] != spacing[1]:
        raise NotRasterGridError()

    grid = RasterModelGrid(shape, spacing=spacing)

    if not just_grid:
        fields = _read_netcdf_structured_data(root)
        for (name, values) in fields.items():
            grid.add_field('node', name, values)

    root.close()

    return grid
Пример #5
0
def read_netcdf(
    nc_file,
    grid=None,
    name=None,
    just_grid=False,
    halo=0,
    nodata_value=-9999.0,
):
    """Create a :class:`~.RasterModelGrid` from a netcdf file.

    Create a new :class:`~.RasterModelGrid` from the netcdf file, *nc_file*.
    If the netcdf file also contains data, add that data to the grid's fields.
    To create a new grid without any associated data from the netcdf file,
    set the *just_grid* keyword to ``True``.

    A halo can be added with the keyword *halo*.

    If you want the fields to be added to an existing grid, it can be passed
    to the keyword argument *grid*.

    Parameters
    ----------
    nc_file : str
        Name of a netcdf file.
    grid : *grid* , optional
        Adds data to an existing *grid* instead of creating a new one.
    name : str, optional
        Add only fields with NetCDF variable name to the grid. Default is to
        add all NetCDF varibles to the grid.
    just_grid : boolean, optional
        Create a new grid but don't add value data.
    halo : integer, optional
        Adds outer border of depth halo to the *grid*.
    nodata_value : float, optional
        Value that indicates an invalid value. Default is -9999.

    Returns
    -------
    :class:`~.RasterModelGrid`
        A newly-created :class:`~.RasterModelGrid`.

    Examples
    --------
    Import :func:`read_netcdf` and the path to an example netcdf file included
    with landlab.

    >>> from landlab.io.netcdf import read_netcdf

    Create a new grid from the netcdf file. The example grid is a uniform
    rectilinear grid with 4 rows and 3 columns of nodes with unit spacing.
    The data file also contains data defined at the nodes for the grid for
    a variable called, *surface__elevation*.

    >>> grid = read_netcdf("test-netcdf4.nc") # doctest: +SKIP
    >>> grid.shape == (4, 3) # doctest: +SKIP
    True
    >>> grid.dy, grid.dx # doctest: +SKIP
    (1.0, 1.0)
    >>> list(grid.at_node.keys()) # doctest: +SKIP
    ['surface__elevation']
    >>> grid.at_node['surface__elevation'] # doctest: +SKIP
    array([  0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,
            11.])

    :func:`read_netcdf` will try to determine the format of the netcdf file.
    For example, the same call will also work for *netcdf3*-formatted files.

    >>> grid = read_netcdf("test-netcdf3-64bit.nc") # doctest: +SKIP
    >>> grid.shape == (4, 3) # doctest: +SKIP
    True
    >>> grid.dy, grid.dx # doctest: +SKIP
    (1.0, 1.0)

    A more complicated example might add data with a halo to an existing grid.
    Note that the lower left corner must be specified correctly for the data
    and the grid to align correctly.

    >>> from landlab import RasterModelGrid
    >>> grid = RasterModelGrid((6, 5), xy_of_lower_left=(-1., -1.)) # doctest: +SKIP
    >>> grid = read_netcdf(
    ...     "test-netcdf4.nc",
    ...     grid=grid,
    ...     halo=1,
    ...     nodata_value=-1,
    ... ) # doctest: +SKIP
    >>> grid.at_node['surface__elevation'].reshape(grid.shape) # doctest: +SKIP
    array([[ -1.,  -1.,  -1.,  -1.,  -1.],
           [ -1.,   0.,   1.,   2.,  -1.],
           [ -1.,   3.,   4.,   5.,  -1.],
           [ -1.,   6.,   7.,   8.,  -1.],
           [ -1.,   9.,  10.,  11.,  -1.],
           [ -1.,  -1.,  -1.,  -1.,  -1.]])
    """
    from landlab import RasterModelGrid

    dataset = xr.open_dataset(nc_file)

    if isinstance(name, str):
        names = {name}
    elif name is None:
        names = set(dataset.variables)
    else:
        names = set(name)

    # test if the input is a raster (x and y) are only 1-D instead of 2D.
    if len(dataset["x"].shape) == 1:
        y, x = np.meshgrid(dataset["y"], dataset["x"], indexing="ij")
    else:
        x = dataset["x"]
        y = dataset["y"]

    dx = np.diff(x, axis=1)
    dy = np.diff(y, axis=0)

    if np.all(dx == dx[0, 0]) and np.all(dy == dy[0, 0]):
        xy_spacing = (dx[0, 0], dy[0, 0])
    else:
        raise NotRasterGridError()

    shape = x.shape
    xy_of_lower_left = (
        x[0, 0] - halo * xy_spacing[0],
        y[0, 0] - halo * xy_spacing[1],
    )

    if grid is None:
        grid = RasterModelGrid(shape,
                               xy_spacing=xy_spacing,
                               xy_of_lower_left=xy_of_lower_left)
    else:
        if grid.shape != (shape[0] + 2 * halo, shape[1] + 2 * halo):
            raise MismatchGridDataSizeError(
                shape[0] + 2 * halo * shape[1] + 2 * halo,
                grid.number_of_node_rows * grid.number_of_node_columns,
            )
        if (grid.dx, grid.dy) != xy_spacing:
            raise MismatchGridXYSpacing((grid.dx, grid.dy), xy_spacing)

        if grid.xy_of_lower_left != xy_of_lower_left:
            raise MismatchGridXYLowerLeft(grid.xy_of_lower_left,
                                          xy_of_lower_left)

    if not just_grid:
        fields, grid_mapping_dict = _read_netcdf_structured_data(dataset)
        for (field_name, values) in fields.items():

            # add halo if necessary
            if halo > 0:
                values = add_halo(values.reshape(shape),
                                  halo=halo,
                                  halo_value=nodata_value).reshape((-1, ))

            # add only the requested fields.
            if (name is None) or (field_name == name):
                add_field = True
            else:
                add_field = False

            if add_field:
                grid.add_field(field_name, values, at="node", clobber=True)

        if (name is not None) and (name not in grid.at_node):
            raise ValueError(
                "Specified field {name} was not in provided NetCDF.".format(
                    name=name))

    ignore = {"x", "y"}
    for name in names - ignore:
        values = dataset.variables[name].values
        if halo > 0:
            values = add_halo(values.reshape(shape),
                              halo=halo,
                              halo_value=nodata_value).reshape((-1, ))
        grid.add_field(name, values, at="node", clobber=True)

    return grid