GRASS logo

NAME

r.dem.lod - Compute Level of Detection (LoD) for DEM difference maps

KEYWORDS

raster, statistics, uncertainty, DEM, change detection

SYNOPSIS

r.dem.lod
r.dem.lod --help
r.dem.lod [dem=name] [reference=name] [dod=name] output=name method=string [confidence=float] [window=integer] [point_density=name] [nmad=float] [stable_mask=name] [floor=float] [min_stable=integer] [sigma_extra=name[,name,...]] [output_sigma=name] [output_domain=name] [--overwrite] [--help] [--verbose] [--quiet] [--ui]

Flags:

--overwrite
Allow output files to overwrite existing files
--help
Print usage summary
--verbose
Verbose module output
--quiet
Quiet module output
--ui
Force launching GUI dialog

Parameters:

dem=name
Post-event DEM (co-registered); requires reference
reference=name
Reference DEM; requires dem
dod=name
Precomputed (e.g. debiased) DEM of Difference; alternative to dem+reference
output=name [required]
Output LoD raster
method=string [required]
LoD method: global (uniform) or local (spatially variable)
Options: global, local
Default: local
confidence=float
Confidence level (e.g., 0.95 for 95% CI)
Default: 0.95
window=integer
Moving window size (cells) for local LoD, must be odd
Default: 21
point_density=name
Point cloud density raster (pts per square meter), used in local LoD
nmad=float
Pre-computed NMAD (m), skips stable pixel estimation if provided
stable_mask=name
Raster mask of stable pixels for sigma estimation (1=stable, null=unstable)
floor=float
Vertical uncertainty floor (meters, 1 sigma); method=global adds it in quadrature with the NMAD, method=local treats it as the flight-wide stable-residual NMAD and adds only its long-wavelength excess over the windowed dispersion, once (two-scale decomposition)
Default: 0.0
min_stable=integer
Minimum stable cells inside the window for the local dispersion to be defined (guards the sparse-coverage sigma_win=0 degeneracy)
Default: 25
sigma_extra=name[,name,...]
Additional 1-sigma uncertainty rasters added in quadrature
output_sigma=name
Output combined 1-sigma uncertainty raster (output = z * this)
output_domain=name
Output significance-domain raster (1 = LoD defined, NULL elsewhere; method=local)

Table of contents

DESCRIPTION

r.dem.lod computes a Level of Detection (LoD) raster for DEM differencing, the elevation-change magnitude below which a measured difference cannot be distinguished from noise. It supports a global (spatially uniform) and a local (spatially variable) mode.

The uncertainty of the difference is estimated from the Normalized Median Absolute Deviation (NMAD) of the elevation residuals on stable terrain:

NMAD = 1.4826 * median(|dh - median(dh)|)

The residual dh comes either from dem minus reference, or from a precomputed (typically bias-corrected) difference supplied via dod. Both paths difference the surfaces before estimation, so the NMAD estimates the difference dispersion directly and no sqrt(2) epoch factor applies on either path.

method=global

A single NMAD is estimated over the whole study area (or the stable_mask region when supplied), producing a uniform LoD value applied everywhere.

method=local

A spatially variable LoD is computed in a Gaussian-weighted moving window of size window (matching r.dem.stats):

sigma_win(x,y) = 1.4826 * median_W(|dh - median_W(dh)|)
s_long^2       = max(0, floor^2 - median_stable(sigma_win^2))
LoD(x,y)       = z * sqrt(sigma_win^2 + s_long^2 + sum(sigma_extra_i^2))

Global formula: LoD = z * sqrt(NMAD^2 + floor^2), one convention on both input paths (a non-zero floor must be an independent registration budget). Locally, floor is the flight-wide stable NMAD and only its long-wavelength excess s_long is added, once; the dispersion is defined only where at least min_stable stable cells fall in the window. NULL in any sigma_extra or point_density raster propagates to the LoD (unknown uncertainty means untestable).

sigma_extra accepts additional 1-sigma rasters (for example the bias-model coefficient SE from r.dem.bias). output_sigma stores the combined 1-sigma surface and output_domain marks cells where the LoD is defined. With a stable_mask the LoD exists only within the window's reach of stable cells and is deliberately not extended beyond it; the tested share of observed cells is always reported.

When a point_density raster is supplied, the local uncertainty is penalised in sparsely sampled areas before the LoD is computed.

NOTES

A precomputed nmad value can be supplied to skip the stable-pixel estimation, and a stable_mask restricts the residual statistics to terrain assumed unchanged (roads, parking lots, bare ground).

The output LoD raster can be passed directly to r.dem.change as the lod input for significance thresholding. For full per-source uncertainty propagation (combining several error rasters in quadrature) use r.dem.errprop.

The tool requires the Python scipy package.

EXAMPLES

The commands below use the example scene built in the r.dem toolset manual, which is derived from the North Carolina sample dataset. Build it there first.

A single detection limit for the whole map, estimated from the stable residuals:

g.region raster=elev_lid792_1m

r.dem.lod dod=dod_debiased output=lod_global method=global \
    stable_mask=stable_lod confidence=0.95

The debiased residual on the stable cells is the injected noise, so the result is z(0.95) times its NMAD:

NMAD: 0.0890 m
LoD: 0.1743 m (uniform)

A spatially variable limit, keeping the combined 1-sigma surface for r.dem.errprop and the domain raster that marks where the limit is defined:

r.dem.lod dod=dod_debiased output=lod_local method=local window=21 \
    stable_mask=stable_lod output_sigma=sigma_combined \
    output_domain=lod_domain confidence=0.95

Because the survey noise varies across this scene, so does the limit: it runs from roughly 0.12 m on the smooth fields to over 0.30 m under canopy, against a single uniform value of 0.175 m. That is the case for method=local, and the reason the mask must include forest.

However, the limit is undefined wherever no stable cell falls inside the window, which on this scene means the interior of the change features. Fall back to the uniform limit there before thresholding:

r.mapcalc "lod_filled = if(isnull(lod_local), lod_global, lod_local)"

Add the bias-model coefficient SE from r.dem.bias to the quadrature when the regression path was used:

r.dem.lod dod=dod_regression output=lod_with_se method=local \
    stable_mask=stable_terrain sigma_extra=bias_se \
    output_sigma=sigma_with_se
r.dem.lod example
Figure: The spatially variable Level of Detection against the uniform one, on a shared scale. White marks cells with no stable cell inside the window, where the local limit is undefined.

REFERENCES

SEE ALSO

r.dem, r.dem.change, r.dem.errprop, r.dem.stats, r.neighbors, r.univar

AUTHORS

Corey T. White, Center for Geospatial Analytics, NC State University

SOURCE CODE

Available at: r.dem.lod source code (history)

Accessed: Sunday Sep 13 08:28:13 2026


Main index | Raster index | Topics index | Keywords index | Graphical index | Full index

© 2003-2026 GRASS Development Team, GRASS 8.5.1dev Reference Manual