{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "## Update a Wflow model: gauging stations" ] }, { "cell_type": "markdown", "id": "1", "metadata": {}, "source": [ "Once you have a **Wflow** model, you may want to update your model in order to use a new landuse map, change a parameter value, add sample locations, use different forcing data, create and run different scenarios etc.\n", "\n", "With HydroMT, you can easily read your model and update one or several components of your model using the **update** function of the command line interface (CLI). Here are the steps and some examples on how to **update/add gauging stations** to your model.\n", "\n", "All lines in this notebook which starts with ! are executed from the command line. Within the notebook environment the logging messages are shown after completion. You can also copy these lines and paste them in your shell to get more feedback." ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "### Import packages" ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "In this notebook, we will use some functions of HydroMT to plot the new gauging stations of the updated model. Here are the libraries to import to realize these steps." ] }, { "cell_type": "code", "execution_count": null, "id": "4", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import geopandas as gpd\n", "from shapely.geometry import box" ] }, { "cell_type": "code", "execution_count": null, "id": "5", "metadata": {}, "outputs": [], "source": [ "# for plotting\n", "import matplotlib.pyplot as plt\n", "import cartopy.io.img_tiles as cimgt\n", "import cartopy.crs as ccrs\n", "\n", "proj = ccrs.PlateCarree() # plot projection" ] }, { "cell_type": "markdown", "id": "6", "metadata": {}, "source": [ "### Locations of the gauging stations" ] }, { "cell_type": "markdown", "id": "7", "metadata": {}, "source": [ "Adding gauging stations to your **Wflow** model can be quite useful. It allows you to directly extract model outputs at specific locations. For example for model validation, calibration, you can then directly compare model results to available observations.\n", "\n", "In our previous notebook, we built a wflow model in which the locations of the available [GRDC](https://waterandchange.org/en/grdc-data-download-provides-river-discharge-data-online/) stations are including. If you have other observation data available, you can easily add them to your model using HydroMT. One way to do it is to prepare a csv table containing the ID, latitude and longitude of the available stations. An example **test_stations.csv** has been prepared. Let's have a look at it. " ] }, { "cell_type": "code", "execution_count": null, "id": "8", "metadata": {}, "outputs": [], "source": [ "fn_station = \"test_stations.csv\"\n", "with open(fn_station, \"r\", encoding=\"utf8\") as f:\n", " txt = f.read()\n", "print(txt)" ] }, { "cell_type": "markdown", "id": "9", "metadata": {}, "source": [ "Here we can see that we have defined three stations with an ID and the longitude (x) and latitude (y) coordinates, in the same EPSG system as our model (EPSG 4326). We can now add them to our model." ] }, { "cell_type": "markdown", "id": "10", "metadata": {}, "source": [ "### HydroMT CLI update interface" ] }, { "cell_type": "markdown", "id": "11", "metadata": {}, "source": [ "Using the **HydroMT build** API, we can update one or several components of an already existing Wflow model. Let's get an overview of the available options:" ] }, { "cell_type": "code", "execution_count": null, "id": "12", "metadata": {}, "outputs": [], "source": [ "# Print the options available from the update command\n", "! hydromt update --help" ] }, { "cell_type": "markdown", "id": "13", "metadata": {}, "source": [ "### Update Wflow gauging stations" ] }, { "cell_type": "markdown", "id": "14", "metadata": {}, "source": [ "Let's open the example configuration file (**wflow_update_gauges.yml**) from the model repository [examples folder] and have a look at the setup_gauges step." ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": {}, "outputs": [], "source": [ "fn_config = \"wflow_update_gauges.yml\"\n", "with open(fn_config, \"r\") as f:\n", " txt = f.read()\n", "print(txt)" ] }, { "cell_type": "markdown", "id": "16", "metadata": {}, "source": [ "Here, you see the step for updating the gauges with our test_stations.csv and giving it the name **test-flow**.\n", "Let's update the model with the following CLI command:" ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": {}, "outputs": [], "source": [ "# NOTE: copy this line (without !) to your shell for more direct feedback\n", "! hydromt update wflow_sbm wflow_piave_subbasin -o ./wflow_piave_gauges -i wflow_update_gauges.yml -v" ] }, { "cell_type": "markdown", "id": "18", "metadata": {}, "source": [ "The example above means the following: run **hydromt** with:\n", "\n", "- `update wflow`: i.e. update a wflow model\n", "- `wflow_piave_subbasin`: original model folder\n", "- `-o ./wflow_piave_gauges`: output updated model folder\n", "- `-i wflow_update_gauges.yml`: path to the update configuration file. \n", "- `v`: give some extra verbosity (2 * v) to display feedback on screen. Now debug messages are provided.\n", "\n", "Other available options are available in the [docs (setup gauges)](https://deltares.github.io/hydromt_wflow/latest/_generated/hydromt_wflow.WflowBaseModel.setup_gauges.html)." ] }, { "cell_type": "markdown", "id": "19", "metadata": {}, "source": [ "### Update Wflow gauging stations without snapping" ] }, { "cell_type": "markdown", "id": "20", "metadata": {}, "source": [ "By default, the **setup_gauges** of HydroMT Wflow will assume that gauges are for flow sampling and will therefore snap the gauges locations to the river. If your observations are used to compare rainfall data, then you do not want HydroMT to move the location of your gauges. This is done by setting `snap_to_river: False`.\n", "\n", "By default, HydroMT Wflow will update the TOML in order to save both river discharge and precipitation at the new gauges locations. With our rainfall stations, we only need to save the precipitation. We can set this with hydroMT using the options:\n", "\n", "- `gauge_toml_header: ['P-station']`: set the column name in the outputcsv file of the Wflow run in the TOML configuration\n", "- `gauge_toml_param: ['atmosphere_water__precipitation_volume_flux']`: set the Wflow variable to save in the corresponding outputcsv file column of Wflow run in the TOML configuration " ] }, { "cell_type": "code", "execution_count": null, "id": "21", "metadata": {}, "outputs": [], "source": [ "fn_config = \"wflow_update_gauges_without_snapping.yml\"\n", "with open(fn_config, \"r\") as f:\n", " txt = f.read()\n", "print(txt)" ] }, { "cell_type": "code", "execution_count": null, "id": "22", "metadata": {}, "outputs": [], "source": [ "# NOTE: copy this line (without !) to your shell for more direct feedback\n", "! hydromt update wflow_sbm wflow_piave_gauges -i wflow_update_gauges_without_snapping.yml -v" ] }, { "cell_type": "markdown", "id": "23", "metadata": {}, "source": [ "The example above means the following: run **hydromt** with:\n", "\n", "- `update wflow`: i.e. update a wflow model\n", "- `wflow_piave_gauges`: model folder to update (here we save our updates in the same model folder)\n", "- `-i wflow_update_gauges_without_snapping.yml`: the config yaml containing the additional options.\n", "- `v`: give some extra verbosity (2 * v) to display feedback on screen. Now debug messages are provided.\n", "\n", "Other available options are available in the [docs (setup gauges)](https://deltares.github.io/hydromt_wflow/latest/_generated/hydromt_wflow.WflowBaseModel.setup_gauges.html).\n", "\n" ] }, { "cell_type": "markdown", "id": "24", "metadata": {}, "source": [ "### Visualization of the gauges" ] }, { "cell_type": "markdown", "id": "25", "metadata": {}, "source": [ "We can now plot our newly created gauges stations maps and check the differences between the flow and rain maps." ] }, { "cell_type": "code", "execution_count": null, "id": "26", "metadata": {}, "outputs": [], "source": [ "# Load the updated model with hydromt\n", "from hydromt_wflow import WflowSbmModel\n", "\n", "mod = WflowSbmModel(root=\"wflow_piave_gauges\", mode=\"r\")" ] }, { "cell_type": "code", "execution_count": null, "id": "27", "metadata": {}, "outputs": [], "source": [ "# read/derive river geometries\n", "gdf_riv = mod.rivers\n", "# read/derive model basin boundary\n", "gdf_bas = mod.basins" ] }, { "cell_type": "code", "execution_count": null, "id": "28", "metadata": {}, "outputs": [], "source": [ "# Plot\n", "# we assume the model maps are in the geographic CRS EPSG:4326\n", "proj = ccrs.PlateCarree()\n", "# adjust zoomlevel and figure size to your basis size & aspect\n", "zoom_level = 10\n", "figsize = (10, 8)\n", "shaded = False\n", "\n", "# initialize image with geoaxes\n", "fig = plt.figure(figsize=figsize)\n", "ax = fig.add_subplot(projection=proj)\n", "bounds = mod.region.total_bounds\n", "bbox = gpd.GeoDataFrame(geometry=[box(*bounds)], crs=mod.crs).to_crs(3857).buffer(5e3)\n", "extent = np.array(bbox.to_crs(mod.crs).total_bounds)[[0, 2, 1, 3]]\n", "ax.set_extent(extent, crs=proj)\n", "\n", "# add sat background image\n", "ax.add_image(cimgt.QuadtreeTiles(), zoom_level, alpha=0.5)\n", "\n", "# plot rivers with increasing width with stream order\n", "gdf_riv.plot(ax=ax, lw=gdf_riv[\"strord\"] / 2, color=\"blue\", zorder=3, label=\"river\")\n", "# plot the basin boundary\n", "gdf_bas.boundary.plot(ax=ax, color=\"k\", linewidth=0.5)\n", "if \"gauges\" in mod.geoms.data:\n", " mod.geoms.get(\"gauges\").plot(\n", " ax=ax, marker=\"d\", markersize=25, facecolor=\"k\", zorder=5, label=\"outlet\"\n", " )\n", "if \"gauges_grdc\" in mod.geoms.data:\n", " mod.geoms.get(\"gauges_grdc\").plot(\n", " ax=ax,\n", " marker=\"d\",\n", " markersize=25,\n", " facecolor=\"purple\",\n", " zorder=5,\n", " label=\"Gauges GRDC\",\n", " )\n", "if \"gauges_test-flow\" in mod.geoms.data:\n", " mod.geoms.get(\"gauges_test-flow\").plot(\n", " ax=ax, marker=\"d\", markersize=25, facecolor=\"red\", zorder=5, label=\"Gauges Flow\"\n", " )\n", "if \"gauges_test-rain\" in mod.geoms.data:\n", " mod.geoms.get(\"gauges_test-rain\").plot(\n", " ax=ax,\n", " marker=\"d\",\n", " markersize=25,\n", " facecolor=\"green\",\n", " zorder=5,\n", " label=\"Gauges Rain\",\n", " )\n", "\n", "ax.xaxis.set_visible(True)\n", "ax.yaxis.set_visible(True)\n", "ax.set_ylabel(f\"latitude [degree north]\")\n", "ax.set_xlabel(f\"longitude [degree east]\")\n", "_ = ax.set_title(f\"wflow base map\")\n", "legend = ax.legend(\n", " handles=[*ax.get_legend_handles_labels()[0]],\n", " title=\"Legend\",\n", " loc=\"lower right\",\n", " frameon=True,\n", " framealpha=0.7,\n", " edgecolor=\"k\",\n", " facecolor=\"white\",\n", ")" ] } ], "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.9" } }, "nbformat": 4, "nbformat_minor": 5 }