From ae3ed31e21d8120212365e59cc26b73407e9ae3d Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Tue, 13 Jan 2026 14:05:55 +0100 Subject: [PATCH 01/17] Introducing NetworkPointObservation --- notebooks/Network_comparison.ipynb | 2247 +++++++++++++++++++++++++++ src/modelskill/matching.py | 14 +- src/modelskill/obs.py | 26 + src/modelskill/timeseries/_point.py | 8 +- src/modelskill/types.py | 2 + 5 files changed, 2293 insertions(+), 4 deletions(-) create mode 100644 notebooks/Network_comparison.ipynb diff --git a/notebooks/Network_comparison.ipynb b/notebooks/Network_comparison.ipynb new file mode 100644 index 000000000..7a7b78124 --- /dev/null +++ b/notebooks/Network_comparison.ipynb @@ -0,0 +1,2247 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "e91978fd", + "metadata": {}, + "outputs": [], + "source": [ + "import modelskill as ms\n", + "import mikeio1d as m1d\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "751cfe2e", + "metadata": {}, + "outputs": [], + "source": [ + "# def df_column_name_generator(data, *, quantity=None, reach=None, gridpoint_index=None, chainage=None, node=None):\n", + "# separator = \":\"\n", + "# col_head = [quantity]\n", + "# if node is not None:\n", + "# col_tail = [node]\n", + "# if reach is not None:\n", + "# if (gridpoint_index is None) and (chainage is not None):\n", + "# col_tail = [reach, chainage]\n", + "# elif (gridpoint_index is not None) and (chainage is None):\n", + "# # Find chainage based on reach and index\n", + "# raise NotImplementedError()\n", + "# else:\n", + "# raise ValueError(\"If specifying by reach, use either 'gridpoint_index' or 'chainage' but not both.\")\n", + " \n", + "# col_elements = [str(el) for el in col_head + col_tail]\n", + "# return separator.join(col_elements)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2e6fe4e5", + "metadata": {}, + "outputs": [], + "source": [ + "# We fabricate an observation set to try the current workflow\n", + "np.random.seed(42)\n", + "\n", + "observations = pd.read_parquet('../tests/testdata/network_res1d.parquet')\n", + "observations = observations + np.random.normal(0, 10, observations.shape)\n", + "# Arbitrarily selecting 2 columns of WaterLevel that will be used as observations\n", + "relevant_columns = [col for col in observations.columns if \"WaterLevel\" in col][8:10]\n", + "observations = observations.loc[:, relevant_columns].rename(columns=lambda x: \"sensor_\" + x.split(\":\")[1])\n", + "observations = observations.resample(\"1min\").mean()" + ] + }, + { + "cell_type": "markdown", + "id": "c2cc9f94", + "metadata": {}, + "source": [ + "## Current workflow" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c88c8a87", + "metadata": {}, + "outputs": [], + "source": [ + "# - Loading model_results\n", + "nt = m1d.open('../tests/testdata/network.res1d')\n", + "\n", + "# - Loading observations (in this cases, they are loaded from the cell above)\n", + "# observations = pd.read_csv(...)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "568f6f18", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nbiasrmseurmsemaeccsir2
observation
sensor_91100.7437789.1679659.1377447.7013890.1818370.0472570.008068
sensor_101100.5358629.3369349.3215447.8073910.0170570.048156-0.003818
\n", + "
" + ], + "text/plain": [ + " n bias rmse urmse mae cc si \\\n", + "observation \n", + "sensor_9 110 0.743778 9.167965 9.137744 7.701389 0.181837 0.047257 \n", + "sensor_10 110 0.535862 9.336934 9.321544 7.807391 0.017057 0.048156 \n", + "\n", + " r2 \n", + "observation \n", + "sensor_9 0.008068 \n", + "sensor_10 -0.003818 " + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "obs_9 = ms.PointObservation(observations, item=\"sensor_9\")\n", + "obs_10 = ms.PointObservation(observations, item=\"sensor_10\")\n", + "\n", + "id = \"WaterLevel:7\"\n", + "modres = ms.PointModelResult(nt.to_dataframe(), item=id)\n", + "\n", + "comparer_1 = ms.match(obs_9, modres)\n", + "comparer_2 = ms.match(obs_10, modres)\n", + "# comparer_1 = ms.match(observations, nt.to_dataframe(), obs_item=\"sensor_9\", mod_item=id, gtype=\"point\")\n", + "# comparer_2 = ms.match(observations, nt.to_dataframe(), obs_item=\"sensor_10\", mod_item=id, gtype=\"point\")\n", + "\n", + "ccol = ms.ComparerCollection([comparer_1, comparer_2])\n", + "ccol.skill()" + ] + }, + { + "cell_type": "markdown", + "id": "35f13324", + "metadata": {}, + "source": [ + "The challenge is the 1d matching (?)\n", + "\n", + "- [Design 1](https://github.com/DHI/modelskill/pull/536) assumes the user knows the sensor location in `mikeio1d` _coordinates_ (reach, chainage, node, catchment).\n", + "- [Design 2](https://github.com/DHI/modelskill/pull/536) suggests a more general approach where we would need to define a __shared__ coordinate system that represents a network architecture. We would need a plugin for each potential model data source (`mikeio1d`, `EPANET`, surrogates)" + ] + }, + { + "cell_type": "markdown", + "id": "8730b218", + "metadata": {}, + "source": [ + "### Design 1" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "493b9c9d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "typing.Union[str, pathlib._local.Path, pandas.core.frame.DataFrame, pandas.core.series.Series, mikeio.dfs._dfs0.Dfs0, mikeio.dataset._dataset.Dataset, mikeio.dataset._dataarray.DataArray, xarray.core.dataset.Dataset, xarray.core.dataarray.DataArray, mikeio1d.res1d.Res1D]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ms.model.point.PointType" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "7607223b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nbiasrmseurmsemaeccsir2
observation
sensor_91100.7437789.1679659.1377447.7013890.1818370.0472570.008068
sensor_101100.5358629.3369349.3215447.8073910.0170570.048156-0.003818
\n", + "
" + ], + "text/plain": [ + " n bias rmse urmse mae cc si \\\n", + "observation \n", + "sensor_9 110 0.743778 9.167965 9.137744 7.701389 0.181837 0.047257 \n", + "sensor_10 110 0.535862 9.336934 9.321544 7.807391 0.017057 0.048156 \n", + "\n", + " r2 \n", + "observation \n", + "sensor_9 0.008068 \n", + "sensor_10 -0.003818 " + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "res = ms.PointModelResult(nt, item=\"WaterLevel:7\")\n", + "obs_1 = ms.obs.NetworkPointObservation(observations, item=\"sensor_9\")\n", + "obs_2 = ms.obs.NetworkPointObservation(observations, item=\"sensor_10\")\n", + "\n", + "comparer_1 = ms.match(obs_1, res)\n", + "comparer_2 = ms.match(obs_2, res)\n", + "\n", + "ccol = ms.ComparerCollection([comparer_1, comparer_2])\n", + "ccol.skill()" + ] + }, + { + "cell_type": "markdown", + "id": "27a4fcb2", + "metadata": {}, + "source": [ + "## Sandbox" + ] + }, + { + "cell_type": "markdown", + "id": "cd9bb273", + "metadata": {}, + "source": [ + "A dataframe has the number of columns equal to the number of gridpoints + nodes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46fca47b", + "metadata": {}, + "outputs": [], + "source": [ + "def get_n_quantities(nt: m1d.result_network.ResultNetwork):\n", + " i = 0\n", + " for reach in nt.reaches.values():\n", + " for n in reach.gridpoints:\n", + " i += len(n.quantities)\n", + "\n", + " for node in nt.nodes.values():\n", + " i += len(node.quantities)\n", + " \n", + " return i\n", + "\n", + "\n", + "n_quantities = get_n_quantities(nt)\n", + "\n", + "assert n_quantities == nt.to_dataframe().shape[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "590e2e50", + "metadata": {}, + "outputs": [], + "source": [ + "quantity = \"WaterLevel\"\n", + "quantity_in_nodes = quantity in nt.nodes.quantities.keys()\n", + "quantity_in_reaches = nt.reaches.quantities.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14186ce2", + "metadata": {}, + "outputs": [], + "source": [ + "# - Specify relevant quantity\n", + "# - Iterate over (mike1d)reaches and select gridpoints with such quantity, we will call them nodes\n", + "# - Check if (mike1d)nodes contain such quantity\n", + "# - Fill quantity network\n", + "# - Location in the network is specified with two" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "9531ae9e", + "metadata": {}, + "outputs": [], + "source": [ + "key_map = list(nt.nodes.keys())\n", + "\n", + "assert len(set(key_map)) == len(key_map) # checking that there are no duplicate node names\n", + "\n", + "n_nodes = len(key_map)\n", + "adjacency = [[]] * n_nodes\n", + "for reach in nt.reaches.values():\n", + " i = key_map.index(reach.start_node)\n", + " j = key_map.index(reach.end_node)\n", + " adjacency[i].append(j)\n", + "\n", + "edges_by_node = [len(ad) for ad in adjacency]\n", + "adjacency = [l for sublist in adjacency for l in sublist]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a118c674", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "4c19c1be", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'100'" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nt.reaches[\"100l1\"].start_node" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "a7528539", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118,\n", + " 118]" + ] + }, + "execution_count": 75, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adjacency\n", + "edges_by_node" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "15122fdb", + "metadata": {}, + "outputs": [ + { + "ename": "IndexError", + "evalue": "list index out of range", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mIndexError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[35]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m k = \u001b[32m3\u001b[39m\n\u001b[32m 2\u001b[39m i = \u001b[38;5;28msum\u001b[39m(edges_by_node[:k]) + edges_by_node[k]\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[43madjacency\u001b[49m\u001b[43m[\u001b[49m\u001b[43mi\u001b[49m\u001b[43m]\u001b[49m\n", + "\u001b[31mIndexError\u001b[39m: list index out of range" + ] + } + ], + "source": [ + "k = 3\n", + "i = sum(edges_by_node[:k]) + edges_by_node[k]\n", + "adjacency[i]" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "c09a7015", + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "object of type 'int' has no len()", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[29]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m [\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mn\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mfor\u001b[39;00m n \u001b[38;5;129;01min\u001b[39;00m adjacency] \n", + "\u001b[31mTypeError\u001b[39m: object of type 'int' has no len()" + ] + } + ], + "source": [ + "[len(n) for n in adjacency] " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9bdadc2a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "119" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.zeros(n_nodes)" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "0725e4be", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
WaterLevel:1WaterLevel:2WaterLevel:3WaterLevel:4WaterLevel:5WaterLevel:6WaterLevel:7WaterLevel:8WaterLevel:9WaterLevel:10...WaterLevel:46WaterLevel:55WaterLevel:58WaterLevel:116WaterLevel:117WaterLevel:118WaterLevel:115WaterLevel:119WaterLevel:120WaterLevel:Weir Outlet:119w1
1994-08-07 16:35:00.000195.052994195.821503195.8815193.604996193.615005193.625000193.675003193.764999193.774994193.804993...194.074997195.005005193.554993193.550003193.585007193.585007193.304993193.550003193.550003193.779999
1994-08-07 16:36:01.870195.052994195.821701195.8815193.604996193.615005193.625320193.675110193.765060193.775116193.804993...194.074997195.005005193.555023193.550064193.585831193.586807193.306061193.550003193.550003188.479996
1994-08-07 16:37:07.560195.052994195.821640195.8815193.604996193.615005193.625671193.675369193.765106193.775513193.804993...194.074997195.005005193.555084193.550110193.586426193.588196193.307144193.550034193.550003188.479996
1994-08-07 16:38:55.828195.052994195.821503195.8815193.604996193.615005193.626236193.675751193.765228193.776077193.804993...194.074997195.005005193.555191193.550156193.586960193.589706193.308884193.550079193.550003188.479996
1994-08-07 16:39:55.828195.052994195.821503195.8815193.604996193.615005193.626556193.675949193.765335193.776352193.804993...194.074997195.005005193.555267193.550171193.587112193.590317193.309860193.550095193.550003188.479996
..................................................................
1994-08-07 18:30:07.967195.119919195.822769195.8815193.884308193.931808193.961746193.977524193.999054194.010910194.023590...194.087036195.025726193.832489193.830322193.755844193.832626193.755829193.800369193.550003188.479996
1994-08-07 18:31:07.967195.118607195.822769195.8815193.879333193.926086193.955582193.971191193.992905194.004776194.017578...194.086807195.025391193.828842193.826797193.756500193.828964193.756470193.798798193.550003188.479996
1994-08-07 18:32:07.967195.117310195.822769195.8815193.874542193.920532193.949615193.965073193.986984193.998856194.011795...194.086609195.025070193.825348193.823456193.757156193.825485193.757172193.797256193.550003188.479996
1994-08-07 18:33:07.967195.115753195.822769195.8815193.869873193.915131193.943802193.959091193.981171193.993011194.006042...194.086411195.024796193.822006193.820160193.757736193.822144193.757660193.795715193.550003188.479996
1994-08-07 18:35:00.000195.112534195.822769195.8815193.861450193.905396193.933258193.948181193.970627193.982437193.995468...194.086029195.024307193.816025193.814346193.758698193.816177193.758667193.792877193.550003188.479996
\n", + "

110 rows × 119 columns

\n", + "
" + ], + "text/plain": [ + " WaterLevel:1 WaterLevel:2 WaterLevel:3 \\\n", + "1994-08-07 16:35:00.000 195.052994 195.821503 195.8815 \n", + "1994-08-07 16:36:01.870 195.052994 195.821701 195.8815 \n", + "1994-08-07 16:37:07.560 195.052994 195.821640 195.8815 \n", + "1994-08-07 16:38:55.828 195.052994 195.821503 195.8815 \n", + "1994-08-07 16:39:55.828 195.052994 195.821503 195.8815 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 195.119919 195.822769 195.8815 \n", + "1994-08-07 18:31:07.967 195.118607 195.822769 195.8815 \n", + "1994-08-07 18:32:07.967 195.117310 195.822769 195.8815 \n", + "1994-08-07 18:33:07.967 195.115753 195.822769 195.8815 \n", + "1994-08-07 18:35:00.000 195.112534 195.822769 195.8815 \n", + "\n", + " WaterLevel:4 WaterLevel:5 WaterLevel:6 \\\n", + "1994-08-07 16:35:00.000 193.604996 193.615005 193.625000 \n", + "1994-08-07 16:36:01.870 193.604996 193.615005 193.625320 \n", + "1994-08-07 16:37:07.560 193.604996 193.615005 193.625671 \n", + "1994-08-07 16:38:55.828 193.604996 193.615005 193.626236 \n", + "1994-08-07 16:39:55.828 193.604996 193.615005 193.626556 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 193.884308 193.931808 193.961746 \n", + "1994-08-07 18:31:07.967 193.879333 193.926086 193.955582 \n", + "1994-08-07 18:32:07.967 193.874542 193.920532 193.949615 \n", + "1994-08-07 18:33:07.967 193.869873 193.915131 193.943802 \n", + "1994-08-07 18:35:00.000 193.861450 193.905396 193.933258 \n", + "\n", + " WaterLevel:7 WaterLevel:8 WaterLevel:9 \\\n", + "1994-08-07 16:35:00.000 193.675003 193.764999 193.774994 \n", + "1994-08-07 16:36:01.870 193.675110 193.765060 193.775116 \n", + "1994-08-07 16:37:07.560 193.675369 193.765106 193.775513 \n", + "1994-08-07 16:38:55.828 193.675751 193.765228 193.776077 \n", + "1994-08-07 16:39:55.828 193.675949 193.765335 193.776352 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 193.977524 193.999054 194.010910 \n", + "1994-08-07 18:31:07.967 193.971191 193.992905 194.004776 \n", + "1994-08-07 18:32:07.967 193.965073 193.986984 193.998856 \n", + "1994-08-07 18:33:07.967 193.959091 193.981171 193.993011 \n", + "1994-08-07 18:35:00.000 193.948181 193.970627 193.982437 \n", + "\n", + " WaterLevel:10 ... WaterLevel:46 WaterLevel:55 \\\n", + "1994-08-07 16:35:00.000 193.804993 ... 194.074997 195.005005 \n", + "1994-08-07 16:36:01.870 193.804993 ... 194.074997 195.005005 \n", + "1994-08-07 16:37:07.560 193.804993 ... 194.074997 195.005005 \n", + "1994-08-07 16:38:55.828 193.804993 ... 194.074997 195.005005 \n", + "1994-08-07 16:39:55.828 193.804993 ... 194.074997 195.005005 \n", + "... ... ... ... ... \n", + "1994-08-07 18:30:07.967 194.023590 ... 194.087036 195.025726 \n", + "1994-08-07 18:31:07.967 194.017578 ... 194.086807 195.025391 \n", + "1994-08-07 18:32:07.967 194.011795 ... 194.086609 195.025070 \n", + "1994-08-07 18:33:07.967 194.006042 ... 194.086411 195.024796 \n", + "1994-08-07 18:35:00.000 193.995468 ... 194.086029 195.024307 \n", + "\n", + " WaterLevel:58 WaterLevel:116 WaterLevel:117 \\\n", + "1994-08-07 16:35:00.000 193.554993 193.550003 193.585007 \n", + "1994-08-07 16:36:01.870 193.555023 193.550064 193.585831 \n", + "1994-08-07 16:37:07.560 193.555084 193.550110 193.586426 \n", + "1994-08-07 16:38:55.828 193.555191 193.550156 193.586960 \n", + "1994-08-07 16:39:55.828 193.555267 193.550171 193.587112 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 193.832489 193.830322 193.755844 \n", + "1994-08-07 18:31:07.967 193.828842 193.826797 193.756500 \n", + "1994-08-07 18:32:07.967 193.825348 193.823456 193.757156 \n", + "1994-08-07 18:33:07.967 193.822006 193.820160 193.757736 \n", + "1994-08-07 18:35:00.000 193.816025 193.814346 193.758698 \n", + "\n", + " WaterLevel:118 WaterLevel:115 WaterLevel:119 \\\n", + "1994-08-07 16:35:00.000 193.585007 193.304993 193.550003 \n", + "1994-08-07 16:36:01.870 193.586807 193.306061 193.550003 \n", + "1994-08-07 16:37:07.560 193.588196 193.307144 193.550034 \n", + "1994-08-07 16:38:55.828 193.589706 193.308884 193.550079 \n", + "1994-08-07 16:39:55.828 193.590317 193.309860 193.550095 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 193.832626 193.755829 193.800369 \n", + "1994-08-07 18:31:07.967 193.828964 193.756470 193.798798 \n", + "1994-08-07 18:32:07.967 193.825485 193.757172 193.797256 \n", + "1994-08-07 18:33:07.967 193.822144 193.757660 193.795715 \n", + "1994-08-07 18:35:00.000 193.816177 193.758667 193.792877 \n", + "\n", + " WaterLevel:120 WaterLevel:Weir Outlet:119w1 \n", + "1994-08-07 16:35:00.000 193.550003 193.779999 \n", + "1994-08-07 16:36:01.870 193.550003 188.479996 \n", + "1994-08-07 16:37:07.560 193.550003 188.479996 \n", + "1994-08-07 16:38:55.828 193.550003 188.479996 \n", + "1994-08-07 16:39:55.828 193.550003 188.479996 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 193.550003 188.479996 \n", + "1994-08-07 18:31:07.967 193.550003 188.479996 \n", + "1994-08-07 18:32:07.967 193.550003 188.479996 \n", + "1994-08-07 18:33:07.967 193.550003 188.479996 \n", + "1994-08-07 18:35:00.000 193.550003 188.479996 \n", + "\n", + "[110 rows x 119 columns]" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "quantity = \"WaterLevel\"\n", + "\n", + "getattr(nt.nodes, quantity).to_dataframe()" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "75511e21", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<Reach: 100l1>\n", + " \n", + "
Attributes (9)
Quantities (2)
Derived Quantities (6)
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nt.reaches[\"100l1\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d261b2db", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
WaterLevel:100l1:0WaterLevel:100l1:47.6827WaterLevel:101l1:0WaterLevel:101l1:66.4361WaterLevel:102l1:0WaterLevel:102l1:10.9366WaterLevel:103l1:0WaterLevel:103l1:26.0653WaterLevel:104l1:0WaterLevel:104l1:34.4131...WaterLevel:98l1:0WaterLevel:98l1:16.0098WaterLevel:99l1:0WaterLevel:99l1:44.5016WaterLevel:9l1:0WaterLevel:9l1:10WaterLevel:Weir:119w1:0WaterLevel:Weir:119w1:1WaterLevel:Pump:115p1:0WaterLevel:Pump:115p1:82.4281
1994-08-07 16:35:00.000195.441498194.661499195.931503195.441498193.550003193.550003195.801498195.701508197.072006196.962006...194.581497194.511505194.661499194.581497193.774994193.764999193.550003188.479996193.304993195.005005
1994-08-07 16:36:01.870195.441498194.661621195.931503195.441605193.550140193.550064195.801498195.703171197.072006196.962051...194.581497194.511841194.661575194.581497193.775070193.765060193.550003188.479996193.306061195.005005
1994-08-07 16:37:07.560195.441498194.661728195.931503195.441620193.550232193.550156195.801498195.703400197.072006196.962082...194.581497194.511795194.661667194.581497193.775391193.765106193.550034188.479996193.307144195.005005
1994-08-07 16:38:55.828195.441498194.661804195.931503195.441605193.550369193.550308195.801498195.703690197.072006196.962112...194.581497194.511581194.661865194.581497193.775894193.765228193.550079188.479996193.308884195.005005
1994-08-07 16:39:55.828195.441498194.661972195.931503195.441605193.550430193.550369195.801498195.703827197.072006196.962128...194.581497194.511505194.661911194.581497193.776154193.765335193.550095188.479996193.309860195.005005
..................................................................
1994-08-07 18:30:07.967195.455109194.689072195.931946195.470230193.850647193.850388195.801498195.787277197.072006196.967056...194.601105194.533127194.685715194.607559194.000839193.999054193.800369188.479996193.755829195.025726
1994-08-07 18:31:07.967195.455063194.688934195.931915195.470108193.846222193.845978195.801498195.785614197.072006196.967041...194.601013194.532974194.685608194.607407193.994766193.992905193.798798188.479996193.756470195.025391
1994-08-07 18:32:07.967195.455002194.688812195.931885195.469986193.841980193.841751195.801498195.783936197.072006196.967026...194.600922194.532822194.685516194.607254193.988892193.986984193.797256188.479996193.757172195.025070
1994-08-07 18:33:07.967195.453049194.688354195.931870195.467972193.837784193.837585195.801498195.782394197.072006196.966660...194.600815194.532684194.685074194.607101193.983109193.981171193.795715188.479996193.757660195.024796
1994-08-07 18:35:00.000195.450409194.686172195.931824195.462082193.830017193.829880195.801498195.779617197.072006196.965775...194.600128194.532333194.682861194.606323193.972641193.970627193.792877188.479996193.758667195.024307
\n", + "

110 rows × 247 columns

\n", + "
" + ], + "text/plain": [ + " WaterLevel:100l1:0 WaterLevel:100l1:47.6827 \\\n", + "1994-08-07 16:35:00.000 195.441498 194.661499 \n", + "1994-08-07 16:36:01.870 195.441498 194.661621 \n", + "1994-08-07 16:37:07.560 195.441498 194.661728 \n", + "1994-08-07 16:38:55.828 195.441498 194.661804 \n", + "1994-08-07 16:39:55.828 195.441498 194.661972 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 195.455109 194.689072 \n", + "1994-08-07 18:31:07.967 195.455063 194.688934 \n", + "1994-08-07 18:32:07.967 195.455002 194.688812 \n", + "1994-08-07 18:33:07.967 195.453049 194.688354 \n", + "1994-08-07 18:35:00.000 195.450409 194.686172 \n", + "\n", + " WaterLevel:101l1:0 WaterLevel:101l1:66.4361 \\\n", + "1994-08-07 16:35:00.000 195.931503 195.441498 \n", + "1994-08-07 16:36:01.870 195.931503 195.441605 \n", + "1994-08-07 16:37:07.560 195.931503 195.441620 \n", + "1994-08-07 16:38:55.828 195.931503 195.441605 \n", + "1994-08-07 16:39:55.828 195.931503 195.441605 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 195.931946 195.470230 \n", + "1994-08-07 18:31:07.967 195.931915 195.470108 \n", + "1994-08-07 18:32:07.967 195.931885 195.469986 \n", + "1994-08-07 18:33:07.967 195.931870 195.467972 \n", + "1994-08-07 18:35:00.000 195.931824 195.462082 \n", + "\n", + " WaterLevel:102l1:0 WaterLevel:102l1:10.9366 \\\n", + "1994-08-07 16:35:00.000 193.550003 193.550003 \n", + "1994-08-07 16:36:01.870 193.550140 193.550064 \n", + "1994-08-07 16:37:07.560 193.550232 193.550156 \n", + "1994-08-07 16:38:55.828 193.550369 193.550308 \n", + "1994-08-07 16:39:55.828 193.550430 193.550369 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 193.850647 193.850388 \n", + "1994-08-07 18:31:07.967 193.846222 193.845978 \n", + "1994-08-07 18:32:07.967 193.841980 193.841751 \n", + "1994-08-07 18:33:07.967 193.837784 193.837585 \n", + "1994-08-07 18:35:00.000 193.830017 193.829880 \n", + "\n", + " WaterLevel:103l1:0 WaterLevel:103l1:26.0653 \\\n", + "1994-08-07 16:35:00.000 195.801498 195.701508 \n", + "1994-08-07 16:36:01.870 195.801498 195.703171 \n", + "1994-08-07 16:37:07.560 195.801498 195.703400 \n", + "1994-08-07 16:38:55.828 195.801498 195.703690 \n", + "1994-08-07 16:39:55.828 195.801498 195.703827 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 195.801498 195.787277 \n", + "1994-08-07 18:31:07.967 195.801498 195.785614 \n", + "1994-08-07 18:32:07.967 195.801498 195.783936 \n", + "1994-08-07 18:33:07.967 195.801498 195.782394 \n", + "1994-08-07 18:35:00.000 195.801498 195.779617 \n", + "\n", + " WaterLevel:104l1:0 WaterLevel:104l1:34.4131 ... \\\n", + "1994-08-07 16:35:00.000 197.072006 196.962006 ... \n", + "1994-08-07 16:36:01.870 197.072006 196.962051 ... \n", + "1994-08-07 16:37:07.560 197.072006 196.962082 ... \n", + "1994-08-07 16:38:55.828 197.072006 196.962112 ... \n", + "1994-08-07 16:39:55.828 197.072006 196.962128 ... \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 197.072006 196.967056 ... \n", + "1994-08-07 18:31:07.967 197.072006 196.967041 ... \n", + "1994-08-07 18:32:07.967 197.072006 196.967026 ... \n", + "1994-08-07 18:33:07.967 197.072006 196.966660 ... \n", + "1994-08-07 18:35:00.000 197.072006 196.965775 ... \n", + "\n", + " WaterLevel:98l1:0 WaterLevel:98l1:16.0098 \\\n", + "1994-08-07 16:35:00.000 194.581497 194.511505 \n", + "1994-08-07 16:36:01.870 194.581497 194.511841 \n", + "1994-08-07 16:37:07.560 194.581497 194.511795 \n", + "1994-08-07 16:38:55.828 194.581497 194.511581 \n", + "1994-08-07 16:39:55.828 194.581497 194.511505 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 194.601105 194.533127 \n", + "1994-08-07 18:31:07.967 194.601013 194.532974 \n", + "1994-08-07 18:32:07.967 194.600922 194.532822 \n", + "1994-08-07 18:33:07.967 194.600815 194.532684 \n", + "1994-08-07 18:35:00.000 194.600128 194.532333 \n", + "\n", + " WaterLevel:99l1:0 WaterLevel:99l1:44.5016 \\\n", + "1994-08-07 16:35:00.000 194.661499 194.581497 \n", + "1994-08-07 16:36:01.870 194.661575 194.581497 \n", + "1994-08-07 16:37:07.560 194.661667 194.581497 \n", + "1994-08-07 16:38:55.828 194.661865 194.581497 \n", + "1994-08-07 16:39:55.828 194.661911 194.581497 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 194.685715 194.607559 \n", + "1994-08-07 18:31:07.967 194.685608 194.607407 \n", + "1994-08-07 18:32:07.967 194.685516 194.607254 \n", + "1994-08-07 18:33:07.967 194.685074 194.607101 \n", + "1994-08-07 18:35:00.000 194.682861 194.606323 \n", + "\n", + " WaterLevel:9l1:0 WaterLevel:9l1:10 \\\n", + "1994-08-07 16:35:00.000 193.774994 193.764999 \n", + "1994-08-07 16:36:01.870 193.775070 193.765060 \n", + "1994-08-07 16:37:07.560 193.775391 193.765106 \n", + "1994-08-07 16:38:55.828 193.775894 193.765228 \n", + "1994-08-07 16:39:55.828 193.776154 193.765335 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 194.000839 193.999054 \n", + "1994-08-07 18:31:07.967 193.994766 193.992905 \n", + "1994-08-07 18:32:07.967 193.988892 193.986984 \n", + "1994-08-07 18:33:07.967 193.983109 193.981171 \n", + "1994-08-07 18:35:00.000 193.972641 193.970627 \n", + "\n", + " WaterLevel:Weir:119w1:0 WaterLevel:Weir:119w1:1 \\\n", + "1994-08-07 16:35:00.000 193.550003 188.479996 \n", + "1994-08-07 16:36:01.870 193.550003 188.479996 \n", + "1994-08-07 16:37:07.560 193.550034 188.479996 \n", + "1994-08-07 16:38:55.828 193.550079 188.479996 \n", + "1994-08-07 16:39:55.828 193.550095 188.479996 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 193.800369 188.479996 \n", + "1994-08-07 18:31:07.967 193.798798 188.479996 \n", + "1994-08-07 18:32:07.967 193.797256 188.479996 \n", + "1994-08-07 18:33:07.967 193.795715 188.479996 \n", + "1994-08-07 18:35:00.000 193.792877 188.479996 \n", + "\n", + " WaterLevel:Pump:115p1:0 \\\n", + "1994-08-07 16:35:00.000 193.304993 \n", + "1994-08-07 16:36:01.870 193.306061 \n", + "1994-08-07 16:37:07.560 193.307144 \n", + "1994-08-07 16:38:55.828 193.308884 \n", + "1994-08-07 16:39:55.828 193.309860 \n", + "... ... \n", + "1994-08-07 18:30:07.967 193.755829 \n", + "1994-08-07 18:31:07.967 193.756470 \n", + "1994-08-07 18:32:07.967 193.757172 \n", + "1994-08-07 18:33:07.967 193.757660 \n", + "1994-08-07 18:35:00.000 193.758667 \n", + "\n", + " WaterLevel:Pump:115p1:82.4281 \n", + "1994-08-07 16:35:00.000 195.005005 \n", + "1994-08-07 16:36:01.870 195.005005 \n", + "1994-08-07 16:37:07.560 195.005005 \n", + "1994-08-07 16:38:55.828 195.005005 \n", + "1994-08-07 16:39:55.828 195.005005 \n", + "... ... \n", + "1994-08-07 18:30:07.967 195.025726 \n", + "1994-08-07 18:31:07.967 195.025391 \n", + "1994-08-07 18:32:07.967 195.025070 \n", + "1994-08-07 18:33:07.967 195.024796 \n", + "1994-08-07 18:35:00.000 195.024307 \n", + "\n", + "[110 rows x 247 columns]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nt.reaches.quantities[\"WaterLevel\"].to_dataframe()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "c2b70041", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
WaterLevel:1WaterLevel:2WaterLevel:3WaterLevel:4WaterLevel:5WaterLevel:6WaterLevel:7WaterLevel:8WaterLevel:9WaterLevel:10...WaterLevel:46WaterLevel:55WaterLevel:58WaterLevel:116WaterLevel:117WaterLevel:118WaterLevel:115WaterLevel:119WaterLevel:120WaterLevel:Weir Outlet:119w1
1994-08-07 16:35:00.000195.052994195.821503195.8815193.604996193.615005193.625000193.675003193.764999193.774994193.804993...194.074997195.005005193.554993193.550003193.585007193.585007193.304993193.550003193.550003193.779999
1994-08-07 16:36:01.870195.052994195.821701195.8815193.604996193.615005193.625320193.675110193.765060193.775116193.804993...194.074997195.005005193.555023193.550064193.585831193.586807193.306061193.550003193.550003188.479996
1994-08-07 16:37:07.560195.052994195.821640195.8815193.604996193.615005193.625671193.675369193.765106193.775513193.804993...194.074997195.005005193.555084193.550110193.586426193.588196193.307144193.550034193.550003188.479996
1994-08-07 16:38:55.828195.052994195.821503195.8815193.604996193.615005193.626236193.675751193.765228193.776077193.804993...194.074997195.005005193.555191193.550156193.586960193.589706193.308884193.550079193.550003188.479996
1994-08-07 16:39:55.828195.052994195.821503195.8815193.604996193.615005193.626556193.675949193.765335193.776352193.804993...194.074997195.005005193.555267193.550171193.587112193.590317193.309860193.550095193.550003188.479996
..................................................................
1994-08-07 18:30:07.967195.119919195.822769195.8815193.884308193.931808193.961746193.977524193.999054194.010910194.023590...194.087036195.025726193.832489193.830322193.755844193.832626193.755829193.800369193.550003188.479996
1994-08-07 18:31:07.967195.118607195.822769195.8815193.879333193.926086193.955582193.971191193.992905194.004776194.017578...194.086807195.025391193.828842193.826797193.756500193.828964193.756470193.798798193.550003188.479996
1994-08-07 18:32:07.967195.117310195.822769195.8815193.874542193.920532193.949615193.965073193.986984193.998856194.011795...194.086609195.025070193.825348193.823456193.757156193.825485193.757172193.797256193.550003188.479996
1994-08-07 18:33:07.967195.115753195.822769195.8815193.869873193.915131193.943802193.959091193.981171193.993011194.006042...194.086411195.024796193.822006193.820160193.757736193.822144193.757660193.795715193.550003188.479996
1994-08-07 18:35:00.000195.112534195.822769195.8815193.861450193.905396193.933258193.948181193.970627193.982437193.995468...194.086029195.024307193.816025193.814346193.758698193.816177193.758667193.792877193.550003188.479996
\n", + "

110 rows × 119 columns

\n", + "
" + ], + "text/plain": [ + " WaterLevel:1 WaterLevel:2 WaterLevel:3 \\\n", + "1994-08-07 16:35:00.000 195.052994 195.821503 195.8815 \n", + "1994-08-07 16:36:01.870 195.052994 195.821701 195.8815 \n", + "1994-08-07 16:37:07.560 195.052994 195.821640 195.8815 \n", + "1994-08-07 16:38:55.828 195.052994 195.821503 195.8815 \n", + "1994-08-07 16:39:55.828 195.052994 195.821503 195.8815 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 195.119919 195.822769 195.8815 \n", + "1994-08-07 18:31:07.967 195.118607 195.822769 195.8815 \n", + "1994-08-07 18:32:07.967 195.117310 195.822769 195.8815 \n", + "1994-08-07 18:33:07.967 195.115753 195.822769 195.8815 \n", + "1994-08-07 18:35:00.000 195.112534 195.822769 195.8815 \n", + "\n", + " WaterLevel:4 WaterLevel:5 WaterLevel:6 \\\n", + "1994-08-07 16:35:00.000 193.604996 193.615005 193.625000 \n", + "1994-08-07 16:36:01.870 193.604996 193.615005 193.625320 \n", + "1994-08-07 16:37:07.560 193.604996 193.615005 193.625671 \n", + "1994-08-07 16:38:55.828 193.604996 193.615005 193.626236 \n", + "1994-08-07 16:39:55.828 193.604996 193.615005 193.626556 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 193.884308 193.931808 193.961746 \n", + "1994-08-07 18:31:07.967 193.879333 193.926086 193.955582 \n", + "1994-08-07 18:32:07.967 193.874542 193.920532 193.949615 \n", + "1994-08-07 18:33:07.967 193.869873 193.915131 193.943802 \n", + "1994-08-07 18:35:00.000 193.861450 193.905396 193.933258 \n", + "\n", + " WaterLevel:7 WaterLevel:8 WaterLevel:9 \\\n", + "1994-08-07 16:35:00.000 193.675003 193.764999 193.774994 \n", + "1994-08-07 16:36:01.870 193.675110 193.765060 193.775116 \n", + "1994-08-07 16:37:07.560 193.675369 193.765106 193.775513 \n", + "1994-08-07 16:38:55.828 193.675751 193.765228 193.776077 \n", + "1994-08-07 16:39:55.828 193.675949 193.765335 193.776352 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 193.977524 193.999054 194.010910 \n", + "1994-08-07 18:31:07.967 193.971191 193.992905 194.004776 \n", + "1994-08-07 18:32:07.967 193.965073 193.986984 193.998856 \n", + "1994-08-07 18:33:07.967 193.959091 193.981171 193.993011 \n", + "1994-08-07 18:35:00.000 193.948181 193.970627 193.982437 \n", + "\n", + " WaterLevel:10 ... WaterLevel:46 WaterLevel:55 \\\n", + "1994-08-07 16:35:00.000 193.804993 ... 194.074997 195.005005 \n", + "1994-08-07 16:36:01.870 193.804993 ... 194.074997 195.005005 \n", + "1994-08-07 16:37:07.560 193.804993 ... 194.074997 195.005005 \n", + "1994-08-07 16:38:55.828 193.804993 ... 194.074997 195.005005 \n", + "1994-08-07 16:39:55.828 193.804993 ... 194.074997 195.005005 \n", + "... ... ... ... ... \n", + "1994-08-07 18:30:07.967 194.023590 ... 194.087036 195.025726 \n", + "1994-08-07 18:31:07.967 194.017578 ... 194.086807 195.025391 \n", + "1994-08-07 18:32:07.967 194.011795 ... 194.086609 195.025070 \n", + "1994-08-07 18:33:07.967 194.006042 ... 194.086411 195.024796 \n", + "1994-08-07 18:35:00.000 193.995468 ... 194.086029 195.024307 \n", + "\n", + " WaterLevel:58 WaterLevel:116 WaterLevel:117 \\\n", + "1994-08-07 16:35:00.000 193.554993 193.550003 193.585007 \n", + "1994-08-07 16:36:01.870 193.555023 193.550064 193.585831 \n", + "1994-08-07 16:37:07.560 193.555084 193.550110 193.586426 \n", + "1994-08-07 16:38:55.828 193.555191 193.550156 193.586960 \n", + "1994-08-07 16:39:55.828 193.555267 193.550171 193.587112 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 193.832489 193.830322 193.755844 \n", + "1994-08-07 18:31:07.967 193.828842 193.826797 193.756500 \n", + "1994-08-07 18:32:07.967 193.825348 193.823456 193.757156 \n", + "1994-08-07 18:33:07.967 193.822006 193.820160 193.757736 \n", + "1994-08-07 18:35:00.000 193.816025 193.814346 193.758698 \n", + "\n", + " WaterLevel:118 WaterLevel:115 WaterLevel:119 \\\n", + "1994-08-07 16:35:00.000 193.585007 193.304993 193.550003 \n", + "1994-08-07 16:36:01.870 193.586807 193.306061 193.550003 \n", + "1994-08-07 16:37:07.560 193.588196 193.307144 193.550034 \n", + "1994-08-07 16:38:55.828 193.589706 193.308884 193.550079 \n", + "1994-08-07 16:39:55.828 193.590317 193.309860 193.550095 \n", + "... ... ... ... \n", + "1994-08-07 18:30:07.967 193.832626 193.755829 193.800369 \n", + "1994-08-07 18:31:07.967 193.828964 193.756470 193.798798 \n", + "1994-08-07 18:32:07.967 193.825485 193.757172 193.797256 \n", + "1994-08-07 18:33:07.967 193.822144 193.757660 193.795715 \n", + "1994-08-07 18:35:00.000 193.816177 193.758667 193.792877 \n", + "\n", + " WaterLevel:120 WaterLevel:Weir Outlet:119w1 \n", + "1994-08-07 16:35:00.000 193.550003 193.779999 \n", + "1994-08-07 16:36:01.870 193.550003 188.479996 \n", + "1994-08-07 16:37:07.560 193.550003 188.479996 \n", + "1994-08-07 16:38:55.828 193.550003 188.479996 \n", + "1994-08-07 16:39:55.828 193.550003 188.479996 \n", + "... ... ... \n", + "1994-08-07 18:30:07.967 193.550003 188.479996 \n", + "1994-08-07 18:31:07.967 193.550003 188.479996 \n", + "1994-08-07 18:32:07.967 193.550003 188.479996 \n", + "1994-08-07 18:33:07.967 193.550003 188.479996 \n", + "1994-08-07 18:35:00.000 193.550003 188.479996 \n", + "\n", + "[110 rows x 119 columns]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nt.nodes.quantities[\"WaterLevel\"].to_dataframe()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "92b249fe", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<ResultGridPoint>\n", + " \n", + "
Attributes (5)
  • reach_name: 105l1
  • chainage: 0.0
  • xcoord: -687516.5991821289
  • ycoord: -1056363.7993774414
  • bottom_level: 197.35000610351562
Quantities (1)
  • Water level (m)
Derived Quantities (0)
    " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nt.reaches[\"105l1\"][\"0.000\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "0a4ca2bf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[, , ]" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nt.reaches[\"105l1\"].gridpoints" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "138e3ef4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['WaterLevel']" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nt.reaches[\"102l1\"][\"10.937\"].quantities" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8abc73b4", + "metadata": {}, + "outputs": [], + "source": [ + "temperature = ms.PointModelResult(datapath, item=\"Temperature\", name=\"Temp\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51fb4d18", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "94025330", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    TemperatureWater Level
    2015-01-01 01:00:003.140.1400
    2015-01-01 02:00:003.140.1370
    2015-01-01 03:00:003.140.1809
    2015-01-01 04:00:003.140.2030
    2015-01-01 05:00:003.140.1750
    .........
    2020-09-27 20:00:003.140.4070
    2020-09-27 21:00:003.140.3790
    2020-09-27 22:00:003.140.3650
    2020-09-27 23:00:003.140.3790
    2020-09-28 00:00:003.140.4140
    \n", + "

    50328 rows × 2 columns

    \n", + "
    " + ], + "text/plain": [ + " Temperature Water Level\n", + "2015-01-01 01:00:00 3.14 0.1400\n", + "2015-01-01 02:00:00 3.14 0.1370\n", + "2015-01-01 03:00:00 3.14 0.1809\n", + "2015-01-01 04:00:00 3.14 0.2030\n", + "2015-01-01 05:00:00 3.14 0.1750\n", + "... ... ...\n", + "2020-09-27 20:00:00 3.14 0.4070\n", + "2020-09-27 21:00:00 3.14 0.3790\n", + "2020-09-27 22:00:00 3.14 0.3650\n", + "2020-09-27 23:00:00 3.14 0.3790\n", + "2020-09-28 00:00:00 3.14 0.4140\n", + "\n", + "[50328 rows x 2 columns]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ds.to_dataframe()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "modelskill", + "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.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/modelskill/matching.py b/src/modelskill/matching.py index f8b15aa4d..7df1235fd 100644 --- a/src/modelskill/matching.py +++ b/src/modelskill/matching.py @@ -28,7 +28,13 @@ from .model.dummy import DummyModelResult from .model.grid import GridModelResult from .model.track import TrackModelResult -from .obs import Observation, PointObservation, TrackObservation, observation +from .obs import ( + Observation, + PointObservation, + TrackObservation, + NetworkPointObservation, + observation, +) from .timeseries import TimeSeries from .types import Period @@ -400,6 +406,8 @@ def _match_space_time( ) case PointModelResult() as pmr, PointObservation(): aligned = pmr.align(observation, max_gap=max_model_gap) + case PointModelResult() as pmr, NetworkPointObservation(): + aligned = pmr.align(observation, max_gap=max_model_gap) case _: raise TypeError( f"Matching not implemented for model type {type(mr)} and observation type {type(observation)}" @@ -430,8 +438,8 @@ def _parse_single_obs( obs: ObsInputType, obs_item: Optional[int | str], gtype: Optional[GeometryTypes], -) -> PointObservation | TrackObservation: - if isinstance(obs, (PointObservation, TrackObservation)): +) -> PointObservation | TrackObservation | NetworkPointObservation: + if isinstance(obs, (PointObservation, TrackObservation, NetworkPointObservation)): if obs_item is not None: raise ValueError( "obs_item argument not allowed if obs is an modelskill.Observation type" diff --git a/src/modelskill/obs.py b/src/modelskill/obs.py index 4bf019ff9..407f4c27b 100644 --- a/src/modelskill/obs.py +++ b/src/modelskill/obs.py @@ -340,6 +340,32 @@ def __init__( super().__init__(data=data, weight=weight, attrs=attrs) +class NetworkPointObservation(Observation): + def __init__( + self, + data: PointType, + *, + name: Optional[str] = None, + item: Optional[str] = None, + attrs: Optional[dict] = None, + quantity: Optional[Quantity] = None, + aux_items: Optional[list[int | str]] = None, + ) -> None: + if not self._is_input_validated(data): + data = _parse_point_input( + data, + name=name, + item=item, + quantity=quantity, + aux_items=aux_items, + x=None, + y=None, + z=None, + ) + assert isinstance(data, xr.Dataset) + super().__init__(data=data, weight=1, attrs=attrs) + + def unit_display_name(name: str) -> str: """Display name diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index 426d0c9d7..93ff4bbab 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -8,6 +8,7 @@ import xarray as xr import mikeio +import mikeio1d from ..types import GeometryType, PointType from ..quantity import Quantity @@ -76,9 +77,14 @@ def _parse_point_input( stem = Path(data).stem data = xr.open_dataset(data) name = name or data.attrs.get("name") or stem + elif suffix == ".res1d": + name = name or Path(data).stem + data = mikeio1d.open(data) + elif isinstance(data, mikeio.Dfs0): data = data.read() # now mikeio.Dataset - + elif isinstance(data, mikeio1d.Res1D): + data = data.read() # now mikeio1d.Res1D # parse items if isinstance(data, (mikeio.DataArray, pd.Series, xr.DataArray)): item_name = data.name if data.name is not None else "PointModelResult" diff --git a/src/modelskill/types.py b/src/modelskill/types.py index 0ba3dcd63..77aef9a77 100644 --- a/src/modelskill/types.py +++ b/src/modelskill/types.py @@ -5,6 +5,7 @@ import pandas as pd import xarray as xr import mikeio +import mikeio1d class GeometryType(Enum): @@ -85,6 +86,7 @@ def from_string(s: str) -> "GeometryType": mikeio.DataArray, xr.Dataset, xr.DataArray, + mikeio1d.Res1D, ] TrackType = Union[str, Path, pd.DataFrame, mikeio.Dfs0, mikeio.Dataset, xr.Dataset] From 5442cf11e2280f0776be1951b42f8a94cc8db786 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 12:16:55 +0100 Subject: [PATCH 02/17] Introducing NetworkModelResult class --- src/modelskill/matching.py | 6 ++- src/modelskill/model/__init__.py | 2 + src/modelskill/model/factory.py | 12 ++++- src/modelskill/model/network.py | 84 ++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/modelskill/model/network.py diff --git a/src/modelskill/matching.py b/src/modelskill/matching.py index 7df1235fd..ae1edede2 100644 --- a/src/modelskill/matching.py +++ b/src/modelskill/matching.py @@ -28,6 +28,7 @@ from .model.dummy import DummyModelResult from .model.grid import GridModelResult from .model.track import TrackModelResult +from .model.network import NetworkModelResult from .obs import ( Observation, PointObservation, @@ -40,7 +41,7 @@ TimeDeltaTypes = Union[float, int, np.timedelta64, pd.Timedelta, timedelta] IdxOrNameTypes = Optional[Union[int, str]] -GeometryTypes = Optional[Literal["point", "track", "unstructured", "grid"]] +GeometryTypes = Optional[Literal["point", "track", "unstructured", "grid", "network"]] MRInputType = Union[ str, Path, @@ -57,6 +58,7 @@ DfsuModelResult, TrackModelResult, DummyModelResult, + NetworkModelResult, ] ObsInputType = Union[ str, @@ -460,6 +462,7 @@ def _parse_single_model( | GridModelResult | DfsuModelResult | DummyModelResult + | NetworkModelResult ): if isinstance( mod, @@ -492,6 +495,7 @@ def _parse_single_model( GridModelResult, DfsuModelResult, DummyModelResult, + NetworkModelResult, ), ) return mod diff --git a/src/modelskill/model/__init__.py b/src/modelskill/model/__init__.py index b0ba468ae..c03a8e62e 100644 --- a/src/modelskill/model/__init__.py +++ b/src/modelskill/model/__init__.py @@ -21,6 +21,7 @@ from .dfsu import DfsuModelResult from .grid import GridModelResult from .dummy import DummyModelResult +from .network import NetworkModelResult __all__ = [ "PointModelResult", @@ -29,4 +30,5 @@ "GridModelResult", "model_result", "DummyModelResult", + "NetworkModelResult", ] diff --git a/src/modelskill/model/factory.py b/src/modelskill/model/factory.py index 4ee2cb7f3..13dc95f1a 100644 --- a/src/modelskill/model/factory.py +++ b/src/modelskill/model/factory.py @@ -9,6 +9,7 @@ from .track import TrackModelResult from .dfsu import DfsuModelResult from .grid import GridModelResult +from .network import NetworkModelResult from ..types import GeometryType, DataInputType @@ -18,6 +19,7 @@ GeometryType.TRACK: TrackModelResult, GeometryType.UNSTRUCTURED: DfsuModelResult, GeometryType.GRID: GridModelResult, + GeometryType.NETWORK: NetworkModelResult, } @@ -27,7 +29,13 @@ def model_result( aux_items: Optional[list[int | str]] = None, gtype: Optional[Literal["point", "track", "unstructured", "grid"]] = None, **kwargs: Any, -) -> PointModelResult | TrackModelResult | DfsuModelResult | GridModelResult: +) -> ( + PointModelResult + | TrackModelResult + | DfsuModelResult + | GridModelResult + | NetworkModelResult +): """A factory function for creating an appropriate object based on the data input. Parameters @@ -86,6 +94,8 @@ def _guess_gtype(data: Any) -> GeometryType: return GeometryType.GRID elif file_ext == ".dfs2": return GeometryType.GRID + elif file_ext == ".res1d": + return GeometryType.NETWORK else: raise ValueError( "Could not guess gtype from file extension, please specify gtype, e.g. gtype='track'" diff --git a/src/modelskill/model/network.py b/src/modelskill/model/network.py new file mode 100644 index 000000000..5b965f424 --- /dev/null +++ b/src/modelskill/model/network.py @@ -0,0 +1,84 @@ +from __future__ import annotations +from typing import Optional, Sequence, Literal + +import pandas as pd + +from pathlib import Path +from mikeio1d import Res1D, open + +from ..quantity import Quantity +from .point import PointModelResult + + +def parse_network_location( + data: Res1D | str, + quantity: str, + *, + node: Optional[int] = None, + reach: Optional[str] = None, + chainage: Optional[str | float] = None, + gridpoint: Optional[int | Literal["start", "end"]] = None, +) -> pd.Series: + if isinstance(data, (str, Path)): + if Path(data).suffix == ".res1d": + data = open(data) + else: + raise ValueError("Invalid path to network") + + by_node = node is not None + by_reach = reach is not None + with_chainage = chainage is not None + with_index = gridpoint is not None + + if by_node and not by_reach: + location = data.nodes[str(node)] + assert ( + quantity in location.quantities + ), f"Quantity {quantity} was not found in node." + + elif by_reach and not by_node: + location = data.reaches[reach] + if with_index != with_chainage: + raise ValueError( + "Items accessed by chainage must be specified either by chainage or by index, not both" + ) + + if with_index and not with_chainage: + gridpoint = 0 if gridpoint == "start" else gridpoint + gridpoint = -1 if gridpoint == "end" else gridpoint + chainage = location.chainages[gridpoint] + + location = location[chainage] + + else: + raise ValueError("Item can only be specified either by node or by reach") + + df = location.to_dataframe() + assert df.shape[1] == 1, "Multiple columns found in df" + df.rename(columns=lambda x: quantity, inplace=True) + return df[quantity].copy() + + +class NetworkModelResult(PointModelResult): + def __init__( + self, + data: Res1D | str, + network_quantity: str, + *, + reach: Optional[float] = None, + node: Optional[float] = None, + chainage: Optional[float] = None, + gridpoint: Optional[int | Literal["start", "end"]] = None, + name: Optional[str] = None, + quantity: Optional[Quantity] = None, + aux_items: Optional[Sequence[int | str]] = None, + ) -> None: + data = parse_network_location( + data, + quantity=network_quantity, + reach=reach, + node=node, + chainage=chainage, + gridpoint=gridpoint, + ) + super().__init__(data=data, name=name, quantity=quantity, aux_items=aux_items) From 4e56858b58daf278b1bb3259aad8a7c4a33dbedc Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 13:27:19 +0100 Subject: [PATCH 03/17] Removing NetworkPointObservation --- src/modelskill/__init__.py | 6 +++++- src/modelskill/matching.py | 7 ++----- src/modelskill/obs.py | 26 -------------------------- 3 files changed, 7 insertions(+), 32 deletions(-) diff --git a/src/modelskill/__init__.py b/src/modelskill/__init__.py index 4a362ffb2..0b3ce52f2 100644 --- a/src/modelskill/__init__.py +++ b/src/modelskill/__init__.py @@ -40,7 +40,11 @@ DfsuModelResult, DummyModelResult, ) -from .obs import observation, PointObservation, TrackObservation +from .obs import ( + observation, + PointObservation, + TrackObservation, +) from .matching import from_matched, match from .configuration import from_config from .settings import options, get_option, set_option, reset_option, load_style diff --git a/src/modelskill/matching.py b/src/modelskill/matching.py index ae1edede2..5c14d0df7 100644 --- a/src/modelskill/matching.py +++ b/src/modelskill/matching.py @@ -33,7 +33,6 @@ Observation, PointObservation, TrackObservation, - NetworkPointObservation, observation, ) from .timeseries import TimeSeries @@ -408,8 +407,6 @@ def _match_space_time( ) case PointModelResult() as pmr, PointObservation(): aligned = pmr.align(observation, max_gap=max_model_gap) - case PointModelResult() as pmr, NetworkPointObservation(): - aligned = pmr.align(observation, max_gap=max_model_gap) case _: raise TypeError( f"Matching not implemented for model type {type(mr)} and observation type {type(observation)}" @@ -440,8 +437,8 @@ def _parse_single_obs( obs: ObsInputType, obs_item: Optional[int | str], gtype: Optional[GeometryTypes], -) -> PointObservation | TrackObservation | NetworkPointObservation: - if isinstance(obs, (PointObservation, TrackObservation, NetworkPointObservation)): +) -> PointObservation | TrackObservation: + if isinstance(obs, (PointObservation, TrackObservation)): if obs_item is not None: raise ValueError( "obs_item argument not allowed if obs is an modelskill.Observation type" diff --git a/src/modelskill/obs.py b/src/modelskill/obs.py index 407f4c27b..4bf019ff9 100644 --- a/src/modelskill/obs.py +++ b/src/modelskill/obs.py @@ -340,32 +340,6 @@ def __init__( super().__init__(data=data, weight=weight, attrs=attrs) -class NetworkPointObservation(Observation): - def __init__( - self, - data: PointType, - *, - name: Optional[str] = None, - item: Optional[str] = None, - attrs: Optional[dict] = None, - quantity: Optional[Quantity] = None, - aux_items: Optional[list[int | str]] = None, - ) -> None: - if not self._is_input_validated(data): - data = _parse_point_input( - data, - name=name, - item=item, - quantity=quantity, - aux_items=aux_items, - x=None, - y=None, - z=None, - ) - assert isinstance(data, xr.Dataset) - super().__init__(data=data, weight=1, attrs=attrs) - - def unit_display_name(name: str) -> str: """Display name From 1017b4884e1bc25771851b60437aac37079c7904 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 13:53:42 +0100 Subject: [PATCH 04/17] Typing hints. Rename network parsing function. --- src/modelskill/model/network.py | 62 ++++----------------------- src/modelskill/timeseries/__init__.py | 3 +- src/modelskill/timeseries/_point.py | 51 +++++++++++++++++++++- 3 files changed, 60 insertions(+), 56 deletions(-) diff --git a/src/modelskill/model/network.py b/src/modelskill/model/network.py index 5b965f424..2bd697565 100644 --- a/src/modelskill/model/network.py +++ b/src/modelskill/model/network.py @@ -1,62 +1,15 @@ from __future__ import annotations from typing import Optional, Sequence, Literal -import pandas as pd - -from pathlib import Path -from mikeio1d import Res1D, open +from mikeio1d import Res1D +from ..timeseries import _parse_network_input from ..quantity import Quantity from .point import PointModelResult -def parse_network_location( - data: Res1D | str, - quantity: str, - *, - node: Optional[int] = None, - reach: Optional[str] = None, - chainage: Optional[str | float] = None, - gridpoint: Optional[int | Literal["start", "end"]] = None, -) -> pd.Series: - if isinstance(data, (str, Path)): - if Path(data).suffix == ".res1d": - data = open(data) - else: - raise ValueError("Invalid path to network") - - by_node = node is not None - by_reach = reach is not None - with_chainage = chainage is not None - with_index = gridpoint is not None - - if by_node and not by_reach: - location = data.nodes[str(node)] - assert ( - quantity in location.quantities - ), f"Quantity {quantity} was not found in node." - - elif by_reach and not by_node: - location = data.reaches[reach] - if with_index != with_chainage: - raise ValueError( - "Items accessed by chainage must be specified either by chainage or by index, not both" - ) - - if with_index and not with_chainage: - gridpoint = 0 if gridpoint == "start" else gridpoint - gridpoint = -1 if gridpoint == "end" else gridpoint - chainage = location.chainages[gridpoint] - - location = location[chainage] - - else: - raise ValueError("Item can only be specified either by node or by reach") - - df = location.to_dataframe() - assert df.shape[1] == 1, "Multiple columns found in df" - df.rename(columns=lambda x: quantity, inplace=True) - return df[quantity].copy() +def build_quantity(network_quantity: str) -> Quantity: + assert True class NetworkModelResult(PointModelResult): @@ -65,15 +18,15 @@ def __init__( data: Res1D | str, network_quantity: str, *, - reach: Optional[float] = None, - node: Optional[float] = None, + reach: Optional[str] = None, + node: Optional[int] = None, chainage: Optional[float] = None, gridpoint: Optional[int | Literal["start", "end"]] = None, name: Optional[str] = None, quantity: Optional[Quantity] = None, aux_items: Optional[Sequence[int | str]] = None, ) -> None: - data = parse_network_location( + data = _parse_network_input( data, quantity=network_quantity, reach=reach, @@ -81,4 +34,5 @@ def __init__( chainage=chainage, gridpoint=gridpoint, ) + quantity = build_quantity(network_quantity) super().__init__(data=data, name=name, quantity=quantity, aux_items=aux_items) diff --git a/src/modelskill/timeseries/__init__.py b/src/modelskill/timeseries/__init__.py index 08fa449a4..1884b8910 100644 --- a/src/modelskill/timeseries/__init__.py +++ b/src/modelskill/timeseries/__init__.py @@ -1,9 +1,10 @@ from ._timeseries import TimeSeries -from ._point import _parse_point_input +from ._point import _parse_point_input, _parse_network_input from ._track import _parse_track_input __all__ = [ "TimeSeries", "_parse_point_input", "_parse_track_input", + "_parse_network_input", ] diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index 93ff4bbab..38d3899f4 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -2,7 +2,7 @@ from collections.abc import Hashable from dataclasses import dataclass from pathlib import Path -from typing import Sequence, get_args, List, Optional +from typing import Literal, Sequence, get_args, List, Optional import numpy as np import pandas as pd import xarray as xr @@ -183,3 +183,52 @@ def _parse_point_input( assert isinstance(ds, xr.Dataset) return ds + + +def _parse_network_input( + data: mikeio1d.Res1D | str, + quantity: str, + *, + node: Optional[int] = None, + reach: Optional[str] = None, + chainage: Optional[str | float] = None, + gridpoint: Optional[int | Literal["start", "end"]] = None, +) -> pd.Series: + if isinstance(data, (str, Path)): + if Path(data).suffix == ".res1d": + data = open(data) + else: + raise ValueError("Invalid path to network") + + by_node = node is not None + by_reach = reach is not None + with_chainage = chainage is not None + with_index = gridpoint is not None + + if by_node and not by_reach: + location = data.nodes[str(node)] + assert ( + quantity in location.quantities + ), f"Quantity {quantity} was not found in node." + + elif by_reach and not by_node: + location = data.reaches[reach] + if with_index != with_chainage: + raise ValueError( + "Items accessed by chainage must be specified either by chainage or by index, not both" + ) + + if with_index and not with_chainage: + gridpoint = 0 if gridpoint == "start" else gridpoint + gridpoint = -1 if gridpoint == "end" else gridpoint + chainage = location.chainages[gridpoint] + + location = location[chainage] + + else: + raise ValueError("Item can only be specified either by node or by reach") + + df = location.to_dataframe() + assert df.shape[1] == 1, "Multiple columns found in df" + df.rename(columns=lambda x: quantity, inplace=True) + return df[quantity].copy() From 7f276e9ee14282e3f7079be5c8858af09aedcaaf Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 14:02:58 +0100 Subject: [PATCH 05/17] correct open --- src/modelskill/timeseries/_point.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index 38d3899f4..2e6d548b4 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -196,7 +196,7 @@ def _parse_network_input( ) -> pd.Series: if isinstance(data, (str, Path)): if Path(data).suffix == ".res1d": - data = open(data) + data = mikeio1d.open(data) else: raise ValueError("Invalid path to network") From 449bf8afe744c24c0db8c5fc294484521d5df052 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 14:04:55 +0100 Subject: [PATCH 06/17] Remove network geometry type (for now) --- src/modelskill/matching.py | 2 +- src/modelskill/model/factory.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/modelskill/matching.py b/src/modelskill/matching.py index 5c14d0df7..5b5d66613 100644 --- a/src/modelskill/matching.py +++ b/src/modelskill/matching.py @@ -40,7 +40,7 @@ TimeDeltaTypes = Union[float, int, np.timedelta64, pd.Timedelta, timedelta] IdxOrNameTypes = Optional[Union[int, str]] -GeometryTypes = Optional[Literal["point", "track", "unstructured", "grid", "network"]] +GeometryTypes = Optional[Literal["point", "track", "unstructured", "grid"]] MRInputType = Union[ str, Path, diff --git a/src/modelskill/model/factory.py b/src/modelskill/model/factory.py index 13dc95f1a..26ec9ffbc 100644 --- a/src/modelskill/model/factory.py +++ b/src/modelskill/model/factory.py @@ -19,7 +19,6 @@ GeometryType.TRACK: TrackModelResult, GeometryType.UNSTRUCTURED: DfsuModelResult, GeometryType.GRID: GridModelResult, - GeometryType.NETWORK: NetworkModelResult, } @@ -94,8 +93,6 @@ def _guess_gtype(data: Any) -> GeometryType: return GeometryType.GRID elif file_ext == ".dfs2": return GeometryType.GRID - elif file_ext == ".res1d": - return GeometryType.NETWORK else: raise ValueError( "Could not guess gtype from file extension, please specify gtype, e.g. gtype='track'" From 08f648c704c64b2b3e7b6c38770a1d93fd513080 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 14:41:16 +0100 Subject: [PATCH 07/17] Passing quantity name modelskill Quantity --- src/modelskill/model/network.py | 13 +++++-------- src/modelskill/timeseries/_point.py | 21 +++++++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/modelskill/model/network.py b/src/modelskill/model/network.py index 2bd697565..f86bfed26 100644 --- a/src/modelskill/model/network.py +++ b/src/modelskill/model/network.py @@ -8,31 +8,28 @@ from .point import PointModelResult -def build_quantity(network_quantity: str) -> Quantity: - assert True - - class NetworkModelResult(PointModelResult): def __init__( self, data: Res1D | str, - network_quantity: str, + quantity: Optional[str | Quantity] = None, *, reach: Optional[str] = None, node: Optional[int] = None, chainage: Optional[float] = None, gridpoint: Optional[int | Literal["start", "end"]] = None, name: Optional[str] = None, - quantity: Optional[Quantity] = None, aux_items: Optional[Sequence[int | str]] = None, ) -> None: + if isinstance(quantity, str): + quantity = Quantity.from_mikeio_eum_name(quantity) + data = _parse_network_input( data, - quantity=network_quantity, + eum_name=quantity.name, reach=reach, node=node, chainage=chainage, gridpoint=gridpoint, ) - quantity = build_quantity(network_quantity) super().__init__(data=data, name=name, quantity=quantity, aux_items=aux_items) diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index 2e6d548b4..f531734e5 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -6,6 +6,7 @@ import numpy as np import pandas as pd import xarray as xr +import difflib import mikeio import mikeio1d @@ -187,13 +188,16 @@ def _parse_point_input( def _parse_network_input( data: mikeio1d.Res1D | str, - quantity: str, + eum_name: str, *, node: Optional[int] = None, reach: Optional[str] = None, chainage: Optional[str | float] = None, gridpoint: Optional[int | Literal["start", "end"]] = None, ) -> pd.Series: + def eum_name_to_res1d(name: str) -> str: + return name.replace(" ", "").replace("_", "") + if isinstance(data, (str, Path)): if Path(data).suffix == ".res1d": data = mikeio1d.open(data) @@ -207,9 +211,6 @@ def _parse_network_input( if by_node and not by_reach: location = data.nodes[str(node)] - assert ( - quantity in location.quantities - ), f"Quantity {quantity} was not found in node." elif by_reach and not by_node: location = data.reaches[reach] @@ -228,7 +229,11 @@ def _parse_network_input( else: raise ValueError("Item can only be specified either by node or by reach") - df = location.to_dataframe() - assert df.shape[1] == 1, "Multiple columns found in df" - df.rename(columns=lambda x: quantity, inplace=True) - return df[quantity].copy() + # After filtering by node or by reach and chainage, a location will only + # have unique quantities + colname = eum_name_to_res1d(eum_name) + df = location.to_dataframe().rename(columns=lambda x: colname) + if df.shape[1] == 1: + return df[colname].copy() + else: + raise ValueError(f"Multiple matching quantites found at location: {df.columns}") From 1405ff26d926d0504e406c3a241655449fdc76d0 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 14:58:43 +0100 Subject: [PATCH 08/17] Fixing naming of network data --- src/modelskill/timeseries/_point.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index f531734e5..c23e0adf2 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -6,7 +6,6 @@ import numpy as np import pandas as pd import xarray as xr -import difflib import mikeio import mikeio1d @@ -231,9 +230,15 @@ def eum_name_to_res1d(name: str) -> str: # After filtering by node or by reach and chainage, a location will only # have unique quantities - colname = eum_name_to_res1d(eum_name) - df = location.to_dataframe().rename(columns=lambda x: colname) + res1d_name = eum_name_to_res1d(eum_name) + df = location.to_dataframe() if df.shape[1] == 1: - return df[colname].copy() + colname = df.columns[0] + if res1d_name not in colname: + raise ValueError( + f"Column name '{colname}' does not match expected pattern '{res1d_name}'" + ) + + return df.rename(columns={colname: res1d_name})[res1d_name].copy() else: raise ValueError(f"Multiple matching quantites found at location: {df.columns}") From 52a28184440f5c9cb2c6203991beaea013c5e666 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 15:05:04 +0100 Subject: [PATCH 09/17] Improving error message --- src/modelskill/timeseries/_point.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index c23e0adf2..3f9f0b2d5 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -235,9 +235,7 @@ def eum_name_to_res1d(name: str) -> str: if df.shape[1] == 1: colname = df.columns[0] if res1d_name not in colname: - raise ValueError( - f"Column name '{colname}' does not match expected pattern '{res1d_name}'" - ) + raise ValueError(f"Column name '{colname}' does not contain '{res1d_name}'") return df.rename(columns={colname: res1d_name})[res1d_name].copy() else: From f06766879a16b805961f20f32fc176ed7b08e818 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 15:12:53 +0100 Subject: [PATCH 10/17] Fix typo --- notebooks/Network_comparison.ipynb | 402 ++++++++++++++++++++++++---- src/modelskill/timeseries/_point.py | 2 +- 2 files changed, 351 insertions(+), 53 deletions(-) diff --git a/notebooks/Network_comparison.ipynb b/notebooks/Network_comparison.ipynb index 7a7b78124..09477835d 100644 --- a/notebooks/Network_comparison.ipynb +++ b/notebooks/Network_comparison.ipynb @@ -16,31 +16,6 @@ { "cell_type": "code", "execution_count": 2, - "id": "751cfe2e", - "metadata": {}, - "outputs": [], - "source": [ - "# def df_column_name_generator(data, *, quantity=None, reach=None, gridpoint_index=None, chainage=None, node=None):\n", - "# separator = \":\"\n", - "# col_head = [quantity]\n", - "# if node is not None:\n", - "# col_tail = [node]\n", - "# if reach is not None:\n", - "# if (gridpoint_index is None) and (chainage is not None):\n", - "# col_tail = [reach, chainage]\n", - "# elif (gridpoint_index is not None) and (chainage is None):\n", - "# # Find chainage based on reach and index\n", - "# raise NotImplementedError()\n", - "# else:\n", - "# raise ValueError(\"If specifying by reach, use either 'gridpoint_index' or 'chainage' but not both.\")\n", - " \n", - "# col_elements = [str(el) for el in col_head + col_tail]\n", - "# return separator.join(col_elements)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, "id": "2e6fe4e5", "metadata": {}, "outputs": [], @@ -66,13 +41,14 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "id": "c88c8a87", "metadata": {}, "outputs": [], "source": [ "# - Loading model_results\n", - "nt = m1d.open('../tests/testdata/network.res1d')\n", + "path_to_res1d = '../tests/testdata/network.res1d'\n", + "nt = m1d.open(path_to_res1d)\n", "\n", "# - Loading observations (in this cases, they are loaded from the cell above)\n", "# observations = pd.read_csv(...)" @@ -80,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "568f6f18", "metadata": {}, "outputs": [ @@ -165,7 +141,7 @@ "sensor_10 -0.003818 " ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -174,16 +150,24 @@ "obs_9 = ms.PointObservation(observations, item=\"sensor_9\")\n", "obs_10 = ms.PointObservation(observations, item=\"sensor_10\")\n", "\n", - "id = \"WaterLevel:7\"\n", - "modres = ms.PointModelResult(nt.to_dataframe(), item=id)\n", + "res1d_item = \"WaterLevel:7\"\n", + "nt = m1d.open(path_to_res1d)\n", + "df = nt.to_dataframe()\n", + "modres = ms.PointModelResult(df, item=res1d_item)\n", "\n", "comparer_1 = ms.match(obs_9, modres)\n", "comparer_2 = ms.match(obs_10, modres)\n", - "# comparer_1 = ms.match(observations, nt.to_dataframe(), obs_item=\"sensor_9\", mod_item=id, gtype=\"point\")\n", - "# comparer_2 = ms.match(observations, nt.to_dataframe(), obs_item=\"sensor_10\", mod_item=id, gtype=\"point\")\n", "\n", - "ccol = ms.ComparerCollection([comparer_1, comparer_2])\n", - "ccol.skill()" + "ccol0 = ms.ComparerCollection([comparer_1, comparer_2])\n", + "ccol0.skill()" + ] + }, + { + "cell_type": "markdown", + "id": "393b840c", + "metadata": {}, + "source": [ + "- We can simplify further the workflow and not initialize `PointObservation` and `PointModelResult`." ] }, { @@ -207,29 +191,132 @@ }, { "cell_type": "code", - "execution_count": 6, - "id": "493b9c9d", + "execution_count": 5, + "id": "7607223b", "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\japr\\Repos\\modelskill\\src\\modelskill\\quantity.py:190: UserWarning: unit='meter' was automatically set for type_name='Water Level'\n", + " warnings.warn(f\"{unit=} was automatically set for {type_name=}\")\n" + ] + }, { "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    nbiasrmseurmsemaeccsir2
    observation
    sensor_91100.7437789.1679659.1377447.7013890.1818370.0472570.008068
    sensor_101100.5358629.3369349.3215447.8073910.0170570.048156-0.003818
    \n", + "
    " + ], "text/plain": [ - "typing.Union[str, pathlib._local.Path, pandas.core.frame.DataFrame, pandas.core.series.Series, mikeio.dfs._dfs0.Dfs0, mikeio.dataset._dataset.Dataset, mikeio.dataset._dataarray.DataArray, xarray.core.dataset.Dataset, xarray.core.dataarray.DataArray, mikeio1d.res1d.Res1D]" + " n bias rmse urmse mae cc si \\\n", + "observation \n", + "sensor_9 110 0.743778 9.167965 9.137744 7.701389 0.181837 0.047257 \n", + "sensor_10 110 0.535862 9.336934 9.321544 7.807391 0.017057 0.048156 \n", + "\n", + " r2 \n", + "observation \n", + "sensor_9 0.008068 \n", + "sensor_10 -0.003818 " ] }, - "execution_count": 6, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "ms.model.point.PointType" + "from modelskill.model import NetworkModelResult\n", + "\n", + "res = NetworkModelResult(path_to_res1d, \"Water Level\", node=7)\n", + "obs_1 = ms.PointObservation(observations, item=\"sensor_9\")\n", + "obs_2 = ms.PointObservation(observations, item=\"sensor_10\")\n", + "\n", + "comparer_1 = ms.match(obs_1, res)\n", + "comparer_2 = ms.match(obs_2, res)\n", + "\n", + "ccol = ms.ComparerCollection([comparer_1, comparer_2])\n", + "ccol.skill()" + ] + }, + { + "cell_type": "markdown", + "id": "a59a1d87", + "metadata": {}, + "source": [ + "#### Thoughts\n", + "- It would be benefitial to have a better way to specify the item in the network file\n", + "- We can actually omit the `NetworkPointObservation` since observations are scarce and typically stored in csv files representing a dataframe" ] }, { "cell_type": "code", - "execution_count": 7, - "id": "7607223b", + "execution_count": 6, + "id": "80271095", "metadata": {}, "outputs": [ { @@ -313,23 +400,181 @@ "sensor_10 -0.003818 " ] }, - "execution_count": 7, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "res = ms.PointModelResult(nt, item=\"WaterLevel:7\")\n", - "obs_1 = ms.obs.NetworkPointObservation(observations, item=\"sensor_9\")\n", - "obs_2 = ms.obs.NetworkPointObservation(observations, item=\"sensor_10\")\n", + "quantity = ms.Quantity(\"Water Level\", unit=\"m3_per_sec\")\n", + "mod_item = NetworkModelResult(path_to_res1d, quantity, node=7)\n", + "obs1 = ms.PointObservation(observations, quantity=quantity, item=\"sensor_9\")\n", + "obs2 = ms.PointObservation(observations, quantity=quantity, item=\"sensor_10\")\n", "\n", - "comparer_1 = ms.match(obs_1, res)\n", - "comparer_2 = ms.match(obs_2, res)\n", + "comparer_1 = ms.match(obs1, mod_item)\n", + "comparer_2 = ms.match(obs2, mod_item)\n", + "# comparer_1 = ms.match(observations, path_to_res1d, obs_item=\"sensor_9\", mod_item=mod_item, gtype=\"point\")\n", + "# comparer_2 = ms.match(observations, path_to_res1d, obs_item=\"sensor_10\", mod_item=mod_item, gtype=\"point\")\n", "\n", "ccol = ms.ComparerCollection([comparer_1, comparer_2])\n", "ccol.skill()" ] }, + { + "cell_type": "markdown", + "id": "55f42b62", + "metadata": {}, + "source": [ + "### Multiple models" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "9ee90ffe", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    nbiasrmseurmsemaeccsir2
    modelobservation
    wl 1sensor_91100.7437789.1679659.1377447.7013890.1818370.0472570.008068
    wl 2sensor_91102.2485879.4089639.1363257.8827460.2052370.047249-0.044767
    \n", + "
    " + ], + "text/plain": [ + " n bias rmse urmse mae cc \\\n", + "model observation \n", + "wl 1 sensor_9 110 0.743778 9.167965 9.137744 7.701389 0.181837 \n", + "wl 2 sensor_9 110 2.248587 9.408963 9.136325 7.882746 0.205237 \n", + "\n", + " si r2 \n", + "model observation \n", + "wl 1 sensor_9 0.047257 0.008068 \n", + "wl 2 sensor_9 0.047249 -0.044767 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "quantity = ms.Quantity(\"Water Level\", unit=\"m3_per_sec\")\n", + "mod_item = NetworkModelResult(path_to_res1d, quantity, node=7)\n", + "mod_item = NetworkModelResult(path_to_res1d, quantity, node=7)\n", + "mod_item = NetworkModelResult(path_to_res1d, quantity, node=7)\n", + "\n", + "models = [\n", + " NetworkModelResult(path_to_res1d, quantity, node=7, name=\"wl 1\"),\n", + " NetworkModelResult(path_to_res1d, quantity, reach=\"100l1\", gridpoint=\"start\", name=\"wl 2\")\n", + "]\n", + "\n", + "obs1 = ms.PointObservation(observations, quantity=quantity, item=\"sensor_9\")\n", + "\n", + "comparer_1 = ms.match(obs1, models)\n", + "comparer_1.skill()" + ] + }, + { + "cell_type": "markdown", + "id": "28e70f19", + "metadata": {}, + "source": [ + "Other examples..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0323c519", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + ": WaterLevel:54l1:47.6946\n", + "Location: nan, nan\n", + "Time: 1994-08-07 16:35:00 - 1994-08-07 18:35:00\n", + "Quantity: []" + ] + }, + "execution_count": 93, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# res = NetworkModelResult(path_to_res1d, \"WaterLevel\", reach=\"100l1\", gridpoint=\"end\")\n", + "# res = NetworkModelResult(path_to_res1d, \"WaterLevel\", reach=\"100l1\", gridpoint=1)\n", + "# res = NetworkModelResult(path_to_res1d, \"WaterLevel\", reach=\"100l1\", chainage=47.7)" + ] + }, { "cell_type": "markdown", "id": "27a4fcb2", @@ -348,12 +593,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 66, "id": "46fca47b", "metadata": {}, "outputs": [], "source": [ - "def get_n_quantities(nt: m1d.result_network.ResultNetwork):\n", + "def get_n_items(nt: m1d.result_network.ResultNetwork):\n", " i = 0\n", " for reach in nt.reaches.values():\n", " for n in reach.gridpoints:\n", @@ -365,9 +610,62 @@ " return i\n", "\n", "\n", - "n_quantities = get_n_quantities(nt)\n", + "n_items = get_n_items(nt)\n", "\n", - "assert n_quantities == nt.to_dataframe().shape[1]" + "assert n_items == nt.to_dataframe().shape[1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1376ce3", + "metadata": {}, + "outputs": [], + "source": [ + "class QuantityNetwork:\n", + " def __init__(self, res1d: m1d.Res1D, quantity: str):\n", + " self.res1d = res1d\n", + " self.quantity = quantity\n", + " self._filtered_res1d = None\n", + " \n", + " def get_filtered_res1d(self) -> m1d.Res1D:\n", + " \"\"\"Returns a new Res1D object containing only the specified quantity.\"\"\"\n", + " if self._filtered_res1d is not None:\n", + " return self._filtered_res1d\n", + " \n", + " # Get the original dataframe\n", + " df = self.res1d.to_dataframe()\n", + " \n", + " # Filter columns to only include the specified quantity\n", + " quantity_columns = [col for col in df.columns if col.startswith(f\"{self.quantity}:\")]\n", + " \n", + " if not quantity_columns:\n", + " raise ValueError(f\"Quantity '{self.quantity}' not found in the Res1D object\")\n", + " \n", + " # Create filtered dataframe\n", + " filtered_df = df[quantity_columns]\n", + " \n", + " # For now, we'll return the original res1d object since creating a new Res1D \n", + " # from filtered data might require more complex reconstruction\n", + " # This is a placeholder implementation that could be enhanced\n", + " self._filtered_res1d = self.res1d\n", + " \n", + " return self._filtered_res1d\n", + " \n", + " def to_dataframe(self):\n", + " \"\"\"Returns a dataframe with only the specified quantity.\"\"\"\n", + " df = self.res1d.to_dataframe()\n", + " quantity_columns = [col for col in df.columns if col.startswith(f\"{self.quantity}:\")]\n", + " \n", + " if not quantity_columns:\n", + " raise ValueError(f\"Quantity '{self.quantity}' not found in the Res1D object\")\n", + " \n", + " return df[quantity_columns]\n", + " \n", + " def get_quantity_columns(self):\n", + " \"\"\"Returns the column names that match the specified quantity.\"\"\"\n", + " df = self.res1d.to_dataframe()\n", + " return [col for col in df.columns if col.startswith(f\"{self.quantity}:\")]" ] }, { diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index 3f9f0b2d5..927cd3910 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -213,7 +213,7 @@ def eum_name_to_res1d(name: str) -> str: elif by_reach and not by_node: location = data.reaches[reach] - if with_index != with_chainage: + if with_index == with_chainage: raise ValueError( "Items accessed by chainage must be specified either by chainage or by index, not both" ) From 59b2104c0c7197166ef61383edc4d437e6668bd3 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 15:37:21 +0100 Subject: [PATCH 11/17] Adding docstring --- src/modelskill/model/network.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/modelskill/model/network.py b/src/modelskill/model/network.py index f86bfed26..692db11eb 100644 --- a/src/modelskill/model/network.py +++ b/src/modelskill/model/network.py @@ -9,10 +9,36 @@ class NetworkModelResult(PointModelResult): + """Model result for a network location. + + Construct a NetworkModelResult from a res1d data source. + + Parameters + ---------- + data : str, Path or mikeio1d.Res1D + filename (.res1d) or object with the data + quantity : str + The name of the model result, + by default None (will be set to file name or item name) + reach : str, optional + Reach id in the network + node : int, optional + Node id in the network + chainage : float, optional + Chainage number in its respective reach + gridpoint : int, optional + Index associated to the gridpoints in the reach + name : Optional[str], optional + The name of the model result, + by default None (will be set to file name or item name) + aux_items : Optional[list[int | str]], optional + Auxiliary items, by default None + """ + def __init__( self, data: Res1D | str, - quantity: Optional[str | Quantity] = None, + quantity: str | Quantity, *, reach: Optional[str] = None, node: Optional[int] = None, From 2711355e675b545c6aef5b267b0f90221a463685 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 15:39:52 +0100 Subject: [PATCH 12/17] Clean network comparison notebook --- notebooks/Network_comparison.ipynb | 2037 +--------------------------- 1 file changed, 24 insertions(+), 2013 deletions(-) diff --git a/notebooks/Network_comparison.ipynb b/notebooks/Network_comparison.ipynb index 09477835d..7ddf47223 100644 --- a/notebooks/Network_comparison.ipynb +++ b/notebooks/Network_comparison.ipynb @@ -257,17 +257,6 @@ " 0.047257\n", " 0.008068\n", " \n", - " \n", - " sensor_10\n", - " 110\n", - " 0.535862\n", - " 9.336934\n", - " 9.321544\n", - " 7.807391\n", - " 0.017057\n", - " 0.048156\n", - " -0.003818\n", - " \n", " \n", "\n", "" @@ -276,12 +265,10 @@ " n bias rmse urmse mae cc si \\\n", "observation \n", "sensor_9 110 0.743778 9.167965 9.137744 7.701389 0.181837 0.047257 \n", - "sensor_10 110 0.535862 9.336934 9.321544 7.807391 0.017057 0.048156 \n", "\n", " r2 \n", "observation \n", - "sensor_9 0.008068 \n", - "sensor_10 -0.003818 " + "sensor_9 0.008068 " ] }, "execution_count": 5, @@ -290,17 +277,11 @@ } ], "source": [ - "from modelskill.model import NetworkModelResult\n", - "\n", - "res = NetworkModelResult(path_to_res1d, \"Water Level\", node=7)\n", + "res = ms.NetworkModelResult(path_to_res1d, \"Water Level\", node=7)\n", "obs_1 = ms.PointObservation(observations, item=\"sensor_9\")\n", - "obs_2 = ms.PointObservation(observations, item=\"sensor_10\")\n", "\n", "comparer_1 = ms.match(obs_1, res)\n", - "comparer_2 = ms.match(obs_2, res)\n", - "\n", - "ccol = ms.ComparerCollection([comparer_1, comparer_2])\n", - "ccol.skill()" + "comparer_1.skill()" ] }, { @@ -407,14 +388,12 @@ ], "source": [ "quantity = ms.Quantity(\"Water Level\", unit=\"m3_per_sec\")\n", - "mod_item = NetworkModelResult(path_to_res1d, quantity, node=7)\n", + "mod_item = ms.NetworkModelResult(path_to_res1d, quantity, node=7)\n", "obs1 = ms.PointObservation(observations, quantity=quantity, item=\"sensor_9\")\n", "obs2 = ms.PointObservation(observations, quantity=quantity, item=\"sensor_10\")\n", "\n", "comparer_1 = ms.match(obs1, mod_item)\n", "comparer_2 = ms.match(obs2, mod_item)\n", - "# comparer_1 = ms.match(observations, path_to_res1d, obs_item=\"sensor_9\", mod_item=mod_item, gtype=\"point\")\n", - "# comparer_2 = ms.match(observations, path_to_res1d, obs_item=\"sensor_10\", mod_item=mod_item, gtype=\"point\")\n", "\n", "ccol = ms.ComparerCollection([comparer_1, comparer_2])\n", "ccol.skill()" @@ -430,7 +409,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "id": "9ee90ffe", "metadata": {}, "outputs": [ @@ -503,6 +482,18 @@ " 0.047249\n", " -0.044767\n", " \n", + " \n", + " wl 3\n", + " sensor_9\n", + " 110\n", + " 0.808813\n", + " 9.240242\n", + " 9.204776\n", + " 7.772271\n", + " 0.212348\n", + " 0.047603\n", + " -0.007633\n", + " \n", " \n", "\n", "" @@ -512,27 +503,26 @@ "model observation \n", "wl 1 sensor_9 110 0.743778 9.167965 9.137744 7.701389 0.181837 \n", "wl 2 sensor_9 110 2.248587 9.408963 9.136325 7.882746 0.205237 \n", + "wl 3 sensor_9 110 0.808813 9.240242 9.204776 7.772271 0.212348 \n", "\n", " si r2 \n", "model observation \n", "wl 1 sensor_9 0.047257 0.008068 \n", - "wl 2 sensor_9 0.047249 -0.044767 " + "wl 2 sensor_9 0.047249 -0.044767 \n", + "wl 3 sensor_9 0.047603 -0.007633 " ] }, - "execution_count": 9, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quantity = ms.Quantity(\"Water Level\", unit=\"m3_per_sec\")\n", - "mod_item = NetworkModelResult(path_to_res1d, quantity, node=7)\n", - "mod_item = NetworkModelResult(path_to_res1d, quantity, node=7)\n", - "mod_item = NetworkModelResult(path_to_res1d, quantity, node=7)\n", - "\n", "models = [\n", - " NetworkModelResult(path_to_res1d, quantity, node=7, name=\"wl 1\"),\n", - " NetworkModelResult(path_to_res1d, quantity, reach=\"100l1\", gridpoint=\"start\", name=\"wl 2\")\n", + " ms.NetworkModelResult(path_to_res1d, quantity, node=7, name=\"wl 1\"),\n", + " ms.NetworkModelResult(path_to_res1d, quantity, reach=\"100l1\", gridpoint=\"start\", name=\"wl 2\"),\n", + " ms.NetworkModelResult(path_to_res1d, quantity, reach=\"54l1\", gridpoint=0, name=\"wl 3\")\n", "]\n", "\n", "obs1 = ms.PointObservation(observations, quantity=quantity, item=\"sensor_9\")\n", @@ -540,1985 +530,6 @@ "comparer_1 = ms.match(obs1, models)\n", "comparer_1.skill()" ] - }, - { - "cell_type": "markdown", - "id": "28e70f19", - "metadata": {}, - "source": [ - "Other examples..." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0323c519", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - ": WaterLevel:54l1:47.6946\n", - "Location: nan, nan\n", - "Time: 1994-08-07 16:35:00 - 1994-08-07 18:35:00\n", - "Quantity: []" - ] - }, - "execution_count": 93, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# res = NetworkModelResult(path_to_res1d, \"WaterLevel\", reach=\"100l1\", gridpoint=\"end\")\n", - "# res = NetworkModelResult(path_to_res1d, \"WaterLevel\", reach=\"100l1\", gridpoint=1)\n", - "# res = NetworkModelResult(path_to_res1d, \"WaterLevel\", reach=\"100l1\", chainage=47.7)" - ] - }, - { - "cell_type": "markdown", - "id": "27a4fcb2", - "metadata": {}, - "source": [ - "## Sandbox" - ] - }, - { - "cell_type": "markdown", - "id": "cd9bb273", - "metadata": {}, - "source": [ - "A dataframe has the number of columns equal to the number of gridpoints + nodes." - ] - }, - { - "cell_type": "code", - "execution_count": 66, - "id": "46fca47b", - "metadata": {}, - "outputs": [], - "source": [ - "def get_n_items(nt: m1d.result_network.ResultNetwork):\n", - " i = 0\n", - " for reach in nt.reaches.values():\n", - " for n in reach.gridpoints:\n", - " i += len(n.quantities)\n", - "\n", - " for node in nt.nodes.values():\n", - " i += len(node.quantities)\n", - " \n", - " return i\n", - "\n", - "\n", - "n_items = get_n_items(nt)\n", - "\n", - "assert n_items == nt.to_dataframe().shape[1]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e1376ce3", - "metadata": {}, - "outputs": [], - "source": [ - "class QuantityNetwork:\n", - " def __init__(self, res1d: m1d.Res1D, quantity: str):\n", - " self.res1d = res1d\n", - " self.quantity = quantity\n", - " self._filtered_res1d = None\n", - " \n", - " def get_filtered_res1d(self) -> m1d.Res1D:\n", - " \"\"\"Returns a new Res1D object containing only the specified quantity.\"\"\"\n", - " if self._filtered_res1d is not None:\n", - " return self._filtered_res1d\n", - " \n", - " # Get the original dataframe\n", - " df = self.res1d.to_dataframe()\n", - " \n", - " # Filter columns to only include the specified quantity\n", - " quantity_columns = [col for col in df.columns if col.startswith(f\"{self.quantity}:\")]\n", - " \n", - " if not quantity_columns:\n", - " raise ValueError(f\"Quantity '{self.quantity}' not found in the Res1D object\")\n", - " \n", - " # Create filtered dataframe\n", - " filtered_df = df[quantity_columns]\n", - " \n", - " # For now, we'll return the original res1d object since creating a new Res1D \n", - " # from filtered data might require more complex reconstruction\n", - " # This is a placeholder implementation that could be enhanced\n", - " self._filtered_res1d = self.res1d\n", - " \n", - " return self._filtered_res1d\n", - " \n", - " def to_dataframe(self):\n", - " \"\"\"Returns a dataframe with only the specified quantity.\"\"\"\n", - " df = self.res1d.to_dataframe()\n", - " quantity_columns = [col for col in df.columns if col.startswith(f\"{self.quantity}:\")]\n", - " \n", - " if not quantity_columns:\n", - " raise ValueError(f\"Quantity '{self.quantity}' not found in the Res1D object\")\n", - " \n", - " return df[quantity_columns]\n", - " \n", - " def get_quantity_columns(self):\n", - " \"\"\"Returns the column names that match the specified quantity.\"\"\"\n", - " df = self.res1d.to_dataframe()\n", - " return [col for col in df.columns if col.startswith(f\"{self.quantity}:\")]" - ] - }, - { - "cell_type": "code", - "execution_count": 73, - "id": "590e2e50", - "metadata": {}, - "outputs": [], - "source": [ - "quantity = \"WaterLevel\"\n", - "quantity_in_nodes = quantity in nt.nodes.quantities.keys()\n", - "quantity_in_reaches = nt.reaches.quantities.keys()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "14186ce2", - "metadata": {}, - "outputs": [], - "source": [ - "# - Specify relevant quantity\n", - "# - Iterate over (mike1d)reaches and select gridpoints with such quantity, we will call them nodes\n", - "# - Check if (mike1d)nodes contain such quantity\n", - "# - Fill quantity network\n", - "# - Location in the network is specified with two" - ] - }, - { - "cell_type": "code", - "execution_count": 74, - "id": "9531ae9e", - "metadata": {}, - "outputs": [], - "source": [ - "key_map = list(nt.nodes.keys())\n", - "\n", - "assert len(set(key_map)) == len(key_map) # checking that there are no duplicate node names\n", - "\n", - "n_nodes = len(key_map)\n", - "adjacency = [[]] * n_nodes\n", - "for reach in nt.reaches.values():\n", - " i = key_map.index(reach.start_node)\n", - " j = key_map.index(reach.end_node)\n", - " adjacency[i].append(j)\n", - "\n", - "edges_by_node = [len(ad) for ad in adjacency]\n", - "adjacency = [l for sublist in adjacency for l in sublist]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a118c674", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 77, - "id": "4c19c1be", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'100'" - ] - }, - "execution_count": 77, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nt.reaches[\"100l1\"].start_node" - ] - }, - { - "cell_type": "code", - "execution_count": 75, - "id": "a7528539", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118,\n", - " 118]" - ] - }, - "execution_count": 75, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "adjacency\n", - "edges_by_node" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "15122fdb", - "metadata": {}, - "outputs": [ - { - "ename": "IndexError", - "evalue": "list index out of range", - "output_type": "error", - "traceback": [ - "\u001b[31m---------------------------------------------------------------------------\u001b[39m", - "\u001b[31mIndexError\u001b[39m Traceback (most recent call last)", - "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[35]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m k = \u001b[32m3\u001b[39m\n\u001b[32m 2\u001b[39m i = \u001b[38;5;28msum\u001b[39m(edges_by_node[:k]) + edges_by_node[k]\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[43madjacency\u001b[49m\u001b[43m[\u001b[49m\u001b[43mi\u001b[49m\u001b[43m]\u001b[49m\n", - "\u001b[31mIndexError\u001b[39m: list index out of range" - ] - } - ], - "source": [ - "k = 3\n", - "i = sum(edges_by_node[:k]) + edges_by_node[k]\n", - "adjacency[i]" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "c09a7015", - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "object of type 'int' has no len()", - "output_type": "error", - "traceback": [ - "\u001b[31m---------------------------------------------------------------------------\u001b[39m", - "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)", - "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[29]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m [\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mn\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mfor\u001b[39;00m n \u001b[38;5;129;01min\u001b[39;00m adjacency] \n", - "\u001b[31mTypeError\u001b[39m: object of type 'int' has no len()" - ] - } - ], - "source": [ - "[len(n) for n in adjacency] " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9bdadc2a", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "119" - ] - }, - "execution_count": 53, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.zeros(n_nodes)" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "id": "0725e4be", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
    WaterLevel:1WaterLevel:2WaterLevel:3WaterLevel:4WaterLevel:5WaterLevel:6WaterLevel:7WaterLevel:8WaterLevel:9WaterLevel:10...WaterLevel:46WaterLevel:55WaterLevel:58WaterLevel:116WaterLevel:117WaterLevel:118WaterLevel:115WaterLevel:119WaterLevel:120WaterLevel:Weir Outlet:119w1
    1994-08-07 16:35:00.000195.052994195.821503195.8815193.604996193.615005193.625000193.675003193.764999193.774994193.804993...194.074997195.005005193.554993193.550003193.585007193.585007193.304993193.550003193.550003193.779999
    1994-08-07 16:36:01.870195.052994195.821701195.8815193.604996193.615005193.625320193.675110193.765060193.775116193.804993...194.074997195.005005193.555023193.550064193.585831193.586807193.306061193.550003193.550003188.479996
    1994-08-07 16:37:07.560195.052994195.821640195.8815193.604996193.615005193.625671193.675369193.765106193.775513193.804993...194.074997195.005005193.555084193.550110193.586426193.588196193.307144193.550034193.550003188.479996
    1994-08-07 16:38:55.828195.052994195.821503195.8815193.604996193.615005193.626236193.675751193.765228193.776077193.804993...194.074997195.005005193.555191193.550156193.586960193.589706193.308884193.550079193.550003188.479996
    1994-08-07 16:39:55.828195.052994195.821503195.8815193.604996193.615005193.626556193.675949193.765335193.776352193.804993...194.074997195.005005193.555267193.550171193.587112193.590317193.309860193.550095193.550003188.479996
    ..................................................................
    1994-08-07 18:30:07.967195.119919195.822769195.8815193.884308193.931808193.961746193.977524193.999054194.010910194.023590...194.087036195.025726193.832489193.830322193.755844193.832626193.755829193.800369193.550003188.479996
    1994-08-07 18:31:07.967195.118607195.822769195.8815193.879333193.926086193.955582193.971191193.992905194.004776194.017578...194.086807195.025391193.828842193.826797193.756500193.828964193.756470193.798798193.550003188.479996
    1994-08-07 18:32:07.967195.117310195.822769195.8815193.874542193.920532193.949615193.965073193.986984193.998856194.011795...194.086609195.025070193.825348193.823456193.757156193.825485193.757172193.797256193.550003188.479996
    1994-08-07 18:33:07.967195.115753195.822769195.8815193.869873193.915131193.943802193.959091193.981171193.993011194.006042...194.086411195.024796193.822006193.820160193.757736193.822144193.757660193.795715193.550003188.479996
    1994-08-07 18:35:00.000195.112534195.822769195.8815193.861450193.905396193.933258193.948181193.970627193.982437193.995468...194.086029195.024307193.816025193.814346193.758698193.816177193.758667193.792877193.550003188.479996
    \n", - "

    110 rows × 119 columns

    \n", - "
    " - ], - "text/plain": [ - " WaterLevel:1 WaterLevel:2 WaterLevel:3 \\\n", - "1994-08-07 16:35:00.000 195.052994 195.821503 195.8815 \n", - "1994-08-07 16:36:01.870 195.052994 195.821701 195.8815 \n", - "1994-08-07 16:37:07.560 195.052994 195.821640 195.8815 \n", - "1994-08-07 16:38:55.828 195.052994 195.821503 195.8815 \n", - "1994-08-07 16:39:55.828 195.052994 195.821503 195.8815 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 195.119919 195.822769 195.8815 \n", - "1994-08-07 18:31:07.967 195.118607 195.822769 195.8815 \n", - "1994-08-07 18:32:07.967 195.117310 195.822769 195.8815 \n", - "1994-08-07 18:33:07.967 195.115753 195.822769 195.8815 \n", - "1994-08-07 18:35:00.000 195.112534 195.822769 195.8815 \n", - "\n", - " WaterLevel:4 WaterLevel:5 WaterLevel:6 \\\n", - "1994-08-07 16:35:00.000 193.604996 193.615005 193.625000 \n", - "1994-08-07 16:36:01.870 193.604996 193.615005 193.625320 \n", - "1994-08-07 16:37:07.560 193.604996 193.615005 193.625671 \n", - "1994-08-07 16:38:55.828 193.604996 193.615005 193.626236 \n", - "1994-08-07 16:39:55.828 193.604996 193.615005 193.626556 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 193.884308 193.931808 193.961746 \n", - "1994-08-07 18:31:07.967 193.879333 193.926086 193.955582 \n", - "1994-08-07 18:32:07.967 193.874542 193.920532 193.949615 \n", - "1994-08-07 18:33:07.967 193.869873 193.915131 193.943802 \n", - "1994-08-07 18:35:00.000 193.861450 193.905396 193.933258 \n", - "\n", - " WaterLevel:7 WaterLevel:8 WaterLevel:9 \\\n", - "1994-08-07 16:35:00.000 193.675003 193.764999 193.774994 \n", - "1994-08-07 16:36:01.870 193.675110 193.765060 193.775116 \n", - "1994-08-07 16:37:07.560 193.675369 193.765106 193.775513 \n", - "1994-08-07 16:38:55.828 193.675751 193.765228 193.776077 \n", - "1994-08-07 16:39:55.828 193.675949 193.765335 193.776352 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 193.977524 193.999054 194.010910 \n", - "1994-08-07 18:31:07.967 193.971191 193.992905 194.004776 \n", - "1994-08-07 18:32:07.967 193.965073 193.986984 193.998856 \n", - "1994-08-07 18:33:07.967 193.959091 193.981171 193.993011 \n", - "1994-08-07 18:35:00.000 193.948181 193.970627 193.982437 \n", - "\n", - " WaterLevel:10 ... WaterLevel:46 WaterLevel:55 \\\n", - "1994-08-07 16:35:00.000 193.804993 ... 194.074997 195.005005 \n", - "1994-08-07 16:36:01.870 193.804993 ... 194.074997 195.005005 \n", - "1994-08-07 16:37:07.560 193.804993 ... 194.074997 195.005005 \n", - "1994-08-07 16:38:55.828 193.804993 ... 194.074997 195.005005 \n", - "1994-08-07 16:39:55.828 193.804993 ... 194.074997 195.005005 \n", - "... ... ... ... ... \n", - "1994-08-07 18:30:07.967 194.023590 ... 194.087036 195.025726 \n", - "1994-08-07 18:31:07.967 194.017578 ... 194.086807 195.025391 \n", - "1994-08-07 18:32:07.967 194.011795 ... 194.086609 195.025070 \n", - "1994-08-07 18:33:07.967 194.006042 ... 194.086411 195.024796 \n", - "1994-08-07 18:35:00.000 193.995468 ... 194.086029 195.024307 \n", - "\n", - " WaterLevel:58 WaterLevel:116 WaterLevel:117 \\\n", - "1994-08-07 16:35:00.000 193.554993 193.550003 193.585007 \n", - "1994-08-07 16:36:01.870 193.555023 193.550064 193.585831 \n", - "1994-08-07 16:37:07.560 193.555084 193.550110 193.586426 \n", - "1994-08-07 16:38:55.828 193.555191 193.550156 193.586960 \n", - "1994-08-07 16:39:55.828 193.555267 193.550171 193.587112 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 193.832489 193.830322 193.755844 \n", - "1994-08-07 18:31:07.967 193.828842 193.826797 193.756500 \n", - "1994-08-07 18:32:07.967 193.825348 193.823456 193.757156 \n", - "1994-08-07 18:33:07.967 193.822006 193.820160 193.757736 \n", - "1994-08-07 18:35:00.000 193.816025 193.814346 193.758698 \n", - "\n", - " WaterLevel:118 WaterLevel:115 WaterLevel:119 \\\n", - "1994-08-07 16:35:00.000 193.585007 193.304993 193.550003 \n", - "1994-08-07 16:36:01.870 193.586807 193.306061 193.550003 \n", - "1994-08-07 16:37:07.560 193.588196 193.307144 193.550034 \n", - "1994-08-07 16:38:55.828 193.589706 193.308884 193.550079 \n", - "1994-08-07 16:39:55.828 193.590317 193.309860 193.550095 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 193.832626 193.755829 193.800369 \n", - "1994-08-07 18:31:07.967 193.828964 193.756470 193.798798 \n", - "1994-08-07 18:32:07.967 193.825485 193.757172 193.797256 \n", - "1994-08-07 18:33:07.967 193.822144 193.757660 193.795715 \n", - "1994-08-07 18:35:00.000 193.816177 193.758667 193.792877 \n", - "\n", - " WaterLevel:120 WaterLevel:Weir Outlet:119w1 \n", - "1994-08-07 16:35:00.000 193.550003 193.779999 \n", - "1994-08-07 16:36:01.870 193.550003 188.479996 \n", - "1994-08-07 16:37:07.560 193.550003 188.479996 \n", - "1994-08-07 16:38:55.828 193.550003 188.479996 \n", - "1994-08-07 16:39:55.828 193.550003 188.479996 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 193.550003 188.479996 \n", - "1994-08-07 18:31:07.967 193.550003 188.479996 \n", - "1994-08-07 18:32:07.967 193.550003 188.479996 \n", - "1994-08-07 18:33:07.967 193.550003 188.479996 \n", - "1994-08-07 18:35:00.000 193.550003 188.479996 \n", - "\n", - "[110 rows x 119 columns]" - ] - }, - "execution_count": 52, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "quantity = \"WaterLevel\"\n", - "\n", - "getattr(nt.nodes, quantity).to_dataframe()" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "75511e21", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "<Reach: 100l1>\n", - " \n", - "
    Attributes (9)
    • name: 100l1
    • length: 47.6827148432828
    • start_chainage: 0.0
    • end_chainage: 47.6827148432828
    • n_gridpoints: 3
    • start_node: 100
    • end_node: 99
    • height: 0.30000001192092896
    • full_flow_discharge: 0.12058743359507902
    Quantities (2)
    • Water level (m)
    • Discharge (m^3/s)
    Derived Quantities (6)
    • ReachAbsoluteDischarge
    • ReachFilling
    • ReachFlooding
    • ReachQQManning
    • ReachWaterDepth
    • ReachWaterLevelAboveCritical
    " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nt.reaches[\"100l1\"]" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "d261b2db", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
    WaterLevel:100l1:0WaterLevel:100l1:47.6827WaterLevel:101l1:0WaterLevel:101l1:66.4361WaterLevel:102l1:0WaterLevel:102l1:10.9366WaterLevel:103l1:0WaterLevel:103l1:26.0653WaterLevel:104l1:0WaterLevel:104l1:34.4131...WaterLevel:98l1:0WaterLevel:98l1:16.0098WaterLevel:99l1:0WaterLevel:99l1:44.5016WaterLevel:9l1:0WaterLevel:9l1:10WaterLevel:Weir:119w1:0WaterLevel:Weir:119w1:1WaterLevel:Pump:115p1:0WaterLevel:Pump:115p1:82.4281
    1994-08-07 16:35:00.000195.441498194.661499195.931503195.441498193.550003193.550003195.801498195.701508197.072006196.962006...194.581497194.511505194.661499194.581497193.774994193.764999193.550003188.479996193.304993195.005005
    1994-08-07 16:36:01.870195.441498194.661621195.931503195.441605193.550140193.550064195.801498195.703171197.072006196.962051...194.581497194.511841194.661575194.581497193.775070193.765060193.550003188.479996193.306061195.005005
    1994-08-07 16:37:07.560195.441498194.661728195.931503195.441620193.550232193.550156195.801498195.703400197.072006196.962082...194.581497194.511795194.661667194.581497193.775391193.765106193.550034188.479996193.307144195.005005
    1994-08-07 16:38:55.828195.441498194.661804195.931503195.441605193.550369193.550308195.801498195.703690197.072006196.962112...194.581497194.511581194.661865194.581497193.775894193.765228193.550079188.479996193.308884195.005005
    1994-08-07 16:39:55.828195.441498194.661972195.931503195.441605193.550430193.550369195.801498195.703827197.072006196.962128...194.581497194.511505194.661911194.581497193.776154193.765335193.550095188.479996193.309860195.005005
    ..................................................................
    1994-08-07 18:30:07.967195.455109194.689072195.931946195.470230193.850647193.850388195.801498195.787277197.072006196.967056...194.601105194.533127194.685715194.607559194.000839193.999054193.800369188.479996193.755829195.025726
    1994-08-07 18:31:07.967195.455063194.688934195.931915195.470108193.846222193.845978195.801498195.785614197.072006196.967041...194.601013194.532974194.685608194.607407193.994766193.992905193.798798188.479996193.756470195.025391
    1994-08-07 18:32:07.967195.455002194.688812195.931885195.469986193.841980193.841751195.801498195.783936197.072006196.967026...194.600922194.532822194.685516194.607254193.988892193.986984193.797256188.479996193.757172195.025070
    1994-08-07 18:33:07.967195.453049194.688354195.931870195.467972193.837784193.837585195.801498195.782394197.072006196.966660...194.600815194.532684194.685074194.607101193.983109193.981171193.795715188.479996193.757660195.024796
    1994-08-07 18:35:00.000195.450409194.686172195.931824195.462082193.830017193.829880195.801498195.779617197.072006196.965775...194.600128194.532333194.682861194.606323193.972641193.970627193.792877188.479996193.758667195.024307
    \n", - "

    110 rows × 247 columns

    \n", - "
    " - ], - "text/plain": [ - " WaterLevel:100l1:0 WaterLevel:100l1:47.6827 \\\n", - "1994-08-07 16:35:00.000 195.441498 194.661499 \n", - "1994-08-07 16:36:01.870 195.441498 194.661621 \n", - "1994-08-07 16:37:07.560 195.441498 194.661728 \n", - "1994-08-07 16:38:55.828 195.441498 194.661804 \n", - "1994-08-07 16:39:55.828 195.441498 194.661972 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 195.455109 194.689072 \n", - "1994-08-07 18:31:07.967 195.455063 194.688934 \n", - "1994-08-07 18:32:07.967 195.455002 194.688812 \n", - "1994-08-07 18:33:07.967 195.453049 194.688354 \n", - "1994-08-07 18:35:00.000 195.450409 194.686172 \n", - "\n", - " WaterLevel:101l1:0 WaterLevel:101l1:66.4361 \\\n", - "1994-08-07 16:35:00.000 195.931503 195.441498 \n", - "1994-08-07 16:36:01.870 195.931503 195.441605 \n", - "1994-08-07 16:37:07.560 195.931503 195.441620 \n", - "1994-08-07 16:38:55.828 195.931503 195.441605 \n", - "1994-08-07 16:39:55.828 195.931503 195.441605 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 195.931946 195.470230 \n", - "1994-08-07 18:31:07.967 195.931915 195.470108 \n", - "1994-08-07 18:32:07.967 195.931885 195.469986 \n", - "1994-08-07 18:33:07.967 195.931870 195.467972 \n", - "1994-08-07 18:35:00.000 195.931824 195.462082 \n", - "\n", - " WaterLevel:102l1:0 WaterLevel:102l1:10.9366 \\\n", - "1994-08-07 16:35:00.000 193.550003 193.550003 \n", - "1994-08-07 16:36:01.870 193.550140 193.550064 \n", - "1994-08-07 16:37:07.560 193.550232 193.550156 \n", - "1994-08-07 16:38:55.828 193.550369 193.550308 \n", - "1994-08-07 16:39:55.828 193.550430 193.550369 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 193.850647 193.850388 \n", - "1994-08-07 18:31:07.967 193.846222 193.845978 \n", - "1994-08-07 18:32:07.967 193.841980 193.841751 \n", - "1994-08-07 18:33:07.967 193.837784 193.837585 \n", - "1994-08-07 18:35:00.000 193.830017 193.829880 \n", - "\n", - " WaterLevel:103l1:0 WaterLevel:103l1:26.0653 \\\n", - "1994-08-07 16:35:00.000 195.801498 195.701508 \n", - "1994-08-07 16:36:01.870 195.801498 195.703171 \n", - "1994-08-07 16:37:07.560 195.801498 195.703400 \n", - "1994-08-07 16:38:55.828 195.801498 195.703690 \n", - "1994-08-07 16:39:55.828 195.801498 195.703827 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 195.801498 195.787277 \n", - "1994-08-07 18:31:07.967 195.801498 195.785614 \n", - "1994-08-07 18:32:07.967 195.801498 195.783936 \n", - "1994-08-07 18:33:07.967 195.801498 195.782394 \n", - "1994-08-07 18:35:00.000 195.801498 195.779617 \n", - "\n", - " WaterLevel:104l1:0 WaterLevel:104l1:34.4131 ... \\\n", - "1994-08-07 16:35:00.000 197.072006 196.962006 ... \n", - "1994-08-07 16:36:01.870 197.072006 196.962051 ... \n", - "1994-08-07 16:37:07.560 197.072006 196.962082 ... \n", - "1994-08-07 16:38:55.828 197.072006 196.962112 ... \n", - "1994-08-07 16:39:55.828 197.072006 196.962128 ... \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 197.072006 196.967056 ... \n", - "1994-08-07 18:31:07.967 197.072006 196.967041 ... \n", - "1994-08-07 18:32:07.967 197.072006 196.967026 ... \n", - "1994-08-07 18:33:07.967 197.072006 196.966660 ... \n", - "1994-08-07 18:35:00.000 197.072006 196.965775 ... \n", - "\n", - " WaterLevel:98l1:0 WaterLevel:98l1:16.0098 \\\n", - "1994-08-07 16:35:00.000 194.581497 194.511505 \n", - "1994-08-07 16:36:01.870 194.581497 194.511841 \n", - "1994-08-07 16:37:07.560 194.581497 194.511795 \n", - "1994-08-07 16:38:55.828 194.581497 194.511581 \n", - "1994-08-07 16:39:55.828 194.581497 194.511505 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 194.601105 194.533127 \n", - "1994-08-07 18:31:07.967 194.601013 194.532974 \n", - "1994-08-07 18:32:07.967 194.600922 194.532822 \n", - "1994-08-07 18:33:07.967 194.600815 194.532684 \n", - "1994-08-07 18:35:00.000 194.600128 194.532333 \n", - "\n", - " WaterLevel:99l1:0 WaterLevel:99l1:44.5016 \\\n", - "1994-08-07 16:35:00.000 194.661499 194.581497 \n", - "1994-08-07 16:36:01.870 194.661575 194.581497 \n", - "1994-08-07 16:37:07.560 194.661667 194.581497 \n", - "1994-08-07 16:38:55.828 194.661865 194.581497 \n", - "1994-08-07 16:39:55.828 194.661911 194.581497 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 194.685715 194.607559 \n", - "1994-08-07 18:31:07.967 194.685608 194.607407 \n", - "1994-08-07 18:32:07.967 194.685516 194.607254 \n", - "1994-08-07 18:33:07.967 194.685074 194.607101 \n", - "1994-08-07 18:35:00.000 194.682861 194.606323 \n", - "\n", - " WaterLevel:9l1:0 WaterLevel:9l1:10 \\\n", - "1994-08-07 16:35:00.000 193.774994 193.764999 \n", - "1994-08-07 16:36:01.870 193.775070 193.765060 \n", - "1994-08-07 16:37:07.560 193.775391 193.765106 \n", - "1994-08-07 16:38:55.828 193.775894 193.765228 \n", - "1994-08-07 16:39:55.828 193.776154 193.765335 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 194.000839 193.999054 \n", - "1994-08-07 18:31:07.967 193.994766 193.992905 \n", - "1994-08-07 18:32:07.967 193.988892 193.986984 \n", - "1994-08-07 18:33:07.967 193.983109 193.981171 \n", - "1994-08-07 18:35:00.000 193.972641 193.970627 \n", - "\n", - " WaterLevel:Weir:119w1:0 WaterLevel:Weir:119w1:1 \\\n", - "1994-08-07 16:35:00.000 193.550003 188.479996 \n", - "1994-08-07 16:36:01.870 193.550003 188.479996 \n", - "1994-08-07 16:37:07.560 193.550034 188.479996 \n", - "1994-08-07 16:38:55.828 193.550079 188.479996 \n", - "1994-08-07 16:39:55.828 193.550095 188.479996 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 193.800369 188.479996 \n", - "1994-08-07 18:31:07.967 193.798798 188.479996 \n", - "1994-08-07 18:32:07.967 193.797256 188.479996 \n", - "1994-08-07 18:33:07.967 193.795715 188.479996 \n", - "1994-08-07 18:35:00.000 193.792877 188.479996 \n", - "\n", - " WaterLevel:Pump:115p1:0 \\\n", - "1994-08-07 16:35:00.000 193.304993 \n", - "1994-08-07 16:36:01.870 193.306061 \n", - "1994-08-07 16:37:07.560 193.307144 \n", - "1994-08-07 16:38:55.828 193.308884 \n", - "1994-08-07 16:39:55.828 193.309860 \n", - "... ... \n", - "1994-08-07 18:30:07.967 193.755829 \n", - "1994-08-07 18:31:07.967 193.756470 \n", - "1994-08-07 18:32:07.967 193.757172 \n", - "1994-08-07 18:33:07.967 193.757660 \n", - "1994-08-07 18:35:00.000 193.758667 \n", - "\n", - " WaterLevel:Pump:115p1:82.4281 \n", - "1994-08-07 16:35:00.000 195.005005 \n", - "1994-08-07 16:36:01.870 195.005005 \n", - "1994-08-07 16:37:07.560 195.005005 \n", - "1994-08-07 16:38:55.828 195.005005 \n", - "1994-08-07 16:39:55.828 195.005005 \n", - "... ... \n", - "1994-08-07 18:30:07.967 195.025726 \n", - "1994-08-07 18:31:07.967 195.025391 \n", - "1994-08-07 18:32:07.967 195.025070 \n", - "1994-08-07 18:33:07.967 195.024796 \n", - "1994-08-07 18:35:00.000 195.024307 \n", - "\n", - "[110 rows x 247 columns]" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nt.reaches.quantities[\"WaterLevel\"].to_dataframe()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "c2b70041", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
    WaterLevel:1WaterLevel:2WaterLevel:3WaterLevel:4WaterLevel:5WaterLevel:6WaterLevel:7WaterLevel:8WaterLevel:9WaterLevel:10...WaterLevel:46WaterLevel:55WaterLevel:58WaterLevel:116WaterLevel:117WaterLevel:118WaterLevel:115WaterLevel:119WaterLevel:120WaterLevel:Weir Outlet:119w1
    1994-08-07 16:35:00.000195.052994195.821503195.8815193.604996193.615005193.625000193.675003193.764999193.774994193.804993...194.074997195.005005193.554993193.550003193.585007193.585007193.304993193.550003193.550003193.779999
    1994-08-07 16:36:01.870195.052994195.821701195.8815193.604996193.615005193.625320193.675110193.765060193.775116193.804993...194.074997195.005005193.555023193.550064193.585831193.586807193.306061193.550003193.550003188.479996
    1994-08-07 16:37:07.560195.052994195.821640195.8815193.604996193.615005193.625671193.675369193.765106193.775513193.804993...194.074997195.005005193.555084193.550110193.586426193.588196193.307144193.550034193.550003188.479996
    1994-08-07 16:38:55.828195.052994195.821503195.8815193.604996193.615005193.626236193.675751193.765228193.776077193.804993...194.074997195.005005193.555191193.550156193.586960193.589706193.308884193.550079193.550003188.479996
    1994-08-07 16:39:55.828195.052994195.821503195.8815193.604996193.615005193.626556193.675949193.765335193.776352193.804993...194.074997195.005005193.555267193.550171193.587112193.590317193.309860193.550095193.550003188.479996
    ..................................................................
    1994-08-07 18:30:07.967195.119919195.822769195.8815193.884308193.931808193.961746193.977524193.999054194.010910194.023590...194.087036195.025726193.832489193.830322193.755844193.832626193.755829193.800369193.550003188.479996
    1994-08-07 18:31:07.967195.118607195.822769195.8815193.879333193.926086193.955582193.971191193.992905194.004776194.017578...194.086807195.025391193.828842193.826797193.756500193.828964193.756470193.798798193.550003188.479996
    1994-08-07 18:32:07.967195.117310195.822769195.8815193.874542193.920532193.949615193.965073193.986984193.998856194.011795...194.086609195.025070193.825348193.823456193.757156193.825485193.757172193.797256193.550003188.479996
    1994-08-07 18:33:07.967195.115753195.822769195.8815193.869873193.915131193.943802193.959091193.981171193.993011194.006042...194.086411195.024796193.822006193.820160193.757736193.822144193.757660193.795715193.550003188.479996
    1994-08-07 18:35:00.000195.112534195.822769195.8815193.861450193.905396193.933258193.948181193.970627193.982437193.995468...194.086029195.024307193.816025193.814346193.758698193.816177193.758667193.792877193.550003188.479996
    \n", - "

    110 rows × 119 columns

    \n", - "
    " - ], - "text/plain": [ - " WaterLevel:1 WaterLevel:2 WaterLevel:3 \\\n", - "1994-08-07 16:35:00.000 195.052994 195.821503 195.8815 \n", - "1994-08-07 16:36:01.870 195.052994 195.821701 195.8815 \n", - "1994-08-07 16:37:07.560 195.052994 195.821640 195.8815 \n", - "1994-08-07 16:38:55.828 195.052994 195.821503 195.8815 \n", - "1994-08-07 16:39:55.828 195.052994 195.821503 195.8815 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 195.119919 195.822769 195.8815 \n", - "1994-08-07 18:31:07.967 195.118607 195.822769 195.8815 \n", - "1994-08-07 18:32:07.967 195.117310 195.822769 195.8815 \n", - "1994-08-07 18:33:07.967 195.115753 195.822769 195.8815 \n", - "1994-08-07 18:35:00.000 195.112534 195.822769 195.8815 \n", - "\n", - " WaterLevel:4 WaterLevel:5 WaterLevel:6 \\\n", - "1994-08-07 16:35:00.000 193.604996 193.615005 193.625000 \n", - "1994-08-07 16:36:01.870 193.604996 193.615005 193.625320 \n", - "1994-08-07 16:37:07.560 193.604996 193.615005 193.625671 \n", - "1994-08-07 16:38:55.828 193.604996 193.615005 193.626236 \n", - "1994-08-07 16:39:55.828 193.604996 193.615005 193.626556 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 193.884308 193.931808 193.961746 \n", - "1994-08-07 18:31:07.967 193.879333 193.926086 193.955582 \n", - "1994-08-07 18:32:07.967 193.874542 193.920532 193.949615 \n", - "1994-08-07 18:33:07.967 193.869873 193.915131 193.943802 \n", - "1994-08-07 18:35:00.000 193.861450 193.905396 193.933258 \n", - "\n", - " WaterLevel:7 WaterLevel:8 WaterLevel:9 \\\n", - "1994-08-07 16:35:00.000 193.675003 193.764999 193.774994 \n", - "1994-08-07 16:36:01.870 193.675110 193.765060 193.775116 \n", - "1994-08-07 16:37:07.560 193.675369 193.765106 193.775513 \n", - "1994-08-07 16:38:55.828 193.675751 193.765228 193.776077 \n", - "1994-08-07 16:39:55.828 193.675949 193.765335 193.776352 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 193.977524 193.999054 194.010910 \n", - "1994-08-07 18:31:07.967 193.971191 193.992905 194.004776 \n", - "1994-08-07 18:32:07.967 193.965073 193.986984 193.998856 \n", - "1994-08-07 18:33:07.967 193.959091 193.981171 193.993011 \n", - "1994-08-07 18:35:00.000 193.948181 193.970627 193.982437 \n", - "\n", - " WaterLevel:10 ... WaterLevel:46 WaterLevel:55 \\\n", - "1994-08-07 16:35:00.000 193.804993 ... 194.074997 195.005005 \n", - "1994-08-07 16:36:01.870 193.804993 ... 194.074997 195.005005 \n", - "1994-08-07 16:37:07.560 193.804993 ... 194.074997 195.005005 \n", - "1994-08-07 16:38:55.828 193.804993 ... 194.074997 195.005005 \n", - "1994-08-07 16:39:55.828 193.804993 ... 194.074997 195.005005 \n", - "... ... ... ... ... \n", - "1994-08-07 18:30:07.967 194.023590 ... 194.087036 195.025726 \n", - "1994-08-07 18:31:07.967 194.017578 ... 194.086807 195.025391 \n", - "1994-08-07 18:32:07.967 194.011795 ... 194.086609 195.025070 \n", - "1994-08-07 18:33:07.967 194.006042 ... 194.086411 195.024796 \n", - "1994-08-07 18:35:00.000 193.995468 ... 194.086029 195.024307 \n", - "\n", - " WaterLevel:58 WaterLevel:116 WaterLevel:117 \\\n", - "1994-08-07 16:35:00.000 193.554993 193.550003 193.585007 \n", - "1994-08-07 16:36:01.870 193.555023 193.550064 193.585831 \n", - "1994-08-07 16:37:07.560 193.555084 193.550110 193.586426 \n", - "1994-08-07 16:38:55.828 193.555191 193.550156 193.586960 \n", - "1994-08-07 16:39:55.828 193.555267 193.550171 193.587112 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 193.832489 193.830322 193.755844 \n", - "1994-08-07 18:31:07.967 193.828842 193.826797 193.756500 \n", - "1994-08-07 18:32:07.967 193.825348 193.823456 193.757156 \n", - "1994-08-07 18:33:07.967 193.822006 193.820160 193.757736 \n", - "1994-08-07 18:35:00.000 193.816025 193.814346 193.758698 \n", - "\n", - " WaterLevel:118 WaterLevel:115 WaterLevel:119 \\\n", - "1994-08-07 16:35:00.000 193.585007 193.304993 193.550003 \n", - "1994-08-07 16:36:01.870 193.586807 193.306061 193.550003 \n", - "1994-08-07 16:37:07.560 193.588196 193.307144 193.550034 \n", - "1994-08-07 16:38:55.828 193.589706 193.308884 193.550079 \n", - "1994-08-07 16:39:55.828 193.590317 193.309860 193.550095 \n", - "... ... ... ... \n", - "1994-08-07 18:30:07.967 193.832626 193.755829 193.800369 \n", - "1994-08-07 18:31:07.967 193.828964 193.756470 193.798798 \n", - "1994-08-07 18:32:07.967 193.825485 193.757172 193.797256 \n", - "1994-08-07 18:33:07.967 193.822144 193.757660 193.795715 \n", - "1994-08-07 18:35:00.000 193.816177 193.758667 193.792877 \n", - "\n", - " WaterLevel:120 WaterLevel:Weir Outlet:119w1 \n", - "1994-08-07 16:35:00.000 193.550003 193.779999 \n", - "1994-08-07 16:36:01.870 193.550003 188.479996 \n", - "1994-08-07 16:37:07.560 193.550003 188.479996 \n", - "1994-08-07 16:38:55.828 193.550003 188.479996 \n", - "1994-08-07 16:39:55.828 193.550003 188.479996 \n", - "... ... ... \n", - "1994-08-07 18:30:07.967 193.550003 188.479996 \n", - "1994-08-07 18:31:07.967 193.550003 188.479996 \n", - "1994-08-07 18:32:07.967 193.550003 188.479996 \n", - "1994-08-07 18:33:07.967 193.550003 188.479996 \n", - "1994-08-07 18:35:00.000 193.550003 188.479996 \n", - "\n", - "[110 rows x 119 columns]" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nt.nodes.quantities[\"WaterLevel\"].to_dataframe()" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "92b249fe", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "<ResultGridPoint>\n", - " \n", - "
    Attributes (5)
    • reach_name: 105l1
    • chainage: 0.0
    • xcoord: -687516.5991821289
    • ycoord: -1056363.7993774414
    • bottom_level: 197.35000610351562
    Quantities (1)
    • Water level (m)
    Derived Quantities (0)
      " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nt.reaches[\"105l1\"][\"0.000\"]" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "0a4ca2bf", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[, , ]" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nt.reaches[\"105l1\"].gridpoints" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "138e3ef4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['WaterLevel']" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nt.reaches[\"102l1\"][\"10.937\"].quantities" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "8abc73b4", - "metadata": {}, - "outputs": [], - "source": [ - "temperature = ms.PointModelResult(datapath, item=\"Temperature\", name=\"Temp\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "51fb4d18", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "94025330", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
      \n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
      TemperatureWater Level
      2015-01-01 01:00:003.140.1400
      2015-01-01 02:00:003.140.1370
      2015-01-01 03:00:003.140.1809
      2015-01-01 04:00:003.140.2030
      2015-01-01 05:00:003.140.1750
      .........
      2020-09-27 20:00:003.140.4070
      2020-09-27 21:00:003.140.3790
      2020-09-27 22:00:003.140.3650
      2020-09-27 23:00:003.140.3790
      2020-09-28 00:00:003.140.4140
      \n", - "

      50328 rows × 2 columns

      \n", - "
      " - ], - "text/plain": [ - " Temperature Water Level\n", - "2015-01-01 01:00:00 3.14 0.1400\n", - "2015-01-01 02:00:00 3.14 0.1370\n", - "2015-01-01 03:00:00 3.14 0.1809\n", - "2015-01-01 04:00:00 3.14 0.2030\n", - "2015-01-01 05:00:00 3.14 0.1750\n", - "... ... ...\n", - "2020-09-27 20:00:00 3.14 0.4070\n", - "2020-09-27 21:00:00 3.14 0.3790\n", - "2020-09-27 22:00:00 3.14 0.3650\n", - "2020-09-27 23:00:00 3.14 0.3790\n", - "2020-09-28 00:00:00 3.14 0.4140\n", - "\n", - "[50328 rows x 2 columns]" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ds.to_dataframe()" - ] } ], "metadata": { From 74ce92e50404950fb1d67b1daa0fc3bb3401d5b6 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 15:40:10 +0100 Subject: [PATCH 13/17] Add NetworkModelResult to init --- src/modelskill/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modelskill/__init__.py b/src/modelskill/__init__.py index 0b3ce52f2..a1590fb33 100644 --- a/src/modelskill/__init__.py +++ b/src/modelskill/__init__.py @@ -39,6 +39,7 @@ GridModelResult, DfsuModelResult, DummyModelResult, + NetworkModelResult, ) from .obs import ( observation, @@ -94,6 +95,7 @@ def load(filename: Union[str, Path]) -> Comparer | ComparerCollection: "GridModelResult", "DfsuModelResult", "DummyModelResult", + "NetworkModelResult", "observation", "PointObservation", "TrackObservation", From 7a4edf743639845c21427538fb9738f0c1c6f069 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 16:31:38 +0100 Subject: [PATCH 14/17] Including basic tests --- src/modelskill/timeseries/_point.py | 7 +++- tests/model/test_network.py | 52 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/model/test_network.py diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index 927cd3910..9b8b9bc2c 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -7,6 +7,7 @@ import pandas as pd import xarray as xr +import warnings import mikeio import mikeio1d @@ -201,7 +202,7 @@ def eum_name_to_res1d(name: str) -> str: if Path(data).suffix == ".res1d": data = mikeio1d.open(data) else: - raise ValueError("Invalid path to network") + raise ValueError("Input data must have '.res1d' file extension.") by_node = node is not None by_reach = reach is not None @@ -210,6 +211,10 @@ def eum_name_to_res1d(name: str) -> str: if by_node and not by_reach: location = data.nodes[str(node)] + if with_chainage or with_index: + warnings.warn( + "'chainage' or 'gridpoint' were passed along with 'node'. These are only relevant when passed with 'reach', so they will be ignored." + ) elif by_reach and not by_node: location = data.reaches[reach] diff --git a/tests/model/test_network.py b/tests/model/test_network.py new file mode 100644 index 000000000..2fa5e1aca --- /dev/null +++ b/tests/model/test_network.py @@ -0,0 +1,52 @@ +import pytest +import mikeio1d + +import numpy as np +import pandas as pd +import modelskill as ms + +parse_network = ms.timeseries._parse_network_input + + +@pytest.fixture +def res1d_datapath() -> str: + return "tests/testdata/network.res1d" + + +@pytest.fixture +def res1d_object(res1d_datapath) -> mikeio1d.Res1D: + return mikeio1d.open(res1d_datapath) + + +def test_read_quantity_by_node(res1d_object): + series = parse_network(res1d_object, eum_name="Water Level", node=3) + df = res1d_object.read() + assert isinstance(series, pd.Series) + assert series.name == "WaterLevel" + np.testing.assert_allclose(df["WaterLevel:3"].values, series.values) + + +@pytest.mark.parametrize( + "network_kwargs", + [ + dict(gridpoint="end"), + dict(gridpoint=2), + dict(chainage=47.683), + dict(chainage="47.683"), + ], +) +def test_read_quantity_by_reach(res1d_object, network_kwargs): + series = parse_network( + res1d_object, eum_name="Water Level", reach="100l1", **network_kwargs + ) + df = res1d_object.read() + assert isinstance(series, pd.Series) + assert series.name == "WaterLevel" + np.testing.assert_allclose(df["WaterLevel:100l1:47.6827"].values, series.values) + + +def test_node_and_reach_as_arguments(res1d_object): + with pytest.raises( + ValueError, match="Item can only be specified either by node or by reach" + ): + parse_network(res1d_object, eum_name="Water Level", reach="100l1", node=2) From 09a5143775b6915bb37071d6b75d130172b1d6e7 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 16:59:31 +0100 Subject: [PATCH 15/17] Commit network test file --- tests/testdata/network.res1d | Bin 0 -> 668538 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/testdata/network.res1d diff --git a/tests/testdata/network.res1d b/tests/testdata/network.res1d new file mode 100644 index 0000000000000000000000000000000000000000..45a661f6ec6a5733bcb42ac91ada30d3b2077732 GIT binary patch literal 668538 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 literal 0 HcmV?d00001 From c40b645885560b3b6028a5b87b865f34ade56eaf Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 17:13:04 +0100 Subject: [PATCH 16/17] Clean notebook --- notebooks/Network_comparison.ipynb | 38 ++++++++++-------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/notebooks/Network_comparison.ipynb b/notebooks/Network_comparison.ipynb index 7ddf47223..e8d7cea6d 100644 --- a/notebooks/Network_comparison.ipynb +++ b/notebooks/Network_comparison.ipynb @@ -13,24 +13,6 @@ "import numpy as np" ] }, - { - "cell_type": "code", - "execution_count": 2, - "id": "2e6fe4e5", - "metadata": {}, - "outputs": [], - "source": [ - "# We fabricate an observation set to try the current workflow\n", - "np.random.seed(42)\n", - "\n", - "observations = pd.read_parquet('../tests/testdata/network_res1d.parquet')\n", - "observations = observations + np.random.normal(0, 10, observations.shape)\n", - "# Arbitrarily selecting 2 columns of WaterLevel that will be used as observations\n", - "relevant_columns = [col for col in observations.columns if \"WaterLevel\" in col][8:10]\n", - "observations = observations.loc[:, relevant_columns].rename(columns=lambda x: \"sensor_\" + x.split(\":\")[1])\n", - "observations = observations.resample(\"1min\").mean()" - ] - }, { "cell_type": "markdown", "id": "c2cc9f94", @@ -41,7 +23,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "c88c8a87", "metadata": {}, "outputs": [], @@ -50,8 +32,16 @@ "path_to_res1d = '../tests/testdata/network.res1d'\n", "nt = m1d.open(path_to_res1d)\n", "\n", - "# - Loading observations (in this cases, they are loaded from the cell above)\n", - "# observations = pd.read_csv(...)" + "# Loading observations\n", + "# - We fabricate an observation set to try the current workflow\n", + "np.random.seed(42)\n", + "\n", + "observations = nt.read()\n", + "observations = observations + np.random.normal(0, 10, observations.shape)\n", + "# Arbitrarily selecting 2 columns of WaterLevel that will be used as observations\n", + "relevant_columns = [col for col in observations.columns if \"WaterLevel\" in col][8:10]\n", + "observations = observations.loc[:, relevant_columns].rename(columns=lambda x: \"sensor_\" + x.split(\":\")[1])\n", + "observations = observations.resample(\"1min\").mean()" ] }, { @@ -289,9 +279,7 @@ "id": "a59a1d87", "metadata": {}, "source": [ - "#### Thoughts\n", - "- It would be benefitial to have a better way to specify the item in the network file\n", - "- We can actually omit the `NetworkPointObservation` since observations are scarce and typically stored in csv files representing a dataframe" + "- Multiple observations with one result" ] }, { @@ -404,7 +392,7 @@ "id": "55f42b62", "metadata": {}, "source": [ - "### Multiple models" + "- Multiple models with one observation" ] }, { From eda9dad0e562a5e87f2ee7f22704b39e94a19780 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Wed, 14 Jan 2026 17:37:02 +0100 Subject: [PATCH 17/17] Allowing empty variable if network location has unique quantity --- notebooks/Network_comparison.ipynb | 66 +++++++++++++++++------------ src/modelskill/model/network.py | 5 ++- src/modelskill/timeseries/_point.py | 25 +++++++---- tests/model/test_network.py | 6 +-- 4 files changed, 63 insertions(+), 39 deletions(-) diff --git a/notebooks/Network_comparison.ipynb b/notebooks/Network_comparison.ipynb index e8d7cea6d..a71aa199d 100644 --- a/notebooks/Network_comparison.ipynb +++ b/notebooks/Network_comparison.ipynb @@ -9,7 +9,6 @@ "source": [ "import modelskill as ms\n", "import mikeio1d as m1d\n", - "import pandas as pd\n", "import numpy as np" ] }, @@ -23,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "c88c8a87", "metadata": {}, "outputs": [], @@ -46,7 +45,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "id": "568f6f18", "metadata": {}, "outputs": [ @@ -131,7 +130,7 @@ "sensor_10 -0.003818 " ] }, - "execution_count": 4, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -181,7 +180,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "7607223b", "metadata": {}, "outputs": [ @@ -261,7 +260,7 @@ "sensor_9 0.008068 " ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -284,7 +283,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "id": "80271095", "metadata": {}, "outputs": [ @@ -369,7 +368,7 @@ "sensor_10 -0.003818 " ] }, - "execution_count": 6, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -397,7 +396,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "9ee90ffe", "metadata": {}, "outputs": [ @@ -447,7 +446,7 @@ " \n", " \n", " \n", - " wl 1\n", + " model 1\n", " sensor_9\n", " 110\n", " 0.743778\n", @@ -459,7 +458,7 @@ " 0.008068\n", " \n", " \n", - " wl 2\n", + " model 2\n", " sensor_9\n", " 110\n", " 2.248587\n", @@ -471,7 +470,19 @@ " -0.044767\n", " \n", " \n", - " wl 3\n", + " model 3\n", + " sensor_9\n", + " 110\n", + " 0.808813\n", + " 9.240242\n", + " 9.204776\n", + " 7.772271\n", + " 0.212348\n", + " 0.047603\n", + " -0.007633\n", + " \n", + " \n", + " model 4\n", " sensor_9\n", " 110\n", " 0.808813\n", @@ -487,20 +498,22 @@ "" ], "text/plain": [ - " n bias rmse urmse mae cc \\\n", - "model observation \n", - "wl 1 sensor_9 110 0.743778 9.167965 9.137744 7.701389 0.181837 \n", - "wl 2 sensor_9 110 2.248587 9.408963 9.136325 7.882746 0.205237 \n", - "wl 3 sensor_9 110 0.808813 9.240242 9.204776 7.772271 0.212348 \n", + " n bias rmse urmse mae cc \\\n", + "model observation \n", + "model 1 sensor_9 110 0.743778 9.167965 9.137744 7.701389 0.181837 \n", + "model 2 sensor_9 110 2.248587 9.408963 9.136325 7.882746 0.205237 \n", + "model 3 sensor_9 110 0.808813 9.240242 9.204776 7.772271 0.212348 \n", + "model 4 sensor_9 110 0.808813 9.240242 9.204776 7.772271 0.212348 \n", "\n", - " si r2 \n", - "model observation \n", - "wl 1 sensor_9 0.047257 0.008068 \n", - "wl 2 sensor_9 0.047249 -0.044767 \n", - "wl 3 sensor_9 0.047603 -0.007633 " + " si r2 \n", + "model observation \n", + "model 1 sensor_9 0.047257 0.008068 \n", + "model 2 sensor_9 0.047249 -0.044767 \n", + "model 3 sensor_9 0.047603 -0.007633 \n", + "model 4 sensor_9 0.047603 -0.007633 " ] }, - "execution_count": 7, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -508,9 +521,10 @@ "source": [ "quantity = ms.Quantity(\"Water Level\", unit=\"m3_per_sec\")\n", "models = [\n", - " ms.NetworkModelResult(path_to_res1d, quantity, node=7, name=\"wl 1\"),\n", - " ms.NetworkModelResult(path_to_res1d, quantity, reach=\"100l1\", gridpoint=\"start\", name=\"wl 2\"),\n", - " ms.NetworkModelResult(path_to_res1d, quantity, reach=\"54l1\", gridpoint=0, name=\"wl 3\")\n", + " ms.NetworkModelResult(path_to_res1d, quantity, node=7, name=\"model 1\"),\n", + " ms.NetworkModelResult(path_to_res1d, quantity, reach=\"100l1\", gridpoint=\"start\", name=\"model 2\"),\n", + " ms.NetworkModelResult(path_to_res1d, quantity, reach=\"54l1\", gridpoint=0, name=\"model 3\"),\n", + " ms.NetworkModelResult(path_to_res1d, reach=\"54l1\", gridpoint=0, name=\"model 4\")\n", "]\n", "\n", "obs1 = ms.PointObservation(observations, quantity=quantity, item=\"sensor_9\")\n", diff --git a/src/modelskill/model/network.py b/src/modelskill/model/network.py index 692db11eb..d481c252f 100644 --- a/src/modelskill/model/network.py +++ b/src/modelskill/model/network.py @@ -38,7 +38,7 @@ class NetworkModelResult(PointModelResult): def __init__( self, data: Res1D | str, - quantity: str | Quantity, + quantity: Optional[str | Quantity] = None, *, reach: Optional[str] = None, node: Optional[int] = None, @@ -50,9 +50,10 @@ def __init__( if isinstance(quantity, str): quantity = Quantity.from_mikeio_eum_name(quantity) + variable = quantity.name if isinstance(quantity, Quantity) else None data = _parse_network_input( data, - eum_name=quantity.name, + variable=variable, reach=reach, node=node, chainage=chainage, diff --git a/src/modelskill/timeseries/_point.py b/src/modelskill/timeseries/_point.py index 9b8b9bc2c..b5aca4149 100644 --- a/src/modelskill/timeseries/_point.py +++ b/src/modelskill/timeseries/_point.py @@ -188,14 +188,14 @@ def _parse_point_input( def _parse_network_input( data: mikeio1d.Res1D | str, - eum_name: str, + variable: Optional[str] = None, *, node: Optional[int] = None, reach: Optional[str] = None, chainage: Optional[str | float] = None, gridpoint: Optional[int | Literal["start", "end"]] = None, ) -> pd.Series: - def eum_name_to_res1d(name: str) -> str: + def variable_name_to_res1d(name: str) -> str: return name.replace(" ", "").replace("_", "") if isinstance(data, (str, Path)): @@ -213,14 +213,14 @@ def eum_name_to_res1d(name: str) -> str: location = data.nodes[str(node)] if with_chainage or with_index: warnings.warn( - "'chainage' or 'gridpoint' were passed along with 'node'. These are only relevant when passed with 'reach', so they will be ignored." + "'chainage' or 'gridpoint' are only relevant when passed with 'reach' but they were passed with 'node', so they will be ignored." ) elif by_reach and not by_node: location = data.reaches[reach] if with_index == with_chainage: raise ValueError( - "Items accessed by chainage must be specified either by chainage or by index, not both" + "Locations accessed by chainage must be specified either by chainage or by index, not both." ) if with_index and not with_chainage: @@ -231,11 +231,20 @@ def eum_name_to_res1d(name: str) -> str: location = location[chainage] else: - raise ValueError("Item can only be specified either by node or by reach") + raise ValueError( + "A network location must be specified either by node or by reach." + ) - # After filtering by node or by reach and chainage, a location will only - # have unique quantities - res1d_name = eum_name_to_res1d(eum_name) + if variable is None: + if len(location.quantities) != 1: + raise ValueError( + f"The network location does not have a unique quantity: {location.quantities}, in such case 'variable' argument cannot be None" + ) + res1d_name = location.quantities[0] + else: + # After filtering by node or by reach and chainage, a location will only + # have unique quantities + res1d_name = variable_name_to_res1d(variable) df = location.to_dataframe() if df.shape[1] == 1: colname = df.columns[0] diff --git a/tests/model/test_network.py b/tests/model/test_network.py index 2fa5e1aca..92284c800 100644 --- a/tests/model/test_network.py +++ b/tests/model/test_network.py @@ -19,7 +19,7 @@ def res1d_object(res1d_datapath) -> mikeio1d.Res1D: def test_read_quantity_by_node(res1d_object): - series = parse_network(res1d_object, eum_name="Water Level", node=3) + series = parse_network(res1d_object, variable="Water Level", node=3) df = res1d_object.read() assert isinstance(series, pd.Series) assert series.name == "WaterLevel" @@ -37,7 +37,7 @@ def test_read_quantity_by_node(res1d_object): ) def test_read_quantity_by_reach(res1d_object, network_kwargs): series = parse_network( - res1d_object, eum_name="Water Level", reach="100l1", **network_kwargs + res1d_object, variable="Water Level", reach="100l1", **network_kwargs ) df = res1d_object.read() assert isinstance(series, pd.Series) @@ -49,4 +49,4 @@ def test_node_and_reach_as_arguments(res1d_object): with pytest.raises( ValueError, match="Item can only be specified either by node or by reach" ): - parse_network(res1d_object, eum_name="Water Level", reach="100l1", node=2) + parse_network(res1d_object, variable="Water Level", reach="100l1", node=2)