Skip to content

Reference the inland German waterways to low water - #156

Draft
bkeepers wants to merge 3 commits into
mainfrom
dgm-w-inland
Draft

Reference the inland German waterways to low water#156
bkeepers wants to merge 3 commits into
mainfrom
dgm-w-inland

Conversation

@bkeepers

Copy link
Copy Markdown
Member

Second half of the #76 split, stacked on #155: activates the 68 inland DGM-W tiles by fabricating the low-water reference surface where Germany publishes none. Closes #53.

Inland riverbeds sit tens of metres above MSL, so without a reference they render as land. There is no packaged low-water grid for any of these rivers; the surface is assembled per hydraulic regime from gauge data and transcribed barrage tables:

Waterway (tiles) Reference Method
Rhein free-flowing, km 336–865 (3) GlW gauge ramp, filled over the Overture river corridor
Upper Elbe (25), Grenzoder (8), Ober-/Mittelweser (1) MNW same ramp; MNW is the conservative open proxy for the un-published GlW
Main, km 0–102 (6) Stauziel per-pool step, divided exactly at each OSM weir line
Upper Rhein, km 164–334 (16) Stauziel per-pool step by latitude (the reach flows due north)
Mosel (1), Saar (5), Lahn (3) Stauziel per-pool step by arc-length along the centerline, asserted against PEGELONLINE ZS_I gauges

Two refresh scripts keep the checked-in inputs reproducible, and neither runs in the build: harvest_gauges.py pulls per-gauge low-water values (GlW/ZS_I/MNW in NHN) from PEGELONLINE, and build_geometry.py extracts river corridors and centerlines from Overture Maps. build_reference.py builds the ten reaches and merges them onto the finest grid, since the datum store serves a single raster per surface name.

Caveat worth knowing at review: the Mittelweser is impounded but publishes no ZS_I, so the Weser ramp smooths its pool steps by ~1–2 m at each barrage. Documented in the README, upgradeable to a proper step reach if a level table surfaces.

Still deferred:

  • Ems (4 tiles, tidal): needs the SKN path or MTnw, a different approach than the ramp
  • Dortmund-Ems-Kanal / Havel-Oder canals: no PEGELONLINE gauges, need WSV Haltung levels
  • Check the merged surface raster's size with a local build_reference.py --out run before any production dispatch
  • Reconcile the clamp_positive clamp against the OSM land–water mask so drying flats survive (shared with the tidal PR)

Not for navigation. References: PEGELONLINE characteristic values (WSV), Overture Maps geometry, barrage tables transcribed from Wikipedia and WSV fact sheets (sources cited per file in the README).

bkeepers added a commit that referenced this pull request Aug 15, 2026
The reach merge is last-wins where corridors overlap, and the ramps are
painted after the tidal/Stauziel surfaces, so an unclipped ramp corridor
overrode its neighbour: the Rhein ramp reached south past Iffezheim and
replaced the pool Stauziele with its clamped endpoint GlW (20 m+ error),
and the Elbe MNW ramp bled west over the tidal SKN corridor at Geesthacht
(metres too deep). The ramps now stop at the Iffezheim barrage latitude
and the Geesthacht weir longitude via fill_corridor's row/column bounds.
Found by review on PR #156.
@bkeepers
bkeepers requested a lite review from Copilot August 15, 2026 19:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Extends the existing WSV DGM-W source from tidal-only coverage to include multiple inland German waterways by generating a per-reach low-water reference surface (ramps from gauge characteristic values and stepped pool surfaces from barrage tables), then activating the additional inland tiles and documenting the methodology.

Changes:

  • Expands dgm_w_lowwater surface generation to merge tidal SKN, free-flowing ramp surfaces (GlW/MNW), and impounded step surfaces (Stauziel) into a single datum raster.
  • Adds reproducible, checked-in gauge extracts (*_glw.csv, *_mnw.csv, *_zs.csv), barrage tables (*_stau.csv), and river geometry (*_river.wkt, *_centerline.wkt) plus refresh scripts.
  • Activates the newly supported inland waterways in sources/dgm_w/file_list.txt and updates metadata/docs to reflect the broader scope.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
Snakefile Updates the datum_surface_dgm_w rule inputs to include all reach CSV/WKT dependencies.
sources/README.md Updates the sources catalog entry to reflect inland DGM-W coverage and datum regimes.
sources/dgm_w/README.md Documents inland reach methodology (ramps/steps), inputs, refresh scripts, and active/deferred reaches.
sources/dgm_w/metadata.json Updates the source name and expands datum description to include inland regimes and active reaches.
sources/dgm_w/file_list.txt Activates inland DGM-W tiles and adds reach-by-reach commentary on datum references.
sources/dgm_w/build_reference.py Major expansion: builds and merges SKN + ramp + step reference rasters into dgm_w_lowwater.tif.
sources/dgm_w/harvest_gauges.py New script to regenerate committed gauge characteristic-value CSV inputs from PEGELONLINE.
sources/dgm_w/build_geometry.py New script to regenerate corridor/centerline WKTs from Overture base/water for reproducibility.
sources/dgm_w/tideelbe_skn.csv Adds a Geesthacht weir anchor row to extend the inner-tidal Elbe SKN fill to the regime boundary.
sources/dgm_w/rhein_glw.csv Adds harvested Rhine GlW-in-NHN gauge reference inputs for the free-flowing ramp reach.
sources/dgm_w/elbe_mnw.csv Adds harvested Elbe MNW-in-NHN gauge reference inputs for the free-flowing ramp reach.
sources/dgm_w/oder_mnw.csv Adds harvested Oder MNW-in-NHN gauge reference inputs for the free-flowing ramp reach.
sources/dgm_w/weser_mnw.csv Adds harvested Weser MNW-in-NHN gauge reference inputs for the free-flowing ramp reach.
sources/dgm_w/main_zs.csv Adds harvested Main ZS_I-in-NHN gauge inputs used to cross-check the Main Stauziel table.
sources/dgm_w/main_stau.csv Adds Main barrage Stauziel levels + OSM weir-line endpoints for exact pool step dividers.
sources/dgm_w/main_centerline.wkt Adds Main centerline geometry used to constrain the step fill corridor.
sources/dgm_w/rhein_stau.csv Adds upper Rhine barrage Stauziel levels + lock coords used for latitude-stepped pool dividers.
sources/dgm_w/rhein_centerline.wkt Adds upper Rhine navigation-centerline geometry used to constrain the step fill corridor.
sources/dgm_w/mosel_zs.csv Adds harvested Mosel ZS_I gauge inputs used to cross-check the Mosel Stauziel staircase.
sources/dgm_w/mosel_stau.csv Adds Mosel barrage Stauziel staircase table used for impounded step surface generation.
sources/dgm_w/saar_zs.csv Adds harvested Saar ZS_I gauge inputs used to cross-check the Saar Stauziel staircase.
sources/dgm_w/saar_stau.csv Adds Saar barrage Stauziel staircase table (including Konz backwater stub anchoring).
sources/dgm_w/saar_river.wkt Adds Saar corridor geometry used to bound the filled reference surface to the river.
sources/dgm_w/saar_centerline.wkt Adds Saar centerline geometry used for arc-length pool assignment.
sources/dgm_w/lahn_zs.csv Adds harvested Lahn ZS_I gauge inputs used to cross-check the Lahn Stauziel staircase.
sources/dgm_w/lahn_stau.csv Adds Lahn weir Stauziel staircase table (from WSV/WSA-Koblenz fact sheets).
sources/dgm_w/lahn_river.wkt Adds Lahn corridor geometry used to bound the filled reference surface to the river.
sources/dgm_w/lahn_centerline.wkt Adds Lahn centerline geometry used for arc-length pool assignment.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +87 to +90
weir = None
if r.get("lon1", "").strip():
weir = ((float(r["lon1"]), float(r["lat1"])), (float(r["lon2"]), float(r["lat2"])))
rows.append({"km": float(r["km"]), "stau": float(r["stauziel_nhn_m"]), "weir": weir})
Comment thread Snakefile Outdated
Comment thread sources/dgm_w/build_reference.py Outdated
Extends the DGM-W datum surface beyond the tidal SKN reach to the inland
waterways, where no low-water grid is published and the reference has to be
fabricated per hydraulic regime:

- Free-flowing rivers (Rhein below Iffezheim, upper Elbe, Grenzoder,
  Ober-/Mittelweser): a low-water ramp — per-gauge GlW (or MNW where GlW is
  un-published, the conservative proxy) interpolated by arc-length along the
  gauge line and painted over the Overture river corridor.
- Impounded canalised rivers (Main, upper Rhein, Mosel, Saar, Lahn): a
  Stauziel step — flat per pool, jumping at each barrage (weir lines on the
  Main, latitude on the due-north upper Rhein, centerline arc-length
  elsewhere), cross-checked against PEGELONLINE ZS_I gauges where they exist.

harvest_gauges.py (PEGELONLINE characteristic values) and build_geometry.py
(Overture corridors/centerlines) refresh the checked-in CSVs/WKTs; the build
reads only the committed files. build_reference.py now merges all ten
reaches onto the finest grid for the single store/datum raster. 68 inland
tiles activate; only the tidal Ems and the gauge-less canals stay deferred.

Extracted from the add-source-wsv-dgmw branch (PR #76).
The reach merge is last-wins where corridors overlap, and the ramps are
painted after the tidal/Stauziel surfaces, so an unclipped ramp corridor
overrode its neighbour: the Rhein ramp reached south past Iffezheim and
replaced the pool Stauziele with its clamped endpoint GlW (20 m+ error),
and the Elbe MNW ramp bled west over the tidal SKN corridor at Geesthacht
(metres too deep). The ramps now stop at the Iffezheim barrage latitude
and the Geesthacht weir longitude via fill_corridor's row/column bounds.
Found by review on PR #156.
The pool-index clip assigned the most-downstream pool's Stauziel to
pixels past its barrage (the Main mouth got Kostheim's 83.9 m over Rhein
backwater at ~81.5 m — the deep direction). All three step builders now
return nodata there: the mouth is the neighbouring reach's backwater and
the ramps cover it where their corridors reach. Also parenthesize the
datum rule's multi-line input concatenation for clarity. Review comments
on PR #156.
@bkeepers
bkeepers marked this pull request as draft August 15, 2026 20:04
Base automatically changed from dgm-w-tidal to main August 15, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants