Skip to content

Hydrology pipeline#

End-to-end DEM-hydrology workflow. Every stage produces a typed result that flows into the next.

DEM
  → fill_depressions       (Wang-Liu / Planchon-Darboux / Priority-Flood / breach / fill-burn)
  → resolve_flats          (Garbrecht-Martz random-tiebreak)
  → flow_direction         (D8 / D∞ / MFD-Quinn / MFD-Holmgren / Rho8)
  → accumulate             (Kahn-sort over the routing's receivers)
  → streams                (accumulation threshold or area-slope criterion)
  → order                  (Strahler / Shreve / Horton / Hack / Topological)
  → to_vector              (LineString links carrying length, drop, slope, sinuosity)

1. DEM conditioning#

Method Reference What it does
DEM.fill_depressions(method="priority_flood") Barnes 2014 O(N log N) heap-driven hydrologic fill
DEM.fill_depressions(method="wang_liu") Wang & Liu 2006 Heap-driven flat-fill (no plateau lift)
DEM.fill_depressions(method="planchon_darboux") Planchon & Darboux 2002 Sweep-based iterative fill
DEM.breach_depressions(method="least_cost") Lindsay 2016 Dijkstra breach that finds the lowest cumulative breach path
DEM.breach_depressions(method="hybrid") Lindsay 2016 Breach where possible, fill where not
DEM.breach_depressions(method="single_cell") One-pass single-cell pit breach
DEM.burn_streams(method="fill_burn") Lindsay 2018 (= WBT FillBurn) Burn a vector network into the DEM, then priority-flood
DEM.burn_streams(method="topological_breach") Lindsay 2016 Topology-aware breach + burn
DEM.burn_streams(method="agree") Hellweger 1997 Distance-weighted AGREE burn + buffer
DEM.resolve_flats() Garbrecht & Martz 1997 (variant) Random-tiebreak plateau resolution
DEM.enforce_culverts(roads, streams) WBT BurnStreamsAtRoads Drop a cell at every stream-road intersection
DEM.enforce_breaklines(breaklines, lift) WBT RaiseWalls Raise cells along linear barriers
DEM.hydroflatten(water_polygons, method) Force lake / pond surfaces to a single elevation
DEM.burn_buildings(building_polygons, lift) Lift building footprints above the DEM
DEM.anudem_interpolate(...) Hutchinson 1989 Biharmonic ANUDEM interpolation
DEM.stochastic_depressions(sigma, n_runs) Lindsay & Creed 2006 W-11 — Monte-Carlo depression occurrence probability

2. Flow direction#

Method Receivers per cell Reference
"d8" 1 O'Callaghan & Mark 1984
"rho8" 1 (stochastic) Fairfield & Leymarie 1991
"dinf" up to 2 Tarboton 1997
"mfd_quinn" up to 8 Quinn 1991
"mfd_holmgren" up to 8 Holmgren 1994

Every routing emits a typed FlowDirection carrying a routing tag that propagates through all downstream stages.

3. Flow accumulation#

FlowDirection.accumulate(weights=None) runs a single Kahn topological-sort kernel that handles all five routings via the unified (receivers, proportions) representation. Returns a typed Accumulation raster.

Build extensions:

  • FlowDirection.upslope_flowpath_length()W-9 — per-cell longest upslope flow path.

4. Stream extraction#

Accumulation.streams(threshold, units="cells") returns a typed StreamRaster. With a slope DEM, the call switches to the Montgomery & Foufoula-Georgiou (1993) area-slope criterion (acc * slope**theta >= k).

5. Stream ordering and cleanup#

Method Reference What it produces
order(method="strahler") Strahler 1957 Topology-based order (Kahn BFS)
order(method="shreve") Shreve 1966 Additive magnitude (head count)
order(method="horton") Horton 1945 Strahler with main-stem promotion
order(method="hack") Hack 1957 (W-1) Main-stem-first ordering
order(method="topological") Kahn 1962 (W-2) Sequential Kahn-sort indices
to_vector(...) GeoDataFrame of links with length_m, drop_m, mean_slope, sinuosity (W-3)
main_stem(flow_direction, outlet=None) W-4 Binary mask of the longest source-to-outlet trace
prune_short(flow_direction, min_length_m) WBT RemoveShortStreams (W-5) Drop headwater links below threshold

6. Watershed delineation#

Method What it produces
FlowDirection.watershed(points, ...) One basin per pour point (D8 / Rho8)
FlowDirection.basins(...) Partition into terminal-outlet basins
FlowDirection.subbasins_pfafstetter(accumulation, streams, level=N) Pfafstetter coding to level N (1 or 2)
FlowDirection.isobasins(streams, accumulation, target_area_km2) W-7 — equal-area sub-basin partition
StreamRaster.subbasins(flow_direction) Per-link sub-basins (head / confluence segments)

WatershedRaster.statistics(...) ships per-basin metrics: area, elevation stats, hypsometric integral, drainage density, longest_flow_path_m (W-8), centroid.

7. Hydrologic indices#

  • DEM.hand(streams, flow_direction, method="d8") — Rennó 2008 / Nobre 2011 D8-traced HAND.
  • DEM.hand(streams, method="euclidean")W-10 — Euclidean-nearest-stream variant.
  • DEM.twi(accumulation, slope_deg=None)W-12 — Beven & Kirkby 1979 wetness index.
  • DEM.spi(accumulation, slope_deg=None)W-13 — stream power index.
  • DEM.sti(accumulation, slope_deg=None)W-14 — Moore & Burch 1986 sediment transport index.

8. Composite pipeline (W-20)#

DEM.full_hydro_pipeline(fill_method, flow_method, stream_threshold_cells) chains fill → flow_direction → accumulate → (optional streams) in one call, returning a dict of typed results.

See also#