GeoDMS Academy — Closing exercise
Flood hazard analysis per dike ring area
Background
The Netherlands is divided into dike ring areas (dijkringgebieden): polders or regions protected by a connected system of flood defences. For each area, a flood hazard zonation (overstromingsgevaarzonering) classifies the land surface into six categories based on the expected flood depth and flow velocity if the defences were to fail:
| Code | Label | Meaning |
|---|---|---|
| 0 | Nihil | No meaningful hazard |
| 1 | Gering_20 | Low hazard, shallow flooding |
| 2 | Gering_200 | Low hazard, deeper flooding |
| 3 | Enigszins_gevaarlijk | Somewhat dangerous |
| 4 | Gevaarlijk | Dangerous |
| 5 | Zeer_gevaarlijk | Very dangerous |
Your task is to analyse how much of each dike ring area falls into each hazard class, identify the most at-risk areas, and use meta-scripting to do it efficiently.
Download the configuration with data here.
The configuration skeleton is provided in exercise.dms. The data is already wired up in the SourceData container. You work in the Analyse container.
Getting oriented (no scripting needed yet)
Open exercise.dms in the GeoDMS GUI and explore the source data before writing anything.
- Open
SourceData/DijkringGebiedin a map view. How many dike ring areas are there? - Open
SourceData/Overstromingsgevaarzoneringin a map view. What does the spatial pattern look like? - Look at the
Classifications/OverstromingsgevaarzoneringKcontainer. Notice theVsub-container — this is itself afor_eachthat creates named references to each class index. This is why you can writeClassifications/OverstromingsgevaarzoneringK/V/Zeer_gevaarlijkas a typed index instead of5[OverstromingsgevaarzoneringK].
Task 1 — Total area per dike ring (Module 2 + 1c)
In Analyse/Dijkringen, calculate the total area of each dike ring in km².
The skeleton already shows how to compute the area in m²:
attribute<meter2> Opp := count(per_rdc_25m, per_rdc_25m)[float64] * rdc_25m/NrMeter2PerCell;
Add an attribute Opp_km2 that expresses this in km².
Check your units: give Opp_km2 a proper km² values unit and verify in the Detail Pages that its metric indeed shows km². Going from m² to km² is a factor of 1,000,000, not 1,000; with a bare division the wrong factor still produces plausible-looking numbers, while a declared metric lets the GeoDMS flag the mismatch for you.
Open Dijkringen in a table view. Which dike ring area is the largest?
Task 2 — Hazard class area for one class (Module 1c)
Calculate the area (in m²) and the share (fraction 0–1) of one hazard class of your choice within each dike ring. The skeleton shows this for Zeer_gevaarlijk — use a different class.
Tip: to select cells of a specific class, use a boolean condition:
SourceData/Overstromingsgevaarzonering == Classifications/OverstromingsgevaarzoneringK/V/Gevaarlijk
Task 3 — Classification and map (Module 1d)
Define a class unit RiskClass that classifies dike rings by their share of the “Gevaarlijk” or “Zeer_gevaarlijk” class into four or five meaningful categories.
Configure a ClassBreaks attribute and a BrushColor attribute. Then classify your share attribute using classify. Open the result in a map view using the dike ring geometry.
Which dike ring areas stand out?
Task 4 — Template: one analysis for all classes (Module 3, steps 1–2)
The calculation of area + share is identical for every hazard class. Only the class index differs.
- Define a
Template HazardClassAnalysiswith the class index as a case parameter. - Inside the template, calculate:
area_m2: area of cells with this hazard class (in m²)share: fraction of the dike ring covered by this class
- Replace your Task 2 calculation with a template instantiation. Then add instantiations for all six classes.
Task 5 — for_each: generate all six analyses automatically (Module 3, step 3)
The Classifications/OverstromingsgevaarzoneringK unit already has:
- a
nameattribute with the six class names - a
Vsub-container with typed index references per class
Restructure your template so the case parameter is a typed index into OverstromingsgevaarzoneringK rather than a separate attribute. Then use for_each with OverstromingsgevaarzoneringK/name to generate all six analyses automatically.
The result should be a container HazardByClass with six sub-containers, one per class.
Task 6 — Weighted risk score (Advanced)
Using the six shares from Task 5, calculate a single weighted risk score per dike ring:
risk_score = sum over all classes of (class_index × share_of_class)
A score of 0 means entirely in the “Nihil” class; a score close to 5 means almost entirely “Zeer gevaarlijk”.
Tip: the asItemList function and an indirect expression can help build a sum expression dynamically from the six share attributes. Alternatively, you can compute the score explicitly as:
0.0 * share_nihil + 1.0 * share_gering_20 + ... + 5.0 * share_zeer_gevaarlijk
Rank the dike rings by risk score. Which three are most at risk?
Task 7 — Selection (Advanced, Module 1c)
Select only the dike rings where the combined share of “Gevaarlijk” and “Zeer_gevaarlijk” exceeds 15%. Use select_with_org_rel and bring the geometry and risk score to the selection domain.
How many dike rings meet this threshold?
Task 8 — Export (Advanced, Module 2b)
Export the dike ring results to a shapefile or GeoPackage. Include at minimum:
- the geometry
Opp_km2- the share for each of the six hazard classes
- the
risk_score
Use %LocalDataProjDir% as the output location.
What you have practised
| Task | Topic |
|---|---|
| 1–2 | Reading data, relations, aggregation |
| 3 | Classification and visualisation |
| 4 | Templates and case instantiation |
| 5 | for_each with a domain unit |
| 6 | Combining template output in a derived calculation |
| 7 | Selections |
| 8 | Writing output data |