{ "cells": [ { "cell_type": "markdown", "id": "d1b7a6c5-62f9-4c75-80dc-3bfcb594f380", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "---\n", "title: Flood areas in Saarland\n", "subtitle: Visualizing Generalized Flood Areas for HQ100 Event and relate to an existing flooding event.\n", "authors:\n", " - name: Anne Fouilloux\n", " orcid: 0000-0002-1784-2920\n", " github: annefou\n", " affiliations:\n", " - id: Simula Research Laboratory\n", " institution: Simula Research Laboratory\n", " ror: 00vn06n10\n", "date: 2025-05-14\n", "keywords : flooding\n", "---" ] }, { "cell_type": "markdown", "id": "71f3a69b-ca3e-4c56-8134-1fe01b4bae27", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "```{image} https://www.en.urbandataplatform.hamburg/resource/crblob/797502/9c2f2d2edc1149673134bf88ece1dda5/logo-udp-data.jpg\n", ":alt: Urban Data Portal Logo\n", ":width: 250px\n", ":align: center\n", "```" ] }, { "cell_type": "markdown", "id": "69d30de9-f559-4e55-94b8-2a0c053d1cd8", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(introduction)=\n", "# Introduction\n", "\n", "## Flood areas in Saarland\n", "\n", "Saarland, located in southwestern Germany, is particularly vulnerable to flooding due to its dense river network and hilly terrain. Periodic heavy rainfall and overflowing rivers like the Saar and Blies can lead to widespread inundation, especially in low-lying urban and industrial zones. The HQ100 flood areas represent regions statistically likely to flood once every 100 years, serving as critical indicators for urban planning, risk management, and environmental protection. Mapping these zones is essential for identifying vulnerable communities and infrastructure, including industrial facilities that may pose additional environmental risks during extreme flood events.\n", "\n", "\n", "## Purpose\n", "\n", "### Visualizing Generalized Flood Areas and Environmental Risk Sites in Saarland\n", "\n", "This Jupyter notebook provides an interactive visualization of the **generalized flood areas (Area100_generalized)** associated with a **100-year flood event (HQ100)** in Saarland. It integrates spatial data from the **Hamburg Urban Data Portal** and the **Geoportal Saarland**, as well as the geolocation of a Wikimedia Commons photo illustrating flood conditions.\n", "\n", "#### 🌊 About the HQ100 Flood Area Dataset\n", "\n", "- **Event type**: HQ100 (statistical 100-year flood)\n", "- **Layer**: Area100_generalized\n", "- **Data source**: Hamburg Urban Data Portal\n", "- **Coordinate system**: WGS84 (EPSG:4326)\n", "- **Date**: 01.06.2018\n", "- **Coverage**: \n", " - **SW corner**: 6.31°E, 49.1°N \n", " - **NE corner**: 7.41°E, 49.64°N\n", "\n", "This dataset shows flood-prone areas and is useful for planning, disaster risk assessment, and climate adaptation studies.\n", "\n", "#### 🏭 IED (IVU) Facilities in Flood-Prone Zones\n", "\n", "We additionally integrate data from the **Geoportal Saarland** on **IED-regulated industrial facilities** that could pose environmental risks during floods. These facilities are categorized under the EU’s **IVU (Integrated Pollution Prevention and Control) directive**, which mandates special precautions for pollution control.\n", "\n", "- **Dataset**: Hochwasserrisiko – IED-Betriebe des Saarlandes\n", "- **Attributes**:\n", " - `GEWAESSER`: River name\n", " - `BETRIEB`: Facility name\n", " - `GEMEINDE`, `GEMARKUNG`: Municipality & land registry info\n", " - `GEWKZ`: River code\n", "- **Coordinate system**: WGS84\n", "- **Timeliness**:\n", " - Created: 10.07.2012\n", " - Last updated: 01.06.2018\n", "- **Download options**:\n", " - [WFS](https://geoportal.saarland.de/arcgis/services/Internet/Hochwasser_WFS/MapServer/WFSServer?&request=GetCapabilities&VERSION=1.1.0&SERVICE=WFS)\n", " - [Shapefile ZIP](https://www.shop.lvgl.saarland.de/cloud/index.php/s/GDZ_Hochwasser/download?path=IED-Anlagen)\n", "\n", "**License**: Creative Commons Attribution 4.0 International (CC BY 4.0) \n", "**Attribution**: © GDI-SL (2018) \n", "**Contact**: poststelle@umwelt.saarland.de\n", "\n", "#### 📸 Image Location Reference\n", "\n", "A geotagged image from Wikimedia Commons showing flood impact is added for visual context. This demonstrates how photo evidence can complement official geospatial data in public awareness or participatory science initiatives.\n" ] }, { "cell_type": "markdown", "id": "669f66e9-920c-42ef-affc-2606777172e2", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(overview)=\n", ":::{hint} Overview\n", "Questions\n", "\n", "What data from the Hamburg and Saarland Urban Data Portals are we visualizing?\n", "\n", "How can the visualization of flood zones and industrial facilities support flood risk assessment?\n", "\n", "Objectives\n", "\n", "Load and map HQ100 generalized flood zones and IED-regulated facilities.\n", "\n", "Analyze spatial relationships between flood-prone areas, industrial sites, and citizen-reported observations (e.g., photos).\n", ":::" ] }, { "cell_type": "markdown", "id": "6f37b746-0954-4073-965d-08f5f4f1cf05", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(requirements)=\n", "## Requirements\n", "Start installing and importing the necessary libraries\n", "### Install Python Packages" ] }, { "cell_type": "code", "execution_count": null, "id": "7b895abf-c613-49f8-86f3-dbfe765788cc", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "pip install geopandas matplotlib pillow" ] }, { "cell_type": "markdown", "id": "4d699a3b-769f-4149-9932-de2a947b98e2", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(setup)=\n", "### Import Python Packages" ] }, { "cell_type": "code", "execution_count": null, "id": "0f19b79c-f9a2-482d-8c77-a9c1c470df72", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "import json\n", "import os\n", "from io import BytesIO\n", "\n", "import geopandas as gpd\n", "import matplotlib.pyplot as plt\n", "import requests\n", "from jupytergis import GISDocument\n", "from PIL import Image as PILImage" ] }, { "cell_type": "markdown", "id": "e553adf6-febc-4068-989e-0255844324e1", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(functions)=\n", "### Define functions" ] }, { "cell_type": "code", "execution_count": null, "id": "7e6e2126-0a65-4f7a-8d6c-5b76f581c3ff", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "def get_data_from_wfs(wfs_url, params):\n", " try:\n", " # Fetch data\n", " r = requests.get(wfs_url, params=params)\n", " r.raise_for_status() # Check for HTTP errors\n", "\n", " # Read GML directly into GeoDataFrame\n", " gml_data = BytesIO(r.content)\n", " data = gpd.read_file(gml_data, driver=\"GML\")\n", " return data\n", "\n", " except requests.exceptions.RequestException as e:\n", " print(f\"Request failed: {e}\")\n", " except Exception as e:\n", " print(f\"Failed to parse GML: {e}\")" ] }, { "cell_type": "code", "execution_count": null, "id": "0a65c479-5765-4791-8053-ed07d3ff0ebc", "metadata": {}, "outputs": [], "source": [ "def get_image_metadata(filename):\n", " gps_lat = None\n", " gps_lon = None\n", " extmetadata = None\n", " image_url = None\n", "\n", " url = \"https://commons.wikimedia.org/w/api.php\"\n", " params = {\n", " \"action\": \"query\",\n", " \"titles\": f\"File:{filename}\",\n", " \"prop\": \"imageinfo\",\n", " \"iiprop\": \"extmetadata|url\",\n", " \"format\": \"json\",\n", " }\n", "\n", " response = requests.get(url, params=params)\n", " response.raise_for_status()\n", " data = response.json()\n", "\n", " pages = data.get(\"query\", {}).get(\"pages\", {})\n", " for page in pages.values():\n", " imageinfo = page.get(\"imageinfo\", [{}])[0]\n", " extmetadata = imageinfo.get(\"extmetadata\", {})\n", " image_url = imageinfo.get(\"url\", None)\n", "\n", " # GPS data if available and convertible\n", " lat_str = extmetadata.get(\"GPSLatitude\", {}).get(\"value\", None)\n", " lon_str = extmetadata.get(\"GPSLongitude\", {}).get(\"value\", None)\n", "\n", " gps_lat = float(lat_str) if lat_str else None\n", " gps_lon = float(lon_str) if lon_str else None\n", "\n", " return gps_lon, gps_lat, extmetadata, image_url" ] }, { "cell_type": "code", "execution_count": null, "id": "7538e60e-8b2d-4569-9c7e-2c8c8a16e398", "metadata": {}, "outputs": [], "source": [ "def show_image_from_url(image_url):\n", " headers = {\n", " \"User-Agent\": \"MyOpenSourceBot/1.0 (https://example.org/mybot; myemail@example.org)\"\n", " }\n", " response = requests.get(image_url, headers=headers)\n", " response.raise_for_status()\n", "\n", " image = PILImage.open(BytesIO(response.content))\n", " plt.imshow(image)\n", " plt.axis(\"off\")\n", " plt.title(\"Image from Wikimedia Commons\")\n", " plt.show()" ] }, { "cell_type": "markdown", "id": "84ecc2dc-e91d-4a82-922c-57fa4e913526", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(parameters)=\n", "## Input data required\n", "### Set input parameters for getting data\n", "\n", "#### Generalized flood areas in a HQ100 event \n", "- Data from the Hamburg Urban Data Portal [HQ100 Area100 generalized](https://www.metaver.de:443/trefferanzeige?docuuid=951ceb7b-7e60-4300-9db1-0d9fe6a062b0&q=Hochwasserschutz&rstart=10¤tSelectorPage=1&f=type:opendata;metadata_group:geoset;&lang=de )\n", "- The HQ100 represents the land use of the flooded areas during events. Area100_generalized\n", "- Timeliness of the data set: 01.06.2018\n", "\n", "#### Flood risk - IED companies in Saarland\n", "\n", "- [Flood risk IED Companies in Saarland](https://www.metaver.de:443/trefferanzeige?docuuid=391766b5-de80-4fe1-afc5-9c094e553f34&q=Saarland&rstart=90&f=type:opendata;metadata_group:geoset;&lang=de ) Data from the Hamburg Urban Data Portal " ] }, { "cell_type": "code", "execution_count": null, "id": "1215e08e-c4d8-4eef-92f7-9708c4762bdc", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "parameters" ] }, "outputs": [], "source": [ "# WFS URL for HQ100\n", "wfs_url_hq100: str = (\n", " \"https://geoportal.saarland.de/arcgis/services/Internet/Hochwasser_WFS/MapServer/WFSServer?&request=GetCapabilities&VERSION=1.1.0&SERVICE=WFS\"\n", ")\n", "\n", "# Feature type\n", "feature_typename_hq100: str = \"Hochwasser_WFS:Flaeche100_generalisiert\"\n", "\n", "# Output file name (Geojson)\n", "filename_hq100: str = \"HQ100_Flaeche100_generalisiert_4326.geojson\"\n", "\n", "# WFS URL for IED\n", "wfs_url_ied: str = (\n", " \"https://geoportal.saarland.de/arcgis/services/Internet/Hochwasser_WFS/MapServer/WFSServer?&request=GetCapabilities&VERSION=1.1.0&SERVICE=WFS\"\n", ")\n", "\n", "# Feature type\n", "feature_typename_ied: str = \"Hochwasser_WFS:Betr_EW\"\n", "\n", "# Output file name (Geojson)\n", "filename_ied: str = \"Hochwasser_WFS_Betr_EW_4326.geojson\"\n", "\n", "# wikimedia common artefact (picture)\n", "wikimedia_filename: str = \"20240517_Flood_Saarland_07.jpg\"\n", "wikimedia_artefact_location_filename: str = \"artefact_location.geojson\"\n", "\n", "# JupyterGIS output filename\n", "jupytergis_filename: str = \"Saarland_flood_20240517.jGIS\"" ] }, { "cell_type": "markdown", "id": "0e460095-15e2-43db-9a12-d53469d7133c", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(retrieve)=\n", "## Get data from the Hamburg Urban Data Portal using WFS" ] }, { "cell_type": "code", "execution_count": null, "id": "4a837eb5-86a3-4046-bef7-b912e766afe3", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "# Specify parameters\n", "params_hq100 = {\n", " \"service\": \"WFS\",\n", " \"request\": \"GetFeature\",\n", " \"typeName\": feature_typename_hq100,\n", "}\n", "\n", "dset_hq100 = get_data_from_wfs(wfs_url_hq100, params_hq100)" ] }, { "cell_type": "code", "execution_count": null, "id": "4f09ad9d-a6dc-4b34-a8e2-c2f9b5403e3b", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "# Specify parameters\n", "params_ied = {\n", " \"service\": \"WFS\",\n", " \"request\": \"GetFeature\",\n", " \"typeName\": feature_typename_ied,\n", "}\n", "\n", "dset_ied = get_data_from_wfs(wfs_url_ied, params_ied)" ] }, { "cell_type": "markdown", "id": "bf26954f-c9f5-40ef-8a2a-da4c0b0517a0", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(outputs)=\n", "## Save to geojson with WSG84 (epsg:4326) projection" ] }, { "cell_type": "code", "execution_count": null, "id": "870b96bc-9bcc-4e3f-9754-0fbf0e1ea8e9", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "if os.path.exists(filename_hq100):\n", " print(\"Skipped creation: file already exists.\")\n", "else:\n", " dset_hq100.to_crs(4326).to_file(filename_hq100, encoding=\"utf-8\")" ] }, { "cell_type": "code", "execution_count": null, "id": "59adda85-01f9-47ba-aead-d01040be5a46", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "if os.path.exists(filename_ied):\n", " print(\"Skipped creation: file already exists.\")\n", "else:\n", " dset_ied.to_crs(4326).to_file(filename_ied, encoding=\"utf-8\")" ] }, { "cell_type": "markdown", "id": "1d7e6953-a7d4-4c83-9b5c-f3ca5c3cf4c9", "metadata": {}, "source": [ "(retrieve)=\n", "## Get location of picture from Wikimedia Commons" ] }, { "cell_type": "code", "execution_count": null, "id": "d71b5373-e3bf-46f0-a1a9-41572780d4af", "metadata": {}, "outputs": [], "source": [ "gps_lon, gps_lat, all_metadata, image_url = get_image_metadata(wikimedia_filename)\n", "\n", "print(\"Image URL: \", image_url)\n", "print(\"GPS Coordinates:\", gps_lon, gps_lat)\n", "print(\"metadata:\", all_metadata)" ] }, { "cell_type": "markdown", "id": "987876cb-adbd-4822-b7d2-3e6629dada06", "metadata": {}, "source": [ "### Create geojson for picture location" ] }, { "cell_type": "code", "execution_count": null, "id": "57915bd3-b0f8-49ba-af86-6fb215530bdd", "metadata": {}, "outputs": [], "source": [ "artefact_location = {\n", " \"type\": \"FeatureCollection\",\n", " \"features\": [\n", " {\n", " \"type\": \"Feature\",\n", " \"properties\": {\n", " \"id\": \"camera_location\",\n", " \"description\": all_metadata[\"ImageDescription\"][\"value\"],\n", " },\n", " \"geometry\": {\"type\": \"Point\", \"coordinates\": [gps_lon, gps_lat]},\n", " }\n", " ],\n", "}" ] }, { "cell_type": "markdown", "id": "67311c75-b45b-4655-9f9f-9007bf4684de", "metadata": {}, "source": [ "(outputs)=\n", "### Save geosjon to file" ] }, { "cell_type": "code", "execution_count": null, "id": "c758cc9b-b206-4bc0-b7ee-a31b1c5ef892", "metadata": {}, "outputs": [], "source": [ "with open(wikimedia_artefact_location_filename, \"w\") as f:\n", " json.dump(artefact_location, f)" ] }, { "cell_type": "markdown", "id": "7fc31ca2-c9b1-4165-9d12-7734aac591fb", "metadata": {}, "source": [ "(figure)=\n", "\n", "## Show Wikimedia photo" ] }, { "cell_type": "code", "execution_count": null, "id": "5e7ab7fb-e9c9-4ca6-aa91-3036d35d0b25", "metadata": {}, "outputs": [], "source": [ "show_image_from_url(image_url)" ] }, { "cell_type": "markdown", "id": "d2d19b56-f346-43ed-b4f5-62d90089ef04", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(jupytergis)=\n", "\n", "## Create JupyterGIS map\n", "### Open Jupyter notebook" ] }, { "cell_type": "code", "execution_count": null, "id": "b40eacdb-194b-4f30-b7fc-7a04e40c4e0e", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "doc = GISDocument(\n", " jupytergis_filename,\n", " latitude=gps_lat,\n", " longitude=gps_lon,\n", " zoom=6,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "91c4ab54-6921-45bf-b5f5-db1bf8ea79c2", "metadata": {}, "outputs": [], "source": [ "doc" ] }, { "cell_type": "markdown", "id": "1d7e6c7e-9869-47a4-a2d5-012488667376", "metadata": {}, "source": [ "(jupytergis-add-layer)=\n", "### Add basemap layer" ] }, { "cell_type": "code", "execution_count": null, "id": "4aaf5b51-5e72-4b5a-a2a2-a76cc6cc94f9", "metadata": {}, "outputs": [], "source": [ "doc.add_raster_layer(\n", " url=\"https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}\",\n", " name=\"Google Satellite\",\n", " attribution=\"Google\",\n", " opacity=0.6,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "a739be2f-14b2-4cd5-b8c6-069ee771e04e", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "doc.layers" ] }, { "cell_type": "markdown", "id": "492f7f56-81be-40bf-acc7-51abe57e7587", "metadata": {}, "source": [ "(jupytergis-add-layer)=" ] }, { "cell_type": "markdown", "id": "da291fc8-7027-4da6-9c26-95fac8cdd8c4", "metadata": {}, "source": [ "(jupytergis-add-layer)=\n", "### Add HQ100 Flood Area Layer" ] }, { "cell_type": "code", "execution_count": null, "id": "be6b4a12-2fc6-40cc-8ed8-85c4bf6a2996", "metadata": {}, "outputs": [], "source": [ "doc.add_geojson_layer(\n", " path=filename_hq100,\n", " name=\"HQ100 generalized flood zones\",\n", " color_expr={\n", " \"fill-color\": \"#00f2ff\",\n", " \"stroke-width\": 4.25,\n", " \"stroke-color\": \"#0400ff\",\n", " },\n", ")" ] }, { "cell_type": "markdown", "id": "db7acb2d-3fc4-45d6-931b-4323729dda0b", "metadata": {}, "source": [ "(jupytergis-add-layer)=\n", "### Add the locations of companies at risk of flooding in Saarland." ] }, { "cell_type": "code", "execution_count": null, "id": "eb90c63d-04b1-4e96-8856-c4e54cbd99c8", "metadata": {}, "outputs": [], "source": [ "doc.add_geojson_layer(\n", " path=filename_ied,\n", " name=\"Businesses at risk in Saarland\",\n", " type=\"circle\",\n", " color_expr={\n", " \"circle-radius\": 9,\n", " \"circle-stroke-width\": 4.25,\n", " \"circle-stroke-color\": \"#d400ff\",\n", " \"circle-fill-color\": \"#ffb700\",\n", " },\n", ")" ] }, { "cell_type": "markdown", "id": "c5cc133e-5d0b-4133-a4b4-8d4d0b9ba30e", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "(jupytergis-add-layer)=\n", "### Add location of the picture from Wikimedia Commons" ] }, { "cell_type": "code", "execution_count": null, "id": "317f9521-f3dd-4c1a-b3f7-be1810e1a114", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "doc.add_geojson_layer(\n", " path=wikimedia_artefact_location_filename,\n", " name=\"Artefact Location\",\n", " type=\"circle\",\n", " color_expr={\n", " \"circle-radius\": 10,\n", " \"circle-stroke-width\": 5.25,\n", " \"circle-stroke-color\": \"#ff3700\",\n", " \"circle-fill-color\": \"#fff700\",\n", " },\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "2f3e6baa-eb0a-438e-ac83-d440327407bc", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "c06101ab-8520-441b-989f-6397ff4be712", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.1" } }, "nbformat": 4, "nbformat_minor": 5 }