v0.3.0 — Shared rivernetworkx core and module modernization
This release migrates the toolkit onto a single shared river-network library,
modernizes the modules, and makes several correctness fixes. The API is still
pre-1.0 and may change.
Added
rivernetworkx: a new importable Python package (pure NetworkX, no GRASS)
that single-sources the river-network logic — graph construction
(build_network/build_graph), raster sampling, breadth-first traversal,
cumulative-distance accumulation, per-segment smoothing and densification,
channel slope (−d z/d s) and slope–area, and node-link
JSON I/O. The GRASS modules are now thin consumers of it, and the same
representation is reusable outside GRASS (e.g. the GRLP coupling).v.stream.networkgains an optionaljson=export (withelevation=,
accumulation=,accum_mult=): it builds the NetworkX river-network graph,
samples rasters along each segment, computes cumulative distance upstream of
the outlet, and writes node-link JSON. This is the capability formerly
provided by the separatev.stream.networkxmodule.v.stream.networkandv.stream.profilergain a-cflag (the region
contains the full basin): a negative-accumulation channel head is then treated
as anr.watershedboundary artifact (a divide on the region edge) rather than
off-map inflow, skipping the off-map error.
Changed
v.stream.profilerrebuilt onrivernetworkx. It walks either downstream
to the outlet or upstream through all tributaries, samples
elevation/accumulation/slope along the channel, optionally densifies
(dx_target=) and smooths (window=) per segment (smoothing and
densification never cross tributary junctions, preserving the natural breaks),
and outputs a text long-profile table and/or a node-link JSON sub-network
(json=).- Drainage area sampled from
r.watershedis returned as a positive magnitude
(the outlet cells, which GRASS marks negative as a boundary flag, are
recovered). examples/clean_coarsen_network.pynow post-processes the
v.stream.network json=export; its accumulation array is optional.
Fixed
v.stream.profilerwas non-functional on current GRASS GIS and pandas (a
stalegrass.rasterimport and aSeries→intcoercion); it runs again,
and its long-standing branching bug is fixed by construction.v.stream.networkwrites the off-map outlettostreamas0(an earlier
partial migration wrote-1); diverging (distributary/braided) networks now
stop with a clear error instead of writing a partialtostream.- Raster sampling is limited to the network's extent (covers the whole network
even when the current region does not, and avoids reading a full large
region), includes points exactly on the east/south region edges, and tolerates
coincident vertices. - Incomplete catchments (off-map upstream contributing area, flagged by negative
r.watershedaccumulation reaching a channel head) are caught with a clear
error rather than silently producing a misleading network; the-cflag
overrides this when the region truly holds the full basin. - Raster NULL cells are read as NaN rather than a silent
0, so missing data
stays honest; sampling accumulation with no data under a channel cell now
errors clearly instead of slipping through as a fake0. export_jsonemits standards-compliant JSON (non-finite floats asnull, not
the bareNaNtoken that strict parsers reject);load_jsonrestores them.
Removed
v.stream.networkx: retired. Its sole job (build graph → JSON) is now
thejson=option onv.stream.network, backed byrivernetworkx.v.stream.profiler/RiverNetwork.py: the bespoke network class is replaced
by the sharedrivernetworkxlibrary.
Full changelog: v0.2.0...v0.3.0