Slope and aspect methods

Slope and aspect methods#

Terrain slope and aspect can be estimated using different methods. Here is an example of how to generate the two with each method, and understand their differences.

For more information, see the Terrain attributes chapter and the Terrain attributes example.

import matplotlib.pyplot as plt
import numpy as np

import xdem

Example data

dem = xdem.DEM(xdem.examples.get_path("longyearbyen_ref_dem"))

def plot_attribute(attribute, cmap, label=None, vlim=None):
    plt.figure(figsize=(8, 5))

    if vlim is not None:
        if isinstance(vlim, (int, np.integer, float, np.floating)):
            vlims = {"vmin": -vlim, "vmax": vlim}
        elif len(vlim) == 2:
            vlims = {"vmin": vlim[0], "vmax": vlim[1]}
        vlims = {}

    attribute.plot(cmap=cmap, cbar_title=label)


Slope with method of Horn (1981) (GDAL default), based on a refined approximation of the gradient (page 18, bottom left, and pages 20-21).

slope_horn = xdem.terrain.slope(dem)

plot_attribute(slope_horn, "Reds", "Slope of Horn (1981) (°)")
plot slope methods

Slope with method of Zevenbergen and Thorne (1987), Equation 13.

slope_zevenberg = xdem.terrain.slope(dem, method="ZevenbergThorne")

plot_attribute(slope_zevenberg, "Reds", "Slope of Zevenberg and Thorne (1987) (°)")
plot slope methods

We compute the difference between the slopes computed with each method.

diff_slope = slope_horn - slope_zevenberg

plot_attribute(diff_slope, "RdYlBu", "Slope of Horn (1981) minus\n slope of Zevenberg and Thorne (1987) (°)", vlim=3)
plot slope methods

The differences are negative, implying that the method of Horn always provides flatter slopes. Additionally, they seem to occur in places of high curvatures. We verify this by plotting the maximum curvature.

maxc = xdem.terrain.maximum_curvature(dem)

plot_attribute(maxc, "RdYlBu", "Maximum curvature (100 m $^{-1}$)", vlim=2)
plot slope methods

We quantify the relationship by computing the median of slope differences in bins of curvatures, and plot the result. We define custom bins for curvature, due to its skewed distribution.

df_bin = xdem.spatialstats.nd_binning(
    statistics=[np.nanmedian, "count"],

    label_var="Maximum absolute curvature (100 m$^{-1}$)",
    label_statistic="Slope of Horn (1981) minus\n " "slope of Zevenberg and Thorne (1987) (°)",
plot slope methods

We perform the same exercise to analyze the differences in terrain aspect. We compute the difference modulo 360°, to account for the circularity of aspect.

aspect_horn = xdem.terrain.aspect(dem)
aspect_zevenberg = xdem.terrain.aspect(dem, method="ZevenbergThorne")

diff_aspect = aspect_horn - aspect_zevenberg
diff_aspect_mod = np.minimum(diff_aspect % 360, 360 - diff_aspect % 360)

    diff_aspect_mod, "Spectral", "Aspect of Horn (1981) minus\n aspect of Zevenberg and Thorne (1987) (°)", vlim=[0, 90]
plot slope methods

Same as for slope, differences in aspect seem to coincide with high curvature areas. We observe also observe large differences for areas with nearly flat slopes, owing to the high sensitivity of orientation estimation for flat terrain.

# Note: the default aspect for a 0° slope is 180°, as in GDAL.

Total running time of the script: (0 minutes 4.349 seconds)

Gallery generated by Sphinx-Gallery