{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Alpine monatliche Niederschlagsdaten" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alpine monatliche Niederschlagsdaten seit 1871, abgeleitet aus stationären Beobachtungen: Der LAPrec-Datensatz (Long-term Alpine Precipitation Reconstruction) bietet monatliche Niederschlagsdaten für die Alpenregion und basiert auf stationären Beobachtungen. Es gibt zwei Versionen:\n", "\n", "* LAPrec1871 (ab 1871, 85 Eingabereihen)\n", "* LAPrec1901 (ab 1901, 165 Eingabereihen)\n", " \n", "Der Datensatz erfüllt hohe klimatische Standards und ist eine wertvolle Grundlage für historische Klimaanalysen in den Alpen, einer Region, die stark vom Klimawandel betroffen ist. Es kombiniert die Datenquellen HISTALP (homogenisierte stationäre Niederschlagsdaten) und APGD (tägliche Rasterdaten von 1971–2008) und nutzt die Methode der Reduced Space Optimal Interpolation (RSOI). LAPrec wird alle zwei Jahre aktualisiert und wurde im Rahmen des Copernicus Climate Change Service in Zusammenarbeit mit den Wetterdiensten von Schweiz (MeteoSwiss) und Österreich (ZAMG) entwickelt.\n", "\n", "**Informationen zum Datensatz:**\n", "* Quelle: [Alpine Monthly Precipitation](https://cds.climate.copernicus.eu/datasets/insitu-gridded-observations-alpine-precipitation?tab=overview)\n", "* Author: T. Tewes (City of Konstanz)\n", "* Notebook-Version: 1.1 (Aktualisiert: Dezember 05, 2024)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Festlegen der Pfade und Arbeitsverzeichnisse" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "''' ---- Verzeichnisse hier angeben ---- '''\n", "download_folder = r\".\\data\\alpine-monthly-precipitation\\download\"\n", "working_folder = r\".\\data\\alpine-monthly-precipitation\\working\"\n", "geotiff_folder = r\".\\data\\alpine-monthly-precipitation\\geotiff\"\n", "csv_folder = r\".\\data\\alpine-monthly-precipitation\\csv\"\n", "output_folder = r\".\\data\\alpine-monthly-precipitation\\output\"\n", "''' ----- Ende der Angaben ---- '''\n", "\n", "os.makedirs(download_folder, exist_ok=True)\n", "os.makedirs(working_folder, exist_ok=True)\n", "os.makedirs(geotiff_folder, exist_ok=True)\n", "os.makedirs(csv_folder, exist_ok=True)\n", "os.makedirs(output_folder, exist_ok=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Herunterladen und Entpacken des Datensatzes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.1 Authentifizierung" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import cdsapi\n", "\n", "def main():\n", " # API-Key für die Authentifizierung\n", " api_key = \"fdae60fd-35d4-436f-825c-c63fedab94a4\"\n", " api_url = \"https://cds.climate.copernicus.eu/api\"\n", "\n", " # Erstellung des CDS-API-Clients\n", " client = cdsapi.Client(url=api_url, key=api_key)\n", " return client" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2 Definieren die „request“ und laden Sie den Datensatz herunter" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Definition des Datensatzes und der Request-Parameter\n", "dataset = \"insitu-gridded-observations-alpine-precipitation\"\n", "request = {\n", " \"variable\": \"precipitation\",\n", " \"dataset_issue\": [\n", " \"laprec1871\",\n", " \"laprec1901\"\n", " ],\n", " \"version\": [\"1_2\"],\n", "}" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'os' is not defined", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[3], line 16\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mDatensatz bereits heruntergeladen.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 15\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;18m__name__\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m__main__\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m---> 16\u001b[0m \u001b[43mmain_retrieve\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", "Cell \u001b[1;32mIn[3], line 4\u001b[0m, in \u001b[0;36mmain_retrieve\u001b[1;34m()\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mmain_retrieve\u001b[39m():\n\u001b[0;32m 3\u001b[0m dataset_filename \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mdataset\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.zip\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m----> 4\u001b[0m dataset_filepath \u001b[38;5;241m=\u001b[39m \u001b[43mos\u001b[49m\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(download_folder, dataset_filename)\n\u001b[0;32m 6\u001b[0m \u001b[38;5;66;03m# Den Datensatz nur herunterladen, wenn er noch nicht heruntergeladen wurde\u001b[39;00m\n\u001b[0;32m 7\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39misfile(dataset_filepath):\n\u001b[0;32m 8\u001b[0m \u001b[38;5;66;03m# Rufen Sie den CDS-Client nur auf, wenn der Datensatz noch nicht heruntergeladen wurde.\u001b[39;00m\n", "\u001b[1;31mNameError\u001b[0m: name 'os' is not defined" ] } ], "source": [ "# Führen Sie es aus, um den Datensatz herunterzuladen:\n", "def main_retrieve():\n", " dataset_filename = f\"{dataset}.zip\"\n", " dataset_filepath = os.path.join(download_folder, dataset_filename)\n", "\n", " # Den Datensatz nur herunterladen, wenn er noch nicht heruntergeladen wurde\n", " if not os.path.isfile(dataset_filepath):\n", " # Rufen Sie den CDS-Client nur auf, wenn der Datensatz noch nicht heruntergeladen wurde.\n", " client = main()\n", " # Den Datensatz mit den definierten Anforderungsparametern herunterladen\n", " client.retrieve(dataset, request, dataset_filepath)\n", " else:\n", " print(\"Datensatz bereits heruntergeladen.\")\n", "\n", "if __name__ == \"__main__\":\n", " main_retrieve()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.3 Extrahieren die ZIP-Datei in Ordner" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import zipfile\n", "\n", "# Erstellen des Dateinamens und des Dateipfads für die ZIP-Datei des Datensatzes\n", "dataset_filename = f\"{dataset}.zip\"\n", "dataset_filepath = os.path.join(download_folder, dataset_filename)\n", "\n", "# Definieren Sie einen Extraktionsordner für die ZIP-Datei, der dem Arbeitsordner entspricht\n", "extract_folder = working_folder\n", "\n", "# Entpacken der ZIP-Datei\n", "try:\n", " os.makedirs(extract_folder, exist_ok=True)\n", " \n", " if not os.listdir(extract_folder):\n", " # Versuchen Sie, die ZIP-Datei zu öffnen und zu extrahieren\n", " with zipfile.ZipFile(dataset_filepath, 'r') as zip_ref:\n", " zip_ref.extractall(extract_folder)\n", " print(f\"Dateien erfolgreich extrahiert nach: {extract_folder}\")\n", " else:\n", " print(\"Ordner ist nicht leer. Entpacken überspringen.\")\n", "except FileNotFoundError:\n", " print(f\"Fehler: Die Datei {dataset_filepath} wurde nicht gefunden.\")\n", "except zipfile.BadZipFile:\n", " print(f\"Fehler: Die Datei {dataset_filepath} ist keine gültige ZIP-Datei.\")\n", "except Exception as e:\n", " print(f\"Ein unerwarteter Fehler ist aufgetreten: {e}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Untersuchen der Metadaten der NetCDF4-Datei" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Liste der netCDF4-Dateien im Arbeits-/extrahierten Ordner drucken\n", "filename_list = os.listdir(extract_folder)\n", "print(filename_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Der Datensatz Monatliche Niederschläge in den Alpen enthält Aufzeichnungen ab 1871 oder 1901. In diesem Notizbuch verwenden wir den Datensatz von 1901 (LAPrec1901)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import netCDF4 as nc\n", "\n", "# Definieren Sie den Dateipfad für den ausgewählten NetCDF-Datensatz\n", "nc_filename = \"LAPrec1901.v1.2.nc\"\n", "nc_filepath = os.path.join(extract_folder, nc_filename)\n", "\n", "# Öffnen der NetCDF-Datei im Lesemodus\n", "nc_dataset = nc.Dataset(nc_filepath, mode='r')\n", "\n", "# Auflisten aller Variablen im Datensatz\n", "variables_list = list(nc_dataset.variables.keys())\n", "print(f\"Verfügbare Variablen: {list(variables_list)}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "# Variablennamen aus vorhandenen Variablen definieren und Variablendaten lesen\n", "variable_name = 'LAPrec1901'\n", "variable_data = nc_dataset[variable_name]\n", "\n", "# Erstellen einer Zusammenfassung der Hauptvariablen\n", "summary = {\n", " \"Variablename\": variable_name,\n", " \"Datentyp\": variable_data.dtype,\n", " \"Form\": variable_data.shape,\n", " \"Variableinfo\": f\"{variable_name}({', '.join(variable_data.dimensions)})\",\n", " \"Einheiten\": getattr(variable_data, \"units\", \"N/A\"),\n", " \"Langer Name\": getattr(variable_data, \"long_name\", \"N/A\"),\n", "}\n", "\n", "# Anzeigen der Zusammenfassung des Datensatzes als DataFrame zur besseren Visualisierung\n", "nc_summary = pd.DataFrame(list(summary.items()), columns=['Beschreibung', 'Bemerkungen'])\n", "\n", "# Anzeigen des Zusammenfassungs-DataFrames\n", "nc_summary" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Drucken Sie eine Zusammenfassung aller Variablen des Datensatzes\n", "rows = []\n", "for variable in variables_list:\n", " try:\n", " var_obj = nc_dataset.variables[variable]\n", " unit = getattr(var_obj, 'units', 'N/A')\n", " shape = var_obj.shape\n", " rows.append({\n", " \"nc_variablen\": variable,\n", " \"einheit\": unit,\n", " \"form\": shape\n", " })\n", " except Exception as e:\n", " print(f\"Fehler bei der Verarbeitung der Variable {variable}: {e}\")\n", "\n", "# Erstelle ein DataFrame\n", "df = pd.DataFrame(rows)\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Exportieren der Datensatz im CSV-Format" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.1 Begrenzungsrahmen zum Filtern von Daten für Konstanz definieren" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Zusätzliche Anforderungsfelder definieren, um sicherzustellen, dass die Anfrage innerhalb der Dateigrößenbegrenzung bleibt.\n", "# Diese Koordinaten wurden mit dem BBox Extractor Tool erhalten:\n", "# https://str-ucture.github.io/bbox-extractor/\n", "\n", "# Begrenzungsbox für die Region Konstanz (WGS84-Projektion):\n", "bbox_wgs84_konstanz = [47.9, 8.9, 47.6, 9.3] # Format: [Norden, Westen, Süden, Osten]\n", "bbox_wgs84_konstanz_standard = [9.0, 47.6, 9.3, 47.8] # Standardformat: [Westen, Süden, Osten, Norden]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Alternativ können Sie ein Shapefile für eine präzise geografische Filterung verwenden\n", "import geopandas as gpd\n", "import matplotlib.pyplot as plt\n", "from pyproj import Transformer\n", "\n", "# Beispiel: Shapefile von Konstanz laden (WGS84-Projektion)\n", "shapefile = r\"./shapefiles/kn_boundary.shp\"\n", "gdf = gpd.read_file(shapefile)\n", "\n", "# Extrahieren Sie den Begrenzungsrahmen des Shapefiles\n", "shapefile_epsg = gdf.crs.to_epsg()\n", "shapefile_bounds = gdf.total_bounds\n", "\n", "# Definieren Sie die Quell- und Zielprojektionen\n", "proj_shapefile = f\"epsg:{shapefile_epsg}\" # Quellprojektion (CRS der Shape-Datei)\n", "proj_laea = \"epsg:3035\" # Zielprojektion (LAEA für Europa)\n", "\n", "# Definieren Sie einen Transformator, um die Koordinaten von der Quell- in die Zielprojektion umzuwandeln\n", "transformer = Transformer.from_crs(proj_shapefile, proj_laea, always_xy=True)\n", "\n", "# Transformieren Sie die Koordinaten des Begrenzungsrahmens in die Zielprojektion (LAEA)\n", "x_min, y_min = transformer.transform(shapefile_bounds[0], shapefile_bounds[1]) # Untere linke Ecke\n", "x_max, y_max = transformer.transform(shapefile_bounds[2], shapefile_bounds[3]) # Obere rechte Ecke\n", "shapefile_bounds_laea = [x_min, y_min, x_max, y_max] # Begrenzungsrahmen in LAEA-Projektion\n", "\n", "# Anzeige des transformierten Begrenzungsrahmens\n", "print(\"Begrenzungsrahmen in LAEA:\", shapefile_bounds_laea)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(f\"Koordinatensystem: EPSG({shapefile_epsg})\")\n", "print(f\"Bounding Box: {shapefile_bounds}\")\n", "\n", "# Schnelles Plotten Ihres Shapefiles\n", "gdf.plot()\n", "plt.title(\"Shapefile Darstellung\")\n", "plt.xlabel(\"Längengrad / X\")\n", "plt.ylabel(\"Breitengrad / Y\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> Wichtig: Im Allgemeinen ist **kn_bounds_laea** ausreichend für die Extraktion von CSV- und GeoTIFF-Dateien. Allerdings können Anpassungen erforderlich sein, da:\n", "\n", "* **x** und **y** die Mittelpunkte der Rasterzellen darstellen, wodurch die Begrenzungsbox-Kanten möglicherweise nicht genau mit diesen Mittelpunkten übereinstimmen.\n", "* Ohne Anpassung könnten Rasterzellen nahe den Rändern ausgeschlossen werden, wenn die Begrenzungsbox-Kanten zwischen den Zellzentren liegen.\n", "* Eine Anpassung stellt sicher, dass alle relevanten Rasterzellen einbezogen werden.\n", "\n", "