Inspiration

Heavy rain washes street runoff and sewer overflows into city streams. At the Paris 2024 Olympics, rain alone decided whether athletes could swim in the Seine. Yet when we opened OneAquaHealth's public data, we found that 95 of its 96 stream lab results are from 2023. Every city map showed old evidence as if it were current.

Monitoring teams can only make a few site visits. After a storm, the questions are simple: which streams, what to test for, and when? No tool answered them. So we built AfterStorm: after the storm, sample what matters.

What it does

Live demo: https://ankitag80.github.io/afterstorm-oneaquahealth/ · Code: https://github.com/AnkitAg80/afterstorm-oneaquahealth

AfterStorm turns a storm into a reviewable post-storm reassessment plan for a city coordinator:

  • Storm trigger. A day counts as a storm day when rain reaches 20 mm. That's the WMO/ETCCDI very heavy precipitation day index (R20mm), used as a prototype setting. In replay mode, every site in the city must reach it:

$$\text{storm}(d) \iff \min_{s \in S_c} R_s(d) \ge 20\ \text{mm}$$

  • What to test. Each site's stored 2023–24 categories (faecal, pathogen, antibiotic resistance) are relative scores between 0 and 1, not concentrations. They decide which categories to reassess. A category qualifies if its score is at least 0.5:

$$x_{s,k} \ge 0.5, \qquad x_{s,k} \in [0,1]$$

  • When. An experimental window covering the two days after the storm day d, which the coordinator confirms:

$$W = [\,d+1,\; d+2\,]$$

  • Where, within a budget. Qualifying sites are ranked by their highest category score, then by distance to the nearest sewage works, and the first B visits are planned:

$$\text{rank by } \max_k x_{s,k}\ \downarrow,\ \text{then sewage distance}\ \uparrow$$

  • Protection check. It names the sites with draft contact notices that the budget leaves out (for example C2 and C16 in Coimbra), and shows the budget that would cover them all.

  • Draft contact notices for people and pets, where the faecal or pathogen score is at least 0.5:

$$\max\left(x_{\text{fec}},\, x_{\text{path}}\right) \ge 0.5$$

They're never sent automatically. Each one has a confirmation-sample date: under the EU Bathing Water Directive (Annex IV.4), that sample is how a notice ends.

  • Human-in-the-loop review. Approve or hold each visit and notice. Approvals are tied to the evidence: if the storm, categories or window change, AfterStorm asks for a fresh review.
  • Citizen task cards in each city's language (Portuguese, French, Dutch, Italian, Norwegian). They give safe, bank-side yes/no checks: discharging pipes, sewage smell, people or pets in the water, dead fish or animals, and unusual water colour or algae blooms. Each card links to the official OneAquaHealth Citizen Science App.
  • Hand-offs, with nothing uploaded: draft HL7 FHIR R4 ServiceRequests, a lab sheet (CSV) that opens in any spreadsheet, and review files a team can export and import to share decisions.

Four pages keep it readable: Overview, Plan & map, Notices, and Evidence & data. A short first-visit guide explains the flow, and a "How it works" button reopens it.

How we built it

  • Data: OneAquaHealth's official site roster (106 sites in 5 cities), Resilience Map health-risk results, urban parameters and per-site daily weather, plus the Open-Meteo 7-day forecast. Everything is cached with SHA-256 provenance, so the demo works offline.
  • Planner: Python, standard library only (fetch.py, plan.py). Every rule is visible in config.json; nothing is trained or predicted.
  • Standards: fhir_export.py builds draft ServiceRequests (one request type, with each category as an orderDetail). Five were filed once to the HL7 Europe OneAquaHealth FHIR sandbox (ServiceRequest 1046–1050). The current export passes the official HL7 FHIR validator (core R4 4.0.1) with 0 errors (17 warnings, mostly our local code systems). The OneAquaHealth guide's package couldn't be loaded, so we don't claim profile conformance.
  • Front end: a static HTML, CSS and JavaScript app with Leaflet maps, a hash router, and a dark accessible theme with checked contrast, keyboard support and reduced motion. It's hosted on GitHub Pages with no server, so any city on the roster can run it for free.
  • Quality: three automated test suites (planner, data fetch, lab sheet) run in GitHub Actions, and every on-screen number traces back to a source field.

Challenges we ran into

  • Honesty over drama. The lab values are relative 2023 categories, not current concentrations, so we refused to invent risk scores or forecasts. The tool plans evidence; it doesn't predict contamination.
  • Daily data, hourly rain. The WMO heavy-rain rate (7.6 mm/h) needs hourly data; our sources are daily totals. So we used the daily R20mm index and say so plainly.
  • No storm in the forecast. During the build, no city had a storm forecast. A promising 42.9 mm forecast for Oslo dropped to 17.4 mm a day later. That's why the app has a clearly labelled replay of a real past storm, alongside an honest live view.
  • FHIR semantics. Our first export put several categories inside one code, which is wrong in FHIR. We moved them to orderDetail, validated the result, and documented the earlier filed records as v1.
  • Data gaps. Two archive dates are missing for every site, and some sites have no lab result. Missing values are never treated as dry or zero.

Accomplishments that we're proud of

  • A plan you can act on in seconds, with every number traceable to OneAquaHealth's data.
  • Real filings to the HL7 Europe OneAquaHealth sandbox, and 0 errors from the official FHIR validator.
  • A protection check that makes the cost of a small budget visible, without a made-up risk percentage.
  • Citizen science that's safe, multilingual, covers people, pets and wildlife signs, and links to the official app.

What we learned

  • After-storm samples are exactly what early-warning systems, such as Berlin's FLUSSHYGIENE river forecasts, are built from, yet routine monitoring rarely collects them.
  • Standards matter in detail: a FHIR resource can parse cleanly and still say the wrong thing.
  • Saying what a tool doesn't do (no predictions, no safety clearances, drafts only) builds more trust than overclaiming.

What's next for After Storm

  1. Pilot with one city coordinator and calibrate the 20 mm and 0.5 settings with a local ecologist.
  2. Let volunteers record the task-card checks directly in the OneAquaHealth app.
  3. Add sewer-overflow alerts as a second trigger where cities publish them.
  4. Feed the after-storm results back in, so the evidence never goes stale again.

These are OneAquaHealth's five case-study cities; any city added to the official roster appears in AfterStorm automatically.

Share this project:

Updates

Submission history