Esempio n. 1
0
def calc_aspect_at_node(
    grid,
    slope_component_tuple=None,
    elevs="topographic__elevation",
    unit="degrees",
    ignore_closed_nodes=True,
):
    """Get array of aspect of a surface.

    Calculates at returns the aspect of a surface. Aspect is returned as
    radians clockwise of north, unless input parameter units is set to
    'degrees'.

    If slope_component_tuple is provided, i.e., (slope_x, slope_y), the
    aspect will be calculated from these data.

    If it is not, it will be derived from elevation data at the nodes,
    which can either be a string referring to a grid field (default:
    'topographic__elevation'), or an nnodes-long numpy array of the
    values themselves.

    If ignore_closed_nodes is False, all proximal elevation values will be used
    in the calculation. If True, only unclosed nodes are used.

    Parameters
    ----------
    grid : ModelGrid
        A ModelGrid.
    slope_component_tuple : (slope_x_array, slope_y_array) (optional)
        Tuple of components of slope in the x and y directions, defined
        on nodes, if already known. If not, provide *elevs*.
    elevs : str or array (optional)
        Node field name or node array of elevations.
        If *slope_component_tuple* is not provided, must be set, but unused
        otherwise.
    unit : {'degrees', 'radians'}
        Controls the unit that the aspect is returned as.
    ignore_closed_nodes : bool
        If True, do not incorporate values at closed nodes into the calc.

    Examples
    --------
    >>> from landlab import RasterModelGrid
    >>> mg = RasterModelGrid((4, 4))
    >>> z = mg.node_x ** 2 + mg.node_y ** 2
    >>> mg.calc_aspect_at_node(elevs=z)
    array([ 225.        ,  240.16585039,  255.2796318 ,  258.69006753,
            209.83414961,  225.        ,  243.54632481,  248.77808974,
            194.7203682 ,  206.45367519,  225.        ,  231.94498651,
            191.30993247,  201.22191026,  218.05501349,  225.        ])
    >>> z = z.max() - z
    >>> mg.calc_aspect_at_node(elevs=z)
    array([ 45.        ,  60.16585039,  75.2796318 ,  78.69006753,
            29.83414961,  45.        ,  63.54632481,  68.77808974,
            14.7203682 ,  26.45367519,  45.        ,  51.94498651,
            11.30993247,  21.22191026,  38.05501349,  45.        ])

    >>> mg = RasterModelGrid((4, 4), xy_spacing=(3., 2.))
    >>> z = mg.node_x ** 2 + mg.node_y ** 2
    >>> mg.calc_aspect_at_node(elevs=z)
    array([ 236.30993247,  247.52001262,  259.97326008,  262.40535663,
            220.75264634,  234.41577266,  251.13402374,  255.29210302,
            201.54258265,  215.47930877,  235.73541937,  242.24162456,
            196.69924423,  209.43534223,  229.19345757,  236.30993247])

    Note that a small amount of asymmetry arises at the grid edges due
    to the "missing" nodes beyond the edge of the grid.

    LLCATS: NINF SURF
    """
    if slope_component_tuple:
        if not isinstance(slope_component_tuple, (tuple, list)):
            raise TypeError("slope_component_tuple must be tuple")
        if len(slope_component_tuple) != 2:
            raise ValueError("slope_component_tuple must be of length 2")
    else:
        try:
            elev_array = grid.at_node[elevs]
        except (KeyError, TypeError):
            assert elevs.size == grid.number_of_nodes
            elev_array = elevs

        _, slope_component_tuple = grid.calc_slope_at_node(
            elevs=elev_array,
            ignore_closed_nodes=ignore_closed_nodes,
            return_components=True,
        )

    angle_from_x_ccw = np.arctan2(-slope_component_tuple[1], -slope_component_tuple[0])

    if unit == "degrees":
        return radians_to_degrees(angle_from_x_ccw)
    elif unit == "radians":
        angle_from_north_cw = (5. * np.pi / 2. - angle_from_x_ccw) % (2. * np.pi)
        return angle_from_north_cw
    else:
        raise TypeError("unit must be 'degrees' or 'radians'")
Esempio n. 2
0
def calc_aspect_at_node(
    grid,
    slope_component_tuple=None,
    elevs="topographic__elevation",
    unit="degrees",
    ignore_closed_nodes=True,
):
    """Get array of aspect of a surface.

    Calculates at returns the aspect of a surface. Aspect is returned as
    radians clockwise of north, unless input parameter units is set to
    'degrees'.

    If slope_component_tuple is provided, i.e., (slope_x, slope_y), the
    aspect will be calculated from these data.

    If it is not, it will be derived from elevation data at the nodes,
    which can either be a string referring to a grid field (default:
    'topographic__elevation'), or an nnodes-long numpy array of the
    values themselves.

    If ignore_closed_nodes is False, all proximal elevation values will be used
    in the calculation. If True, only unclosed nodes are used.

    Parameters
    ----------
    grid : ModelGrid
        A ModelGrid.
    slope_component_tuple : (slope_x_array, slope_y_array) (optional)
        Tuple of components of slope in the x and y directions, defined
        on nodes, if already known. If not, provide *elevs*.
    elevs : str or array (optional)
        Node field name or node array of elevations.
        If *slope_component_tuple* is not provided, must be set, but unused
        otherwise.
    unit : {'degrees', 'radians'}
        Controls the unit that the aspect is returned as.
    ignore_closed_nodes : bool
        If True, do not incorporate values at closed nodes into the calc.

    Examples
    --------
    >>> from landlab import RasterModelGrid
    >>> mg = RasterModelGrid((4, 4))
    >>> z = mg.node_x ** 2 + mg.node_y ** 2
    >>> mg.calc_aspect_at_node(elevs=z)
    array([ 225.        ,  240.16585039,  255.2796318 ,  258.69006753,
            209.83414961,  225.        ,  243.54632481,  248.77808974,
            194.7203682 ,  206.45367519,  225.        ,  231.94498651,
            191.30993247,  201.22191026,  218.05501349,  225.        ])
    >>> z = z.max() - z
    >>> mg.calc_aspect_at_node(elevs=z)
    array([ 45.        ,  60.16585039,  75.2796318 ,  78.69006753,
            29.83414961,  45.        ,  63.54632481,  68.77808974,
            14.7203682 ,  26.45367519,  45.        ,  51.94498651,
            11.30993247,  21.22191026,  38.05501349,  45.        ])

    >>> mg = RasterModelGrid((4, 4), xy_spacing=(3., 2.))
    >>> z = mg.node_x ** 2 + mg.node_y ** 2
    >>> mg.calc_aspect_at_node(elevs=z)
    array([ 236.30993247,  247.52001262,  259.97326008,  262.40535663,
            220.75264634,  234.41577266,  251.13402374,  255.29210302,
            201.54258265,  215.47930877,  235.73541937,  242.24162456,
            196.69924423,  209.43534223,  229.19345757,  236.30993247])

    Note that a small amount of asymmetry arises at the grid edges due
    to the "missing" nodes beyond the edge of the grid.

    LLCATS: NINF SURF
    """
    if slope_component_tuple:
        if not isinstance(slope_component_tuple, (tuple, list)):
            raise TypeError("slope_component_tuple must be tuple")
        if len(slope_component_tuple) != 2:
            raise ValueError("slope_component_tuple must be of length 2")
    else:
        try:
            elev_array = grid.at_node[elevs]
        except (KeyError, TypeError):
            assert elevs.size == grid.number_of_nodes
            elev_array = elevs

        _, slope_component_tuple = grid.calc_slope_at_node(
            elevs=elev_array,
            ignore_closed_nodes=ignore_closed_nodes,
            return_components=True,
        )

    angle_from_x_ccw = np.arctan2(-slope_component_tuple[1],
                                  -slope_component_tuple[0])

    if unit == "degrees":
        return radians_to_degrees(angle_from_x_ccw)
    elif unit == "radians":
        angle_from_north_cw = (5.0 * np.pi / 2.0 - angle_from_x_ccw) % (2.0 *
                                                                        np.pi)
        return angle_from_north_cw
    else:
        raise TypeError("unit must be 'degrees' or 'radians'")