From d5f514485d69081a943f45618f0b8c3612056a96 Mon Sep 17 00:00:00 2001 From: deltamarnix Date: Wed, 20 May 2026 09:59:00 +0200 Subject: [PATCH 01/27] timflow works `from timflow import steady as timml` --- .vscode/launch.json | 16 ++ README.md | 15 +- docs/developer.qmd | 7 +- docs/index.qmd | 5 +- docs/install.qmd | 8 +- docs/tutorial_Rijsenhout.qmd | 2 +- gistim/__main__.py | 4 - gistim/compute.py | 8 +- pixi.lock | 219 +++++------------------ pixi.toml | 5 +- plugin/qgistim/README.txt | 8 +- plugin/qgistim/core/elements/aquifer.py | 2 +- plugin/qgistim/core/formatting.py | 4 +- plugin/qgistim/core/server_handler.py | 2 +- plugin/qgistim/widgets/install_dialog.py | 15 +- plugin/qgistim/widgets/tim_widget.py | 2 +- pyproject.toml | 4 +- scripts/write_backend_versions.py | 6 +- 18 files changed, 95 insertions(+), 237 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3f911fd --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Compute gistim server", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/gistim/__main__.py", + "console": "integratedTerminal", + "args": [ + "compute", + "${workspaceFolder}/testdata/test.json" + ] + } + ] +} diff --git a/README.md b/README.md index 0f1572e..17c1230 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,14 @@ QGIS-Tim is an open source project for multi-layer groundwater flow simulations. QGIS-Tim provides a link between QGIS and the open source analytic -element method software: [TimML (steady-state)](https://github.com/mbakker7/timml) -and [TTim (transient)](https://github.com/mbakker7/ttim). +element method software: [timflow](https://github.com/timflow-org/timflow). The benefit of the analytic element method (AEM) is that no grid or time-stepping is required. Geohydrological features are represented by points, lines, and polygons. QGIS-Tim stores these features in a [GeoPackage](https://www.geopackage.org/). -QGIS-Tim consists of a "front-end" (the QGIS plugin) and a "back-end" (the TimML and TTim server). +QGIS-Tim consists of a "front-end" (the QGIS plugin) and a "back-end" (the timflow server). The front-end is a QGIS plugin that provides a limited graphical interface to setup model input, visualize, and analyze model input. The back-end is a Python package. The plugin converts the GeoPackage content to a JSON file or a Python script. The back-end reads the JSON file, does the @@ -48,19 +47,19 @@ Download and install a recent version of QGIS (>=3.28): This will add an icon to the toolbar(s). By clicking the icon, the plugin is started. -### Install the TimML and TTim server +### Install the timflow server With the plugin installed, we can already define model input and convert it to Python scripts or JSON files. -To run TimML and TTim computations directly from QGIS, we need to install a server program which contains TimML and TTim. +To run timflow computations directly from QGIS, we need to install a server program which contains timflow. 1. Start the QGIS-Tim plugin by clicking the QGIS-Tim icon in the toolbar. -2. Find and click the "Install TimML and TTim server" button at the bottom of the plugin window. +2. Find and click the "Install timflow server" button at the bottom of the plugin window. 3. Click the "Install latest release from GitHub" button to download and install the server program. Specific releases can also be manually downloaded from the [GitHub Releases page](https://github.com/Deltares/QGIS-Tim/releases): 1. Download the gistim ZIP file for your platform: Windows, macOS, or Linux. -2. Find and click the "Install TimML and TTim server" button at the bottom of the plugin window. +2. Find and click the "Install timflow server" button at the bottom of the plugin window. 3. Set the path to the downloaded ZIP file in the "Install from ZIP file" section. 4. Click the "Install" button. @@ -73,7 +72,7 @@ This repository uses [pixi](https://pixi.sh) to install required dependencies. 3. Call `pixi shell -e dev` to activate the development environment. 4. Call `pixi run install-qgis-plugins` to install this plugin and some debug tools inside of the included QGIS installation. 5. Call `pixi run install-backend` to install the backend as a symlink between the pyinstaller dist folder and %APPDATA%/qgis-tim. -6. Call `pixi run qgis` to start QGIS. The plugin should be installed and enabled and you should be able to see the versions of timml and ttim. +6. Call `pixi run qgis` to start QGIS. The plugin should be installed and enabled and you should be able to see the versions of timflow. After making a change to the plugin, you can reload the plugin with the [plugin reloader](https://plugins.qgis.org/plugins/plugin_reloader/). For debugging we are still encountering an [issue](https://github.com/nextgis/qgis_devtools/issues/10) with the [QGIS DevTools plugin](https://plugins.qgis.org/plugins/devtools/). diff --git a/docs/developer.qmd b/docs/developer.qmd index 19662c8..6e1d360 100644 --- a/docs/developer.qmd +++ b/docs/developer.qmd @@ -8,14 +8,11 @@ QGIS-Tim uses pixi to manage installing dependencies and run common tasks. Follow the instructions on the [Getting Started page](https://pixi.sh/). ### PyInstaller -To build the TimML and TTim server application with PyInstaller, run `pixi run build-backend` +To build the timflow server application with PyInstaller, run `pixi run build-backend` This creates a built PyInstaller application in `./dist/gistim`. -Run `pixi run zip-backend` to create a ZIP file of the PyInstaller application. -Run `pixi run zip-plugin` to create a ZIP file of the QGIS plugin that can be installed in QGIS. - -To test the created ZIP files: Install the QGIS from the ZIP file, start the QGIS plugin and try to install the ZIP file via the "Install TimML and TTim server" button. +Run `pixi run -e dev install-backend` to create a symlink between %APPDATA%/qgistim and ./dist/gistim. ## Creating new release diff --git a/docs/index.qmd b/docs/index.qmd index ad3805f..7dce898 100644 --- a/docs/index.qmd +++ b/docs/index.qmd @@ -10,8 +10,7 @@ listing: QGIS-Tim is an open source project for multi-layer groundwater flow simulations. QGIS-Tim provides a link between QGIS and the open source analytic -element method software: [TimML (steady-state)](https://github.com/mbakker7/timml) -and [TTim (transient)](https://github.com/mbakker7/ttim). +element method software: [timflow](https://github.com/timflow-org/timflow). The benefit of the analytic element method (AEM) is that no grid or time-stepping is required. Geohydrological features are represented by points, @@ -21,5 +20,5 @@ lines, and polygons. QGIS-Tim stores these features in a QGIS-Tim consists of a "front-end" and a "back-end". The front-end is a QGIS plugin that provides a limited graphical interface to setup model input, visualize, and analyze model input. The back-end is a Python package. It reads -the contents of the GeoPackage and transforms it into a TimML or TTim model, +the contents of the GeoPackage and transforms it into a timflow model, computes a result, and writes it to a file that the QGIS plugin loads. diff --git a/docs/install.qmd b/docs/install.qmd index dc97fda..3547bdd 100644 --- a/docs/install.qmd +++ b/docs/install.qmd @@ -35,14 +35,14 @@ This will add an icon to the toolbar(s). ![](figures/tutorial/button-Qgis-tim.pn By clicking the icon, the plugin is started. -## 3. Install the TimML and TTim server +## 3. Install the timflow server With the plugin installed, we can already define model input and convert it to Python scripts or JSON files. -To run TimML and TTim computations directly from QGIS, we need to install a server program which contains TimML and TTim. +To run timflow computations directly from QGIS, we need to install a server program which contains timflow. ### Method A: Install from GitHub (requires internet connection) 1. Start the QGIS-Tim plugin by clicking the QGIS-Tim icon in the toolbar. -1. Find and click the "Install TimML and TTim server" button at the bottom of the plugin window. +1. Find and click the "Install timflow server" button at the bottom of the plugin window. 1. Click the "Install latest release from GitHub" button to download and install the server program. ### Method B: Install from ZIP file @@ -51,6 +51,6 @@ Specific releases can also be manually downloaded from the [GitHub Releases page 1. Download the gistim ZIP file for your platform: Windows, macOS, or Linux. 1. Start the QGIS-Tim plugin by clicking the QGIS-Tim icon in the toolbar. -1. Find and click the "Install TimML and TTim server" button at the bottom of the plugin window. +1. Find and click the "Install timflow server" button at the bottom of the plugin window. 1. Set the path to the downloaded ZIP file in the "Install from ZIP file" section. 1. Click the "Install" button. diff --git a/docs/tutorial_Rijsenhout.qmd b/docs/tutorial_Rijsenhout.qmd index 8d83551..b5f9e97 100644 --- a/docs/tutorial_Rijsenhout.qmd +++ b/docs/tutorial_Rijsenhout.qmd @@ -13,7 +13,7 @@ In this tutorial, you will learn how to: - install and use the QGIS-Tim plugin; - use the basic of QGIS for pre- and postprocessing of TIM; -- create several steady state models (TimML) and a transient model (TTim); +- create several steady state models and a transient model; - analyse the results; - export your model to a Python script. diff --git a/gistim/__main__.py b/gistim/__main__.py index 2c4a053..77f8830 100644 --- a/gistim/__main__.py +++ b/gistim/__main__.py @@ -5,10 +5,6 @@ from contextlib import contextmanager, redirect_stderr, redirect_stdout from os import devnull -# Make sure we explicitly import besselaesnumba for pyinstaller. -# It's a dynamic import inside of timml. -from timml.besselaesnumba import besselaesnumba # noqa: F401 - import gistim.compute diff --git a/gistim/compute.py b/gistim/compute.py index 1c93154..6e3ab2b 100644 --- a/gistim/compute.py +++ b/gistim/compute.py @@ -6,9 +6,9 @@ import numpy as np import pandas as pd -import timml -import ttim import xarray as xr +from timflow import steady as timml +from timflow import transient as ttim from gistim.geopackage import CoordinateReferenceSystem, write_geopackage from gistim.netcdf import write_raster, write_ugrid @@ -96,7 +96,7 @@ def _( y = np.arange(ymax, ymin, -spacing) - 0.5 * spacing head = model.headgrid(xg=x, yg=y) nlayer = model.aq.find_aquifer_data(x[0], y[0]).naq - layer = [i for i in range(nlayer)] + layer = list(range(nlayer)) return xr.DataArray( data=head, name="head", @@ -133,7 +133,7 @@ def _( head = model.headgrid(xg=x, yg=y, t=time) # Other coordinates - layer = [i for i in range(nlayer)] + layer = list(range(nlayer)) time = pd.to_datetime(start_date) + pd.to_timedelta(time, "D") return xr.DataArray( data=head, diff --git a/pixi.lock b/pixi.lock index 4b21328..e227abe 100644 --- a/pixi.lock +++ b/pixi.lock @@ -44,19 +44,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/09/7d/af933f0f6e0767995b4e2d705a0665e454d1c19402aa7e895de3951ebb04/scipy-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/0b/43/a81f20050a3115b57d62c8e781446949512eac36690dc384ccea65ff4cc1/fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/f1/bbecd2f867b97abebe0f9b53d750f862251b40337e061b36676ded3d920f/pandas-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/44/0b/0615dbedb98f5b32a35a53290fbdc6e22306968109278d7e58df82d7a9f6/numba-0.65.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/46/27/5799b020e4cdfb25a7c951c06a96397c135efcdc21b78d853bbd9c814c7d/llvmlite-0.47.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/79/db/e28c1b83e3680740aa78925f5fb2ae4d16207207419ad75ea9fe604f8676/matplotlib-3.10.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cf/c5/9fcb7e0e69cef59cf10c746b84f7d58b08bc66a6b7d459783c5a4f6101a6/numpy-2.4.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl @@ -89,18 +84,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/01/88/a8952b6d5c21e74cbf158515b779666f692846502623e9e3c39d8e8ba25f/llvmlite-0.47.0.tar.gz - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/16/b5c76b838fd9bf6ce84d3a53346b8874ec05c5f0040d75ef2c320100cd2a/pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/50/965308c703f085f225db2886813b27e015b8b3438c350b22dd65b52c2a2c/fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/4c/8c/290f021104741fea63769c31494f5324c0cd249bf536a65a4350767b1f22/matplotlib-3.10.9-cp311-cp311-macosx_10_12_x86_64.whl - pypi: https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/df/75/b4ce781849931fef6fd529afa6b63711d5a733065722d0c3e2724af9e40a/scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl @@ -137,22 +127,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_36.conda - pypi: https://files.pythonhosted.org/packages/08/60/defa5e69641db890a63be281f41345f4c33b157824eaf0b9fad3e08b0dcb/fonttools-4.63.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/0d/271aace3342157c64700c9ff4c59c7b392f3dbab393692e8db6fbe7ab96c/matplotlib-3.10.9-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/da/0d1df507cf574b3f224ccc3d45244c9a1d732c81dcb26b1e8a766ae271a8/scipy-1.17.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/50/59227d06bdc96e23322713c381af4e77420949d8cd8a042c79e0043096cc/llvmlite-0.47.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/63/05d193dbb4b5eec1eca73822d80da98b511f8328ad4ae3ca4caf0f4db91d/numpy-2.4.4-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/bd/9a/af61ec03b3116c161fd7a06b9e8a265729a8718458333e8ffbb06d9a3978/numba-0.65.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/be/6c/28f17390b62b8f2f520e2915095b3c94d88681ecf0041e75389d9667f202/kiwisolver-1.5.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/62/c321f13b5ba1819fc8dca456c7fce578da2dcfecff1abbf0eaddf8406c0f/pandas-3.0.3-cp311-cp311-win_amd64.whl @@ -189,19 +174,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/09/7d/af933f0f6e0767995b4e2d705a0665e454d1c19402aa7e895de3951ebb04/scipy-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/0b/43/a81f20050a3115b57d62c8e781446949512eac36690dc384ccea65ff4cc1/fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/f1/bbecd2f867b97abebe0f9b53d750f862251b40337e061b36676ded3d920f/pandas-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/44/0b/0615dbedb98f5b32a35a53290fbdc6e22306968109278d7e58df82d7a9f6/numba-0.65.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/46/27/5799b020e4cdfb25a7c951c06a96397c135efcdc21b78d853bbd9c814c7d/llvmlite-0.47.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/79/db/e28c1b83e3680740aa78925f5fb2ae4d16207207419ad75ea9fe604f8676/matplotlib-3.10.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cf/c5/9fcb7e0e69cef59cf10c746b84f7d58b08bc66a6b7d459783c5a4f6101a6/numpy-2.4.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl @@ -226,18 +206,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/01/88/a8952b6d5c21e74cbf158515b779666f692846502623e9e3c39d8e8ba25f/llvmlite-0.47.0.tar.gz - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/16/b5c76b838fd9bf6ce84d3a53346b8874ec05c5f0040d75ef2c320100cd2a/pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/50/965308c703f085f225db2886813b27e015b8b3438c350b22dd65b52c2a2c/fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/4c/8c/290f021104741fea63769c31494f5324c0cd249bf536a65a4350767b1f22/matplotlib-3.10.9-cp311-cp311-macosx_10_12_x86_64.whl - pypi: https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/df/75/b4ce781849931fef6fd529afa6b63711d5a733065722d0c3e2724af9e40a/scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl - pypi: https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl @@ -263,22 +238,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_36.conda - pypi: https://files.pythonhosted.org/packages/08/60/defa5e69641db890a63be281f41345f4c33b157824eaf0b9fad3e08b0dcb/fonttools-4.63.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/0d/271aace3342157c64700c9ff4c59c7b392f3dbab393692e8db6fbe7ab96c/matplotlib-3.10.9-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/da/0d1df507cf574b3f224ccc3d45244c9a1d732c81dcb26b1e8a766ae271a8/scipy-1.17.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/50/59227d06bdc96e23322713c381af4e77420949d8cd8a042c79e0043096cc/llvmlite-0.47.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/63/05d193dbb4b5eec1eca73822d80da98b511f8328ad4ae3ca4caf0f4db91d/numpy-2.4.4-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/bd/9a/af61ec03b3116c161fd7a06b9e8a265729a8718458333e8ffbb06d9a3978/numba-0.65.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/be/6c/28f17390b62b8f2f520e2915095b3c94d88681ecf0041e75389d9667f202/kiwisolver-1.5.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl @@ -652,22 +622,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - pypi: https://files.pythonhosted.org/packages/09/7d/af933f0f6e0767995b4e2d705a0665e454d1c19402aa7e895de3951ebb04/scipy-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/0b/43/a81f20050a3115b57d62c8e781446949512eac36690dc384ccea65ff4cc1/fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/26/30/5b1a619941bb458d1d3768377254d5d9e9965405daa2bd75f4317eae86f0/qgis_plugin_manager-1.7.5.tar.gz - pypi: https://files.pythonhosted.org/packages/32/f1/bbecd2f867b97abebe0f9b53d750f862251b40337e061b36676ded3d920f/pandas-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/33/d5/9b8482ed572be40d51c3fcbb87451e446e56b5e19487cd60340b8ef51eb4/PyQt5_stubs-5.15.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/44/0b/0615dbedb98f5b32a35a53290fbdc6e22306968109278d7e58df82d7a9f6/numba-0.65.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/46/27/5799b020e4cdfb25a7c951c06a96397c135efcdc21b78d853bbd9c814c7d/llvmlite-0.47.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/79/db/e28c1b83e3680740aa78925f5fb2ae4d16207207419ad75ea9fe604f8676/matplotlib-3.10.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/97/e0ab7241e2b9f35e03d288f2bb1304c1a1d47219601d0df971a851f9db38/qgis_stubs-0.2.0.post1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e9/bd/e51a61b1054f09437acfbc2ff9106c30d1eb76bc1453d428399946781253/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl @@ -716,22 +681,17 @@ environments: - pypi: https://files.pythonhosted.org/packages/01/88/a8952b6d5c21e74cbf158515b779666f692846502623e9e3c39d8e8ba25f/llvmlite-0.47.0.tar.gz - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/26/30/5b1a619941bb458d1d3768377254d5d9e9965405daa2bd75f4317eae86f0/qgis_plugin_manager-1.7.5.tar.gz - pypi: https://files.pythonhosted.org/packages/33/d5/9b8482ed572be40d51c3fcbb87451e446e56b5e19487cd60340b8ef51eb4/PyQt5_stubs-5.15.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/16/b5c76b838fd9bf6ce84d3a53346b8874ec05c5f0040d75ef2c320100cd2a/pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/50/965308c703f085f225db2886813b27e015b8b3438c350b22dd65b52c2a2c/fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/4c/8c/290f021104741fea63769c31494f5324c0cd249bf536a65a4350767b1f22/matplotlib-3.10.9-cp311-cp311-macosx_10_12_x86_64.whl - pypi: https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/97/e0ab7241e2b9f35e03d288f2bb1304c1a1d47219601d0df971a851f9db38/qgis_stubs-0.2.0.post1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/df/75/b4ce781849931fef6fd529afa6b63711d5a733065722d0c3e2724af9e40a/scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl - pypi: https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl @@ -1025,24 +985,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-ng-2.3.3-h0261ad2_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - pypi: https://files.pythonhosted.org/packages/08/60/defa5e69641db890a63be281f41345f4c33b157824eaf0b9fad3e08b0dcb/fonttools-4.63.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/26/30/5b1a619941bb458d1d3768377254d5d9e9965405daa2bd75f4317eae86f0/qgis_plugin_manager-1.7.5.tar.gz - pypi: https://files.pythonhosted.org/packages/33/d5/9b8482ed572be40d51c3fcbb87451e446e56b5e19487cd60340b8ef51eb4/PyQt5_stubs-5.15.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/0d/271aace3342157c64700c9ff4c59c7b392f3dbab393692e8db6fbe7ab96c/matplotlib-3.10.9-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/da/0d1df507cf574b3f224ccc3d45244c9a1d732c81dcb26b1e8a766ae271a8/scipy-1.17.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/50/59227d06bdc96e23322713c381af4e77420949d8cd8a042c79e0043096cc/llvmlite-0.47.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/9a/af61ec03b3116c161fd7a06b9e8a265729a8718458333e8ffbb06d9a3978/numba-0.65.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/be/6c/28f17390b62b8f2f520e2915095b3c94d88681ecf0041e75389d9667f202/kiwisolver-1.5.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/c2/97/e0ab7241e2b9f35e03d288f2bb1304c1a1d47219601d0df971a851f9db38/qgis_stubs-0.2.0.post1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/83/6d810a8a9ebc9c307989b418840c20e46907c74d707beb67ab566773e6fc/xarray-2026.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/62/c321f13b5ba1819fc8dca456c7fce578da2dcfecff1abbf0eaddf8406c0f/pandas-3.0.3-cp311-cp311-win_amd64.whl @@ -11353,14 +11308,6 @@ packages: version: 1.5.0 sha256: 3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl - name: dill - version: 0.4.1 - sha256: 1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d - requires_dist: - - objgraph>=1.7.2 ; extra == 'graph' - - gprof2dot>=2022.7.29 ; extra == 'profile' - requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/26/30/5b1a619941bb458d1d3768377254d5d9e9965405daa2bd75f4317eae86f0/qgis_plugin_manager-1.7.5.tar.gz name: qgis-plugin-manager version: 1.7.5 @@ -11467,41 +11414,6 @@ packages: - pytest ; extra == 'dev' - pytest-xvfb ; extra == 'dev' requires_python: '>=3.5' -- pypi: https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl - name: lmfit - version: 1.3.4 - sha256: afce1593b42324d37ae2908249b0c55445e2f4c1a0474ff706a8e2f7b5d949fa - requires_dist: - - asteval>=1.0 - - numpy>=1.24 - - scipy>=1.10.0 - - uncertainties>=3.2.2 - - dill>=0.3.4 - - build ; extra == 'dev' - - check-wheel-contents ; extra == 'dev' - - flake8-pyproject ; extra == 'dev' - - pre-commit ; extra == 'dev' - - twine ; extra == 'dev' - - cairosvg ; extra == 'doc' - - corner ; extra == 'doc' - - emcee>=3.0.0 ; extra == 'doc' - - ipykernel ; extra == 'doc' - - jupyter-sphinx>=0.2.4 ; extra == 'doc' - - matplotlib ; extra == 'doc' - - numdifftools ; extra == 'doc' - - pandas ; extra == 'doc' - - pillow ; extra == 'doc' - - pycairo ; sys_platform == 'win32' and extra == 'doc' - - sphinx ; extra == 'doc' - - sphinx-gallery>=0.10 ; extra == 'doc' - - sphinxcontrib-svg2pdfconverter ; extra == 'doc' - - sympy ; extra == 'doc' - - coverage ; extra == 'test' - - flaky ; extra == 'test' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - lmfit[dev,doc,test] ; extra == 'all' - requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/42/16/b5c76b838fd9bf6ce84d3a53346b8874ec05c5f0040d75ef2c320100cd2a/pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl name: pandas version: 3.0.3 @@ -11748,60 +11660,6 @@ packages: - trove-classifiers>=2024.10.12 ; extra == 'tests' - defusedxml ; extra == 'xmp' requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/77/39/8333b23e230581fd4587fa3edcc5a9b07af5184a9258bacefcda862341b2/timml-6.9.0-py3-none-any.whl - name: timml - version: 6.9.0 - sha256: 018d4c64ebb5f5c1f78aa3ef0087f312ee2e9d8f9320f5459703bbf7dc61b2fa - requires_dist: - - numpy - - scipy - - numba - - matplotlib - - pandas - - pytest ; extra == 'ci' - - pytest-cov ; extra == 'ci' - - pytest-xdist ; extra == 'ci' - - nbval ; extra == 'ci' - - jupyter ; extra == 'ci' - - shapely ; extra == 'ci' - - ruff ; extra == 'ci' - - timml[ci] ; extra == 'docs' - - sphinx ; extra == 'docs' - - sphinx-design ; extra == 'docs' - - pydata-sphinx-theme ; extra == 'docs' - - numpydoc ; extra == 'docs' - - myst-nb ; extra == 'docs' - - sphinxcontrib-bibtex ; extra == 'docs' - - sphinx-autoapi ; extra == 'docs' - requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/77/ab/04d8ded05ebee9f8959a21b3dd8da637f14a9e08cb33cae435863e5f8564/ttim-0.8.0-py3-none-any.whl - name: ttim - version: 0.8.0 - sha256: ee305609e87b6bb8ffe6b48060bef6f8116da000f4dd20cab2170f5fb41d184f - requires_dist: - - numpy - - scipy - - numba - - matplotlib - - lmfit - - pandas - - pytest ; extra == 'ci' - - pytest-cov ; extra == 'ci' - - pytest-sugar ; extra == 'ci' - - jupyter ; extra == 'ci' - - shapely ; extra == 'ci' - - coveralls ; extra == 'ci' - - ruff ; extra == 'ci' - - timml ; extra == 'ci' - - ttim[ci] ; extra == 'docs' - - sphinx ; extra == 'docs' - - sphinx-design ; extra == 'docs' - - pydata-sphinx-theme ; extra == 'docs' - - numpydoc ; extra == 'docs' - - myst-nb ; extra == 'docs' - - sphinxcontrib-bibtex ; extra == 'docs' - - sphinx-autoapi ; extra == 'docs' - requires_python: '>=3.11' - pypi: https://files.pythonhosted.org/packages/79/db/e28c1b83e3680740aa78925f5fb2ae4d16207207419ad75ea9fe604f8676/matplotlib-3.10.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl name: matplotlib version: 3.10.9 @@ -11845,21 +11703,6 @@ packages: version: 1.5.0 sha256: 2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27 requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - name: uncertainties - version: 3.2.3 - sha256: 313353900d8f88b283c9bad81e7d2b2d3d4bcc330cbace35403faaed7e78890a - requires_dist: - - numpy ; extra == 'arrays' - - pytest ; extra == 'test' - - pytest-codspeed ; extra == 'test' - - pytest-cov ; extra == 'test' - - scipy ; extra == 'test' - - sphinx ; extra == 'doc' - - sphinx-copybutton ; extra == 'doc' - - python-docs-theme ; extra == 'doc' - - uncertainties[arrays,doc,test] ; extra == 'all' - requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl name: contourpy version: 1.3.3 @@ -11954,19 +11797,6 @@ packages: - pytest-xdist ; extra == 'test-no-images' - wurlitzer ; extra == 'test-no-images' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/99/31/6cf181011dc738c33bf6ba7aea2e8e1d3c1f71b7dab1942f3054f66f6202/asteval-1.0.8-py3-none-any.whl - name: asteval - version: 1.0.8 - sha256: 6c64385c6ff859a474953c124987c7ee8354d781c76509b2c598741c4d1d28e9 - requires_dist: - - build ; extra == 'dev' - - twine ; extra == 'dev' - - sphinx ; extra == 'doc' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - coverage ; extra == 'test' - - asteval[dev,doc,test] ; extra == 'all' - requires_python: '>=3.10' - pypi: https://files.pythonhosted.org/packages/a2/50/59227d06bdc96e23322713c381af4e77420949d8cd8a042c79e0043096cc/llvmlite-0.47.0-cp311-cp311-win_amd64.whl name: llvmlite version: 0.47.0 @@ -12013,6 +11843,37 @@ packages: version: '2026.2' sha256: bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7 requires_python: '>=2' +- pypi: https://files.pythonhosted.org/packages/cf/5b/6aba31c675c6e1b2726115d4cbaf41ace13d17f08ced4e47f555e5cdd23a/timflow-0.2.0-py3-none-any.whl + name: timflow + version: 0.2.0 + sha256: 028b982598d77646b63314097a4bd0762d53e17ff636c3cffa6620be0b11782d + requires_dist: + - numpy + - scipy + - numba + - matplotlib + - pandas + - ruff ; extra == 'lint' + - tqdm ; extra == 'parallel' + - timflow[parallel] ; extra == 'optional' + - lmfit ; extra == 'optional' + - timflow[lint,optional] ; extra == 'ci' + - pytest ; extra == 'ci' + - pytest-cov ; extra == 'ci' + - pytest-xdist ; extra == 'ci' + - nbval ; extra == 'ci' + - jupyter ; extra == 'ci' + - shapely ; extra == 'ci' + - timflow[ci] ; extra == 'docs' + - sphinx ; extra == 'docs' + - sphinx-design ; extra == 'docs' + - pydata-sphinx-theme ; extra == 'docs' + - numpydoc ; extra == 'docs' + - myst-nb ; extra == 'docs' + - sphinxcontrib-bibtex ; extra == 'docs' + - sphinx-autoapi ; extra == 'docs' + - timflow[docs] ; extra == 'dev' + requires_python: '>=3.11' - pypi: https://files.pythonhosted.org/packages/cf/c5/9fcb7e0e69cef59cf10c746b84f7d58b08bc66a6b7d459783c5a4f6101a6/numpy-2.4.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl name: numpy version: 2.4.4 diff --git a/pixi.toml b/pixi.toml index 25ab548..2bbc4ee 100644 --- a/pixi.toml +++ b/pixi.toml @@ -1,7 +1,7 @@ [workspace] name = "gistim" version = "0.6.0" -description = "Connects TimML and TTim Analytic Element modeling to QGIS" +description = "Connects timflow Analytic Element modeling to QGIS" authors = ["Huite Bootsma"] channels = ["conda-forge"] platforms = ["win-64", "linux-64", "osx-64"] @@ -25,8 +25,7 @@ pyinstaller = "*" [pypi-dependencies] pandas = "*" -timml = ">=6.3.0" -ttim = ">=0.8.0" +timflow = ">=0.2.0" xarray = "*" numpy = "*" diff --git a/plugin/qgistim/README.txt b/plugin/qgistim/README.txt index 1388787..fd65565 100644 --- a/plugin/qgistim/README.txt +++ b/plugin/qgistim/README.txt @@ -1,16 +1,14 @@ -This QGIS plugin serves to easily create model input TimML and TTim analytic +This QGIS plugin serves to easily create model input timflow analytic element models: -* https://github.com/mbakker7/timml -* https://github.com/mbakker7/ttim +* [timflow](https://github.com/timflow-org/timflow) Analytic element input is typically a collection of points, lines, and polygons. This plugin represent a single model with a single GeoPackage. The different elements are represented as layers in the GeoPackage, and also as ordinary vector layers in QGIS. -To run the model with TimML and TTim, this plugin relies on a server program called -`gistim`. +To run the model with timflow, this plugin relies on a server program called `gistim`. Find the repository and issue tracker here: https://github.com/Deltares/QGIS-Tim diff --git a/plugin/qgistim/core/elements/aquifer.py b/plugin/qgistim/core/elements/aquifer.py index d3fc498..5c04091 100644 --- a/plugin/qgistim/core/elements/aquifer.py +++ b/plugin/qgistim/core/elements/aquifer.py @@ -96,7 +96,7 @@ def write(self): def remove_from_geopackage(self): """This element may not be removed.""" - return + pass def to_timml(self) -> ElementExtraction: missing = self.check_timml_columns() diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index 8ed59cd..f2a819b 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -183,7 +183,7 @@ def timml_script_content(data: Dict[str, Any]): strings = [ "import numpy as np", - "import timml", + "from timflow import steady as timml", "", f"timml_model = timml.ModelMaq(\n{format_kwargs(aquifer_data)}\n)", ] @@ -207,7 +207,7 @@ def timml_script(data: Dict[str, Any]) -> str: def ttim_script(timml_data: Dict[str, Any], ttim_data: Dict[str, Any]) -> str: strings, _ = timml_script_content(timml_data) - strings.insert(2, "import ttim") + strings.insert(2, "from timflow import transient as ttim") data = ttim_data.copy() # avoid side-effects aquifer_data = data.pop("timml Aquifer:Aquifer") diff --git a/plugin/qgistim/core/server_handler.py b/plugin/qgistim/core/server_handler.py index 2cc10f2..bdf2601 100644 --- a/plugin/qgistim/core/server_handler.py +++ b/plugin/qgistim/core/server_handler.py @@ -1,6 +1,6 @@ """ This module contains the logic for starting, communicating with, and killing a -separate (conda) interpreter, which is running TimML and TTim. +separate (conda) interpreter, which is running timflow. For thread safety: DO NOT INCLUDE QGIS CALLS HERE. """ diff --git a/plugin/qgistim/widgets/install_dialog.py b/plugin/qgistim/widgets/install_dialog.py index 4806071..7c51cc2 100644 --- a/plugin/qgistim/widgets/install_dialog.py +++ b/plugin/qgistim/widgets/install_dialog.py @@ -24,7 +24,7 @@ def finished(self, result) -> None: if result: self.message_bar.pushMessage( title="Info", - text="Succesfully installed TimML and TTim server", + text="Succesfully installed TimFlow server", level=Qgis.Info, ) else: @@ -35,7 +35,7 @@ def finished(self, result) -> None: self.message_bar.pushMessage( title="Error", - text=f"Failed to install TimML and TTim server. {message}", + text=f"Failed to install timflow server. {message}", level=Qgis.Critical, ) return @@ -87,7 +87,7 @@ class InstallDialog(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.parent = parent - self.setWindowTitle("Install TimML and TTim server") + self.setWindowTitle("Install timflow server") self.install_task = None # Define widgets @@ -133,7 +133,7 @@ def __init__(self, parent=None): def initialize_version_view(self): version_widgets = {} version_layout = QGridLayout() - for i, package in enumerate(["timml", "ttim", "gistim"]): + for i, package in enumerate(["timflow", "gistim"]): version_view = QLineEdit() version_view.setEnabled(False) widgets = ( @@ -147,20 +147,17 @@ def initialize_version_view(self): def update_versions(self): versions = self.parent.server_handler.versions() - for package in ["timml", "ttim", "gistim"]: + for package in ["timflow", "gistim"]: self.version_widgets[package][1].setText(versions.get(package)) - return def enable_install_buttons(self, enabled: bool) -> None: self.install_github_button.setEnabled(enabled) self.install_zip_button.setEnabled(enabled) - return def set_zip_path(self) -> None: path, _ = QFileDialog.getOpenFileName(self, "Select file", "", "*.zip") if path != "": # Empty string in case of cancel button press self.install_zip_line_edit.setText(path) - return def install_from_zip(self) -> None: path = self.install_zip_line_edit.text() @@ -181,7 +178,6 @@ def install_from_zip(self) -> None: ) self.enable_install_buttons(False) QgsApplication.taskManager().addTask(self.install_task) - return def install_from_github(self) -> None: reply = QMessageBox.question( @@ -196,4 +192,3 @@ def install_from_github(self) -> None: self.install_task = InstallGithubTask(self, message_bar=self.parent.message_bar) self.enable_install_buttons(False) QgsApplication.taskManager().addTask(self.install_task) - return diff --git a/plugin/qgistim/widgets/tim_widget.py b/plugin/qgistim/widgets/tim_widget.py index 4ca326c..122f977 100644 --- a/plugin/qgistim/widgets/tim_widget.py +++ b/plugin/qgistim/widgets/tim_widget.py @@ -208,7 +208,7 @@ def __init__(self, parent, iface): self.compute_widget = ComputeWidget(self) self.install_dialog = InstallDialog(self) - self.config_button = QPushButton("Install TimML and TTim server") + self.config_button = QPushButton("Install timflow server") self.config_button.clicked.connect(self.install_dialog.show) self.config_button.setIcon(QgsApplication.getThemeIcon("/mActionOptions.svg")) diff --git a/pyproject.toml b/pyproject.toml index a821466..3304678 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta" [project] name = "gistim" -description = "Connects TimML and TTim Analytic Element modeling to QGIS" +description = "Connects timflow Analytic Element modeling to QGIS" readme = "README.md" version = "0.6.0" maintainers = [{ name = "Huite Bootsma", email = "huite.bootsma@deltares.nl" }] requires-python = ">=3.11" -dependencies = ['pandas', 'timml>=6.3.0', 'ttim>=0.8.0', 'xarray', 'numpy'] +dependencies = ['pandas', 'timflow>=0.2.0', 'xarray', 'numpy'] classifiers = [ 'Development Status :: 4 - Beta', 'Intended Audience :: Science/Research', diff --git a/scripts/write_backend_versions.py b/scripts/write_backend_versions.py index dbee876..bee3e32 100644 --- a/scripts/write_backend_versions.py +++ b/scripts/write_backend_versions.py @@ -3,14 +3,12 @@ def write_versions(path): - import timml - import ttim + import timflow import gistim versions = { - "timml": timml.__version__, - "ttim": ttim.__version__, + "timflow": timflow.__version__, "gistim": gistim.__version__, } os.makedirs(os.path.dirname(path), exist_ok=True) From 0f48f6f077925a792ffe402d0d1dd63603482b17 Mon Sep 17 00:00:00 2001 From: Marnix <150045289+deltamarnix@users.noreply.github.com> Date: Thu, 28 May 2026 16:09:15 +0200 Subject: [PATCH 02/27] Add prompt for test data runner Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .vscode/launch.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 3f911fd..eed6afa 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,8 +9,16 @@ "console": "integratedTerminal", "args": [ "compute", - "${workspaceFolder}/testdata/test.json" + "${input:computeGistimJsonPath}" ] } + ], + "inputs": [ + { + "id": "computeGistimJsonPath", + "type": "promptString", + "description": "Path to the JSON input file for the compute command", + "default": "${workspaceFolder}/testdata/test.json" + } ] } From 49348499fa21f25640a6dff35332def0d3289f7c Mon Sep 17 00:00:00 2001 From: Marnix <150045289+deltamarnix@users.noreply.github.com> Date: Thu, 28 May 2026 16:11:37 +0200 Subject: [PATCH 03/27] Fix documentation Path in %APPDATA% was spelled wrongly Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/developer.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer.qmd b/docs/developer.qmd index 6e1d360..74ff658 100644 --- a/docs/developer.qmd +++ b/docs/developer.qmd @@ -12,7 +12,7 @@ To build the timflow server application with PyInstaller, run `pixi run build-ba This creates a built PyInstaller application in `./dist/gistim`. -Run `pixi run -e dev install-backend` to create a symlink between %APPDATA%/qgistim and ./dist/gistim. +Run `pixi run -e dev install-backend` to create a symlink between %APPDATA%/qgis-tim and ./dist/gistim. ## Creating new release From 9ca2a032da6969bbeebe845d69c5f08e683e8f5b Mon Sep 17 00:00:00 2001 From: deltamarnix Date: Thu, 28 May 2026 16:10:34 +0200 Subject: [PATCH 04/27] Fix type-o --- plugin/qgistim/widgets/install_dialog.py | 2 +- plugin/qgistim/widgets/tim_widget.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/qgistim/widgets/install_dialog.py b/plugin/qgistim/widgets/install_dialog.py index 7c51cc2..d5f37e3 100644 --- a/plugin/qgistim/widgets/install_dialog.py +++ b/plugin/qgistim/widgets/install_dialog.py @@ -24,7 +24,7 @@ def finished(self, result) -> None: if result: self.message_bar.pushMessage( title="Info", - text="Succesfully installed TimFlow server", + text="Successfully installed TimFlow server", level=Qgis.Info, ) else: diff --git a/plugin/qgistim/widgets/tim_widget.py b/plugin/qgistim/widgets/tim_widget.py index 122f977..7e61c4f 100644 --- a/plugin/qgistim/widgets/tim_widget.py +++ b/plugin/qgistim/widgets/tim_widget.py @@ -261,7 +261,7 @@ def start_interpreter_task(self) -> Union[StartTask, None]: def execute(self, data: Dict[str, str]) -> Dict[str, Any]: """ - Execute a command, and check whether it executed succesfully. + Execute a command, and check whether it executed successfully. """ response = self.server_handler.send(data) return response From 04f544d401f625a26337e60e32c52707f923912c Mon Sep 17 00:00:00 2001 From: Joeri van Engelen Date: Mon, 1 Jun 2026 15:03:37 +0200 Subject: [PATCH 05/27] consistent name for timflow Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- plugin/qgistim/widgets/install_dialog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/qgistim/widgets/install_dialog.py b/plugin/qgistim/widgets/install_dialog.py index d5f37e3..4862156 100644 --- a/plugin/qgistim/widgets/install_dialog.py +++ b/plugin/qgistim/widgets/install_dialog.py @@ -24,7 +24,7 @@ def finished(self, result) -> None: if result: self.message_bar.pushMessage( title="Info", - text="Successfully installed TimFlow server", + text="Successfully installed timflow server", level=Qgis.Info, ) else: From 7f02a1b283020b189f56d3feb0e64334d34131e8 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 10:48:56 +0200 Subject: [PATCH 06/27] Fix wrong arg --- gistim/compute.py | 4 ++-- plugin/qgistim/core/formatting.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gistim/compute.py b/gistim/compute.py index 6e3ab2b..a40bf50 100644 --- a/gistim/compute.py +++ b/gistim/compute.py @@ -56,7 +56,7 @@ def initialize_timml(data): def initialize_ttim(data, timml_model): aquifer = data.pop("ModelMaq") - ttim_model = ttim.ModelMaq(**aquifer, timmlmodel=timml_model) + ttim_model = ttim.ModelMaq(**aquifer, steady=timml_model) elements = initialize_elements(ttim_model, TTIM_MAPPING, data) return ttim_model, elements @@ -126,7 +126,7 @@ def _( nlayer = model.aq.find_aquifer_data(x[0], y[0]).naq if 0.0 in time: - steady_head = model.timmlmodel.headgrid(xg=x, yg=y)[:, np.newaxis, :, :] + steady_head = model.steady.headgrid(xg=x, yg=y)[:, np.newaxis, :, :] transient_head = model.headgrid(xg=x, yg=y, t=time[1:]) head = np.hstack((steady_head, transient_head)) else: diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index f2a819b..ca525d6 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -215,7 +215,7 @@ def ttim_script(timml_data: Dict[str, Any], ttim_data: Dict[str, Any]) -> str: data.pop("start_date") strings.append( - f"\nttim_model = ttim.ModelMaq(\n{format_kwargs(aquifer_data)}\n{PREFIX}timmlmodel=timml_model,\n)" + f"\nttim_model = ttim.ModelMaq(\n{format_kwargs(aquifer_data)}\n{PREFIX}steady=timml_model,\n)" ) element_strings, observations = elements_and_observations( From 2d4f9fd331f8a631016db358d363a7af0b832087 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 12:47:49 +0200 Subject: [PATCH 07/27] Rename buttons to follow Timflow --- docs/tutorial_Rijsenhout.qmd | 12 +++---- docs/tutorial_TheHague.qmd | 32 +++++++++---------- .../qgistim/core/elements/head_line_sink.py | 2 +- .../core/elements/impermeable_line_doublet.py | 2 +- .../core/elements/leaky_line_doublet.py | 2 +- .../qgistim/core/elements/line_sink_ditch.py | 2 +- plugin/qgistim/core/formatting.py | 16 +++++----- plugin/qgistim/widgets/dataset_widget.py | 8 ++--- 8 files changed, 38 insertions(+), 38 deletions(-) diff --git a/docs/tutorial_Rijsenhout.qmd b/docs/tutorial_Rijsenhout.qmd index b5f9e97..fcc1595 100644 --- a/docs/tutorial_Rijsenhout.qmd +++ b/docs/tutorial_Rijsenhout.qmd @@ -308,9 +308,9 @@ Let's now check the calculated heads for the 4 layers, first with the *Value Too Now we introduce a new but frequently used element: the sheet pile. (@) Return to the QGIS-Tim panel and go to the tab *Elements*. -(@) Click on the element "Leaky Line Doublet". +(@) Click on the element "Leaky Wall". (@) Give the layer a name, e.g. "sheetpile". -(@) In your geopackage select the layer "timml Leaky Line Doublet:sheetpile" and start editing using the *Toggle Editing Mode* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). +(@) In your geopackage select the layer "timml Leaky Wall:sheetpile" and start editing using the *Toggle Editing Mode* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). (@) In the editing mode, the *Add Line Feature* button (![](figures/tutorial/button_AddLineFeature.png){width=4%}) is available. Click the button and draw a box around the 5 bombs (click left to start, click right to close). (@) In the *Feature Attributes* window make resistance = 1500 and layer = 0. (@) Click *OK*. @@ -360,16 +360,16 @@ It is not possible for the plugin to automaticcaly read your geopackage as it is In the backgorund the plugin first removes all layers and than opens the geopackage again. You did not see it, did you? It happend in a blink of an eye. ## Model 5: add infiltration of drainwater -To prevent damage on the private properties caused by the dewatering, the authorities demand 50% of the drained flux to be infiltrated. For the infiltration a horizontal well of 400 m is used. In Tim this element is called "Line Sink Ditch". Let's add this element just along the road (Aalsmeerderweg) southeast of the project area. +To prevent damage on the private properties caused by the dewatering, the authorities demand 50% of the drained flux to be infiltrated. For the infiltration a horizontal well of 400 m is used. In Tim this element is called "Ditch". Let's add this element just along the road (Aalsmeerderweg) southeast of the project area. -(@) On the tab *Elements* in QGIS-Tim click on the element "Line Sink Ditch". +(@) On the tab *Elements* in QGIS-Tim click on the element "Ditch". (@) Give the layer a name, e.g. "InfiltrationWell". -See that layer "timml Line Sink Ditch:InfiltrationWell" is added to the timml sub group in your geopackage with 'line' as geometry. For the transient version of the model a table with the same name is added to the ttim sub group. Next step is to add the location of the horizontal well and its capacity. +See that layer "timml Ditch:InfiltrationWell" is added to the timml sub group in your geopackage with 'line' as geometry. For the transient version of the model a table with the same name is added to the ttim sub group. Next step is to add the location of the horizontal well and its capacity. (@) Click the *Measure Line" button (![](figures/tutorial/button_MeasureLine.png){width=4%}) from the "Attributes Toolbar". (@) With your left mouse button try to get an idea what a distance of 400 m along the road looks like. Close the window. -(@) Select the layer "timml Line Sink Ditch:InfiltrationWell". +(@) Select the layer "timml Ditch:InfiltrationWell". (@) Start editing with the *Toggle Editing Mode*. (@) Use the *Add Line Feature* button (![](figures/tutorial/button_AddLineFeature.png){width=4%}) to draw a 400 m line (click left to start, click right to close). (@) Fill these feature within the table: discharge = -1000 (negative abstraction is flux into the model), resistance = 1, width = 1, layer = 0! not *NULL* ;-). By default order = 4. diff --git a/docs/tutorial_TheHague.qmd b/docs/tutorial_TheHague.qmd index cb665f6..ff80d9f 100644 --- a/docs/tutorial_TheHague.qmd +++ b/docs/tutorial_TheHague.qmd @@ -297,17 +297,17 @@ We are now ready to define our first steady state model by parameterizing our Aq In the QGIS-Tim Window we now introduce the following elements for ground water modelling in the QGIS-Tim tab *Element*: -- Leaky Line Doublet +- Leaky Wall - Well -### Adding a Leaky Line Doublet +### Adding a Leaky Wall -(@) In the QGIS-Tim window go to tab *Elements* and select the button *Leaky Line Doublet*. +(@) In the QGIS-Tim window go to tab *Elements* and select the button *Leaky Wall*. (@) Fill in the name of the layer in the pop-up panel, e.g. 'sheet_pile', and click *OK* and this new Layer is added to the *Layers* panel. First, we will *draw* the location of the sheet pile before *adding* the parameter values. -(@) In the *Layers* panel right click on the layer ![](figures/tutorial/figure_Leakylinedoublet_icon.png){width=4%} *timml Leaky Line Doublet:sheet_pile* and start the editing mode by clicking the *Toggle Editing* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). +(@) In the *Layers* panel right click on the layer ![](figures/tutorial/figure_Leakylinedoublet_icon.png){width=4%} *timml Leaky Wall:sheet_pile* and start the editing mode by clicking the *Toggle Editing* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). Two important remarks before drawing the sheet pile: @@ -323,14 +323,14 @@ Two important remarks before drawing the sheet pile: (@) Draw the sheet pile around the building pit (start south corner) with your left mouse button and close the feature on the first point. (@) In the pop-up window fill in the resistance (1000 d, see \* below) and layer number (layer=0, see \*\* below) as in @fig-LeakylinedoubletFeatureAttributes and click OK to close the window. -![The characteristics of the Leaky line doublet](figures/tutorial/figure_LeakylinedoubletFeatureAttributes.png){width=60% #fig-LeakylinedoubletFeatureAttributes fig-align="left"} +![The characteristics of the Leaky Wall](figures/tutorial/figure_LeakylinedoubletFeatureAttributes.png){width=60% #fig-LeakylinedoubletFeatureAttributes fig-align="left"} > Remarks to the provided values:
> \* Because of a known issue in the TimML software, until this issue is resolved, the value of the resistance must be multiplied by the permeability. For normal sheet pile walls a resistance value of 100-250 d for interlock leakage is a good choice. In this case the chosen value needs to be increased by multiplying with the applicable aquifer permeability in the effected layer (R=100 d becomes R=10*100 d).
> \*\* In the real-world counting starts with 1. However, Tim is programmed in Python and in Python counting starts with 0. You will get used to it. (@) Close the editing mode with a click on (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}) and you are asked to save your changes. -(@) Open the attribute table for *Leaky Line Doublet* (click ![](figures/tutorial/button-Qgis-OpenAttributeTable.png){width=3%} or press F6) to check hydraulic resistance values for the sheet pile walls. +(@) Open the attribute table for *Leaky Wall* (click ![](figures/tutorial/button-Qgis-OpenAttributeTable.png){width=3%} or press F6) to check hydraulic resistance values for the sheet pile walls. ### Adding a Well @@ -353,7 +353,7 @@ Two important remarks before drawing the sheet pile: When you finished the input of the wells and their parameters, you have to look back to the combination of wells and sheet pile wall. The reason is that near a well the flow is strong and therefore the flow through the wall is increased. This may lead to extremities in the calculation if wall segments are chosen too large. Tim uses control points but they are set at regular distances on the doublet (the number of control points is 1+order). It is necessary to divide the wall in smaller sections near well locations. The length of each section should be chosen equal to approximately the distance of the wall to the nearest well. -(@) Select the Leaky Line Doublet in the *Layers* panel and start the editing mode. +(@) Select the Leaky Wall in the *Layers* panel and start the editing mode. (@) Activate the Vertex Tool (![](figures/tutorial/button_VertexTool.png){width=4%}) and then hoover along the sheet pile line in your drawing. The line element near your pointer lights up. (@) With the combination of **Shift + double left click**, you can add a new vertex to the line. Repeat that for the number of points you want to add. @@ -448,7 +448,7 @@ Check in the *Layers* panel and see that the results are not overwritten but add Let's now run Variant 2. (@) In layer *timml Aquifer:...* reset the value for "aquitard_c" in layer 1 to the default of 40 d. -(@) In layer *timml Leaky Line Doublet:...* change the value for "resistance" into 5000 d (500x10). +(@) In layer *timml Leaky Wall:...* change the value for "resistance" into 5000 d (500x10). (@) In the QGIS-Tim panel go to the tab *Results* and change the name of the output, e.g. case-TheHague_v2. (@) Click *Compute* to run variant 2. (@) Fill in your calculated heads at the observation locations in the table above. @@ -461,16 +461,16 @@ Suppose the best guess value of the clay layer resistance was right, then a miti If we want to create extra depth of the sheet pile we will have to introduce it in a deeper layer. There are 2 options to implement it in your model: -- Add a copy of the geometry of the sheet pile wall to the existing *Leaky Line Doublet* shape and assign it to layer 1. -- We recommend to create an extra *Leaky Line Doublet* element. In this case it is more easy to switch on/off this additional element in your sensitivity analysis. +- Add a copy of the geometry of the sheet pile wall to the existing *Leaky Wall* shape and assign it to layer 1. +- We recommend to create an extra *Leaky Wall* element. In this case it is more easy to switch on/off this additional element in your sensitivity analysis. -How to copy the sheet pile wall to an extra *Leaky Line Doublet* element? +How to copy the sheet pile wall to an extra *Leaky Wall* element? -(@) In the QGIS-Tim panel go to the tab *Elements* and add a second *Leaky Line Doublet* and give it a name, e.g. "sheet_pile_L1" +(@) In the QGIS-Tim panel go to the tab *Elements* and add a second *Leaky Wall* and give it a name, e.g. "sheet_pile_L1" (@) Go to the tab *Model Manager* and see that the element separately is added to the list. Here is can switch this element on / off for a calculation. -(@) In the *Layers* panel select the new layer *timml Leaky Line Doublet:sheet_pile_l1*. +(@) In the *Layers* panel select the new layer *timml Leaky Wall:sheet_pile_l1*. (@) Open its *Attribute Table* (F6) and start the editing mode. The table is empty. -(@) Also open the *Attribute Table* of the first *Leaky Line Doublet* and select the existing element. +(@) Also open the *Attribute Table* of the first *Leaky Wall* and select the existing element. (@) Click on the *Copy* button (![](figures/tutorial/button_Copy_Selected_Row.png){width=3%}) in the source table to copy the selected row to the clipboard. ![](figures/tutorial/figure_Leakylinedoublet_copy.png){width=70%} @@ -509,9 +509,9 @@ Still, probably some decrease of interlock leakage is needed when sheet piles ar ## Effect of a not closed wall (about 20 cm) Authorities are afraid that leakage incidents could be harmful for surrounding monuments. -The effect of leakage can be studied by creating a fictitious little opening in the wall. This can be done e.g. by changing the values of first and last coordinate of the leaky line doublet. +The effect of leakage can be studied by creating a fictitious little opening in the wall. This can be done e.g. by changing the values of first and last coordinate of the Leaky Wall. -(@) Select the *Leaky Line Doublet* in the *Layers* panel +(@) Select the *Leaky Wall* in the *Layers* panel (@) In the editing toolbar go to the toggle editing option (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png){width=4%}) and check the vertex option (![](figures/tutorial/button_VertexTool.png){width=4%}). (@) On the drawing panel select a point in the line element of the wall and right click. diff --git a/plugin/qgistim/core/elements/head_line_sink.py b/plugin/qgistim/core/elements/head_line_sink.py index 7cd3d97..0d50df7 100644 --- a/plugin/qgistim/core/elements/head_line_sink.py +++ b/plugin/qgistim/core/elements/head_line_sink.py @@ -43,7 +43,7 @@ class HeadLineSinkSchema(RowWiseSchema): class HeadLineSink(TransientElement): - element_type = "Head Line Sink" + element_type = "River" geometry_type = "Linestring" timml_attributes = ( QgsField("head", QVariant.Double), diff --git a/plugin/qgistim/core/elements/impermeable_line_doublet.py b/plugin/qgistim/core/elements/impermeable_line_doublet.py index e74fb36..f1de5ef 100644 --- a/plugin/qgistim/core/elements/impermeable_line_doublet.py +++ b/plugin/qgistim/core/elements/impermeable_line_doublet.py @@ -16,7 +16,7 @@ class ImpermeableLineDoubletSchema(RowWiseSchema): class ImpermeableLineDoublet(Element): - element_type = "Impermeable Line Doublet" + element_type = "Impermeable Wall" geometry_type = "Linestring" timml_attributes = ( QgsField("order", QVariant.Int), diff --git a/plugin/qgistim/core/elements/leaky_line_doublet.py b/plugin/qgistim/core/elements/leaky_line_doublet.py index b67becc..147d4c0 100644 --- a/plugin/qgistim/core/elements/leaky_line_doublet.py +++ b/plugin/qgistim/core/elements/leaky_line_doublet.py @@ -17,7 +17,7 @@ class LeakyLineDoubletSchema(RowWiseSchema): class LeakyLineDoublet(Element): - element_type = "Leaky Line Doublet" + element_type = "Leaky Wall" geometry_type = "Linestring" timml_attributes = ( QgsField("resistance", QVariant.Double), diff --git a/plugin/qgistim/core/elements/line_sink_ditch.py b/plugin/qgistim/core/elements/line_sink_ditch.py index ac4dd9b..12434b5 100644 --- a/plugin/qgistim/core/elements/line_sink_ditch.py +++ b/plugin/qgistim/core/elements/line_sink_ditch.py @@ -43,7 +43,7 @@ class LineSinkDitchSchema(RowWiseSchema): class LineSinkDitch(TransientElement): - element_type = "Line Sink Ditch" + element_type = "Ditch" geometry_type = "Linestring" timml_attributes = ( QgsField("discharge", QVariant.Double), diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index ca525d6..c945118 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -22,10 +22,10 @@ "Polygon Inhomogeneity": "PolygonInhomMaq", "Polygon Area Sink": "PolygonInhomMaq", "Polygon Semi-Confined Top": "PolygonInhomMaq", - "Head Line Sink": "HeadLineSinkString", - "Line Sink Ditch": "LineSinkDitchString", - "Leaky Line Doublet": "LeakyLineDoubletString", - "Impermeable Line Doublet": "ImpLineDoubletString", + "River": "HeadLineSinkString", + "Ditch": "LineSinkDitchString", + "Leaky Wall": "LeakyLineDoubletString", + "Impermeable Wall": "ImpLineDoubletString", "Building Pit": "BuildingPit", "Leaky Building Pit": "LeakyBuildingPit", "Head Observation": "Head Observation", @@ -39,10 +39,10 @@ "Circular Area Sink": "CircAreaSink", "Well": "Well", "Head Well": "HeadWell", - "Head Line Sink": "HeadLineSinkString", - "Line Sink Ditch": "LineSinkDitchString", - "Leaky Line Doublet": "LeakyLineDoubletString", - "Impermeable Line Doublet": "LeakyLineDoubletString", + "River": "HeadLineSinkString", + "Ditch": "LineSinkDitchString", + "Leaky Wall": "LeakyLineDoubletString", + "Impermeable Wall": "LeakyLineDoubletString", "Head Observation": "Head Observation", } PREFIX = " " diff --git a/plugin/qgistim/widgets/dataset_widget.py b/plugin/qgistim/widgets/dataset_widget.py index 472171e..b480a7d 100644 --- a/plugin/qgistim/widgets/dataset_widget.py +++ b/plugin/qgistim/widgets/dataset_widget.py @@ -48,11 +48,11 @@ "Uniform Flow", "Well", "Head Well", - "Head Line Sink", - "Line Sink Ditch", + "River", + "Ditch", "Circular Area Sink", - "Impermeable Line Doublet", - "Leaky Line Doublet", + "Impermeable Wall", + "Leaky Wall", "Head Observation", ] ) From 84be868fd6ed01c80646c0029bceac9f15868de2 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 13:17:09 +0200 Subject: [PATCH 08/27] Rename Python objects to new Timflow names --- gistim/compute.py | 16 ++++++++-------- plugin/qgistim/core/elements/__init__.py | 12 ++++++------ plugin/qgistim/core/elements/head_line_sink.py | 6 +++--- .../qgistim/core/elements/leaky_line_doublet.py | 6 +++--- plugin/qgistim/core/elements/line_sink_ditch.py | 6 +++--- plugin/qgistim/core/formatting.py | 16 ++++++++-------- plugin/qgistim/qt/qgistim_dockwidget_base.ui | 16 ++++++++-------- 7 files changed, 39 insertions(+), 39 deletions(-) diff --git a/gistim/compute.py b/gistim/compute.py index a40bf50..bfb7e2e 100644 --- a/gistim/compute.py +++ b/gistim/compute.py @@ -20,10 +20,10 @@ "Well": timml.Well, "HeadWell": timml.HeadWell, "PolygonInhomMaq": timml.PolygonInhomMaq, - "HeadLineSinkString": timml.HeadLineSinkString, - "LineSinkDitchString": timml.LineSinkDitchString, - "LeakyLineDoubletString": timml.LeakyLineDoubletString, - "ImpLineDoubletString": timml.ImpLineDoubletString, + "RiverString": timml.RiverString, + "DitchString": timml.DitchString, + "LeakyWallString": timml.LeakyWallString, + "ImpermeableWallString": timml.ImpermeableWallString, "BuildingPit": timml.BuildingPitMaq, "LeakyBuildingPit": timml.LeakyBuildingPitMaq, } @@ -31,9 +31,9 @@ "CircAreaSink": ttim.CircAreaSink, "Well": ttim.Well, "HeadWell": ttim.HeadWell, - "HeadLineSinkString": ttim.HeadLineSinkString, - "LineSinkDitchString": ttim.LineSinkDitchString, - "LeakyLineDoubletString": ttim.LeakyLineDoubletString, + "RiverString": ttim.RiverString, + "DitchString": ttim.DitchString, + "LeakyWallString": ttim.LeakyWallString, } @@ -216,7 +216,7 @@ def extract_discharges(elements, nlayers, **_): table_rows.append(row) tables[f"discharge-{layername}"] = pd.DataFrame.from_records(table_rows) - elif isinstance(sample, (timml.LineSinkDitchString, timml.HeadLineSinkString)): + elif isinstance(sample, (timml.DitchString, timml.RiverString)): table_rows = [] for linestring in content: discharges = linestring.discharge_per_linesink() diff --git a/plugin/qgistim/core/elements/__init__.py b/plugin/qgistim/core/elements/__init__.py index 5ef7fce..59a89e2 100644 --- a/plugin/qgistim/core/elements/__init__.py +++ b/plugin/qgistim/core/elements/__init__.py @@ -11,12 +11,12 @@ from qgistim.core.elements.discharge_observation import DischargeObservation from qgistim.core.elements.domain import Domain from qgistim.core.elements.element import Element -from qgistim.core.elements.head_line_sink import HeadLineSink +from qgistim.core.elements.head_line_sink import River from qgistim.core.elements.headwell import HeadWell, RemoteHeadWell from qgistim.core.elements.impermeable_line_doublet import ImpermeableLineDoublet from qgistim.core.elements.leaky_building_pit import LeakyBuildingPit -from qgistim.core.elements.leaky_line_doublet import LeakyLineDoublet -from qgistim.core.elements.line_sink_ditch import LineSinkDitch +from qgistim.core.elements.leaky_line_doublet import LeakyWall +from qgistim.core.elements.line_sink_ditch import Ditch from qgistim.core.elements.observation import HeadObservation from qgistim.core.elements.polygon_area_sink import PolygonAreaSink from qgistim.core.elements.polygon_inhomogeneity import PolygonInhomogeneity @@ -34,11 +34,11 @@ Well, HeadWell, RemoteHeadWell, - HeadLineSink, - LineSinkDitch, + River, + Ditch, CircularAreaSink, ImpermeableLineDoublet, - LeakyLineDoublet, + LeakyWall, PolygonAreaSink, PolygonSemiConfinedTop, PolygonInhomogeneity, diff --git a/plugin/qgistim/core/elements/head_line_sink.py b/plugin/qgistim/core/elements/head_line_sink.py index 0d50df7..259d1a7 100644 --- a/plugin/qgistim/core/elements/head_line_sink.py +++ b/plugin/qgistim/core/elements/head_line_sink.py @@ -17,7 +17,7 @@ ) -class HeadLineSinkSchema(RowWiseSchema): +class RiverSchema(RowWiseSchema): timml_schemata = { "geometry": Required(), "head": Required(), @@ -42,7 +42,7 @@ class HeadLineSinkSchema(RowWiseSchema): } -class HeadLineSink(TransientElement): +class River(TransientElement): element_type = "River" geometry_type = "Linestring" timml_attributes = ( @@ -71,7 +71,7 @@ class HeadLineSink(TransientElement): "head_transient", "timeseries_id", ) - schema = HeadLineSinkSchema() + schema = RiverSchema() @classmethod def renderer(cls) -> QgsSingleSymbolRenderer: diff --git a/plugin/qgistim/core/elements/leaky_line_doublet.py b/plugin/qgistim/core/elements/leaky_line_doublet.py index 147d4c0..a50f878 100644 --- a/plugin/qgistim/core/elements/leaky_line_doublet.py +++ b/plugin/qgistim/core/elements/leaky_line_doublet.py @@ -7,7 +7,7 @@ from qgistim.core.schemata import Membership, Positive, Required, StrictlyPositive -class LeakyLineDoubletSchema(RowWiseSchema): +class LeakyWallSchema(RowWiseSchema): timml_schemata = { "geometry": Required(), "resistance": Required(StrictlyPositive()), @@ -16,7 +16,7 @@ class LeakyLineDoubletSchema(RowWiseSchema): } -class LeakyLineDoublet(Element): +class LeakyWall(Element): element_type = "Leaky Wall" geometry_type = "Linestring" timml_attributes = ( @@ -28,7 +28,7 @@ class LeakyLineDoublet(Element): timml_defaults = { "order": QgsDefaultValue("4"), } - schema = LeakyLineDoubletSchema() + schema = LeakyWallSchema() @classmethod def renderer(cls) -> QgsSingleSymbolRenderer: diff --git a/plugin/qgistim/core/elements/line_sink_ditch.py b/plugin/qgistim/core/elements/line_sink_ditch.py index 12434b5..4eb99c4 100644 --- a/plugin/qgistim/core/elements/line_sink_ditch.py +++ b/plugin/qgistim/core/elements/line_sink_ditch.py @@ -17,7 +17,7 @@ ) -class LineSinkDitchSchema(RowWiseSchema): +class DitchSchema(RowWiseSchema): timml_schemata = { "geometry": Required(), "discharge": Required(), @@ -42,7 +42,7 @@ class LineSinkDitchSchema(RowWiseSchema): } -class LineSinkDitch(TransientElement): +class Ditch(TransientElement): element_type = "Ditch" geometry_type = "Linestring" timml_attributes = ( @@ -71,7 +71,7 @@ class LineSinkDitch(TransientElement): "discharge_transient", "timeseries_id", ) - schema = LineSinkDitchSchema() + schema = DitchSchema() @classmethod def renderer(cls) -> QgsSingleSymbolRenderer: diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index c945118..76f6d37 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -22,10 +22,10 @@ "Polygon Inhomogeneity": "PolygonInhomMaq", "Polygon Area Sink": "PolygonInhomMaq", "Polygon Semi-Confined Top": "PolygonInhomMaq", - "River": "HeadLineSinkString", - "Ditch": "LineSinkDitchString", - "Leaky Wall": "LeakyLineDoubletString", - "Impermeable Wall": "ImpLineDoubletString", + "River": "RiverString", + "Ditch": "DitchString", + "Leaky Wall": "LeakyWallString", + "Impermeable Wall": "ImpermeableWallString", "Building Pit": "BuildingPit", "Leaky Building Pit": "LeakyBuildingPit", "Head Observation": "Head Observation", @@ -39,10 +39,10 @@ "Circular Area Sink": "CircAreaSink", "Well": "Well", "Head Well": "HeadWell", - "River": "HeadLineSinkString", - "Ditch": "LineSinkDitchString", - "Leaky Wall": "LeakyLineDoubletString", - "Impermeable Wall": "LeakyLineDoubletString", + "River": "RiverString", + "Ditch": "DitchString", + "Leaky Wall": "LeakyWallString", + "Impermeable Wall": "LeakyWallString", "Head Observation": "Head Observation", } PREFIX = " " diff --git a/plugin/qgistim/qt/qgistim_dockwidget_base.ui b/plugin/qgistim/qt/qgistim_dockwidget_base.ui index 072ebe6..69a07b1 100644 --- a/plugin/qgistim/qt/qgistim_dockwidget_base.ui +++ b/plugin/qgistim/qt/qgistim_dockwidget_base.ui @@ -64,9 +64,9 @@ - + - LineSinkDitch + Ditch @@ -85,9 +85,9 @@ - + - LeakyLineDoublet + LeakyWall @@ -99,16 +99,16 @@ - + - ImpLineDoublet + ImpermeableWall - + - HeadLineSink + River From c22312b818704e879febd488a949e27cfe8f4eb3 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 13:21:06 +0200 Subject: [PATCH 09/27] Update metadata --- plugin/qgistim/metadata.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin/qgistim/metadata.txt b/plugin/qgistim/metadata.txt index c8792a3..f3ed907 100644 --- a/plugin/qgistim/metadata.txt +++ b/plugin/qgistim/metadata.txt @@ -4,13 +4,13 @@ [general] name=Qgis-Tim -qgisMinimumVersion=3.28 -description=QGIS plugin to setup TimML multi-layer analytic elements -version=0.6.0 +qgisMinimumVersion=3.40 +description=QGIS plugin to setup Timflow multi-layer analytic elements +version=0.7.0 author=Deltares email=huitebootsma@gmail.com -about=QGIS plugin to setup TimML multi-layer analytic elements +about=QGIS plugin to setup Timflow multi-layer analytic elements tracker=https://github.com/Deltares/QGIS-Tim/issues repository=https://github.com/Deltares/QGIS-Tim @@ -23,7 +23,7 @@ hasProcessingProvider=no # changelog= # Tags are comma separated with spaces allowed -tags=python, groundwater, groundwater modeling, analytic element, TTim, TimML +tags=python, groundwater, groundwater modeling, analytic element, TTim, TimML, Timflow homepage=https://deltares.github.io/QGIS-Tim/ category=Plugins From 8bda20f58c3607e29ce2543a05875944634aa7c1 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 13:32:16 +0200 Subject: [PATCH 10/27] Rename ImpermeableLineDoublet to ImpermeableWall --- plugin/qgistim/core/elements/__init__.py | 4 ++-- plugin/qgistim/core/elements/impermeable_line_doublet.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugin/qgistim/core/elements/__init__.py b/plugin/qgistim/core/elements/__init__.py index 59a89e2..ce106dd 100644 --- a/plugin/qgistim/core/elements/__init__.py +++ b/plugin/qgistim/core/elements/__init__.py @@ -13,7 +13,7 @@ from qgistim.core.elements.element import Element from qgistim.core.elements.head_line_sink import River from qgistim.core.elements.headwell import HeadWell, RemoteHeadWell -from qgistim.core.elements.impermeable_line_doublet import ImpermeableLineDoublet +from qgistim.core.elements.impermeable_line_doublet import ImpermeableWall from qgistim.core.elements.leaky_building_pit import LeakyBuildingPit from qgistim.core.elements.leaky_line_doublet import LeakyWall from qgistim.core.elements.line_sink_ditch import Ditch @@ -37,7 +37,7 @@ River, Ditch, CircularAreaSink, - ImpermeableLineDoublet, + ImpermeableWall, LeakyWall, PolygonAreaSink, PolygonSemiConfinedTop, diff --git a/plugin/qgistim/core/elements/impermeable_line_doublet.py b/plugin/qgistim/core/elements/impermeable_line_doublet.py index f1de5ef..f7bccec 100644 --- a/plugin/qgistim/core/elements/impermeable_line_doublet.py +++ b/plugin/qgistim/core/elements/impermeable_line_doublet.py @@ -7,7 +7,7 @@ from qgistim.core.schemata import Membership, Positive, Required -class ImpermeableLineDoubletSchema(RowWiseSchema): +class ImpermeableWallSchema(RowWiseSchema): timml_schemata = { "geometry": Required(), "order": Required(Positive()), @@ -15,7 +15,7 @@ class ImpermeableLineDoubletSchema(RowWiseSchema): } -class ImpermeableLineDoublet(Element): +class ImpermeableWall(Element): element_type = "Impermeable Wall" geometry_type = "Linestring" timml_attributes = ( @@ -26,7 +26,7 @@ class ImpermeableLineDoublet(Element): timml_defaults = { "order": QgsDefaultValue("4"), } - schema = ImpermeableLineDoubletSchema() + schema = ImpermeableWallSchema() @classmethod def renderer(cls) -> QgsSingleSymbolRenderer: @@ -41,7 +41,7 @@ def process_timml_row(self, row, other=None): } def to_ttim(self, other): - # TTim doesn't have an ImpermeableLineDoublet, we need to add "imp" as + # TTim doesn't have an ImpermeableWall, we need to add "imp" as # the resistance entry. _, data = self.to_timml(other) out = [] From 817026c6c7a688a7eb35f43ad4f53eb1e2c30808 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 14:12:46 +0200 Subject: [PATCH 11/27] Update module names --- gistim/compute.py | 65 ++++++++++++++++--------------- plugin/qgistim/core/formatting.py | 10 ++--- 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/gistim/compute.py b/gistim/compute.py index bfb7e2e..cbc1b1d 100644 --- a/gistim/compute.py +++ b/gistim/compute.py @@ -6,34 +6,33 @@ import numpy as np import pandas as pd +import timflow import xarray as xr -from timflow import steady as timml -from timflow import transient as ttim from gistim.geopackage import CoordinateReferenceSystem, write_geopackage from gistim.netcdf import write_raster, write_ugrid TIMML_MAPPING = { - "Constant": timml.Constant, - "Uflow": timml.Uflow, - "CircAreaSink": timml.CircAreaSink, - "Well": timml.Well, - "HeadWell": timml.HeadWell, - "PolygonInhomMaq": timml.PolygonInhomMaq, - "RiverString": timml.RiverString, - "DitchString": timml.DitchString, - "LeakyWallString": timml.LeakyWallString, - "ImpermeableWallString": timml.ImpermeableWallString, - "BuildingPit": timml.BuildingPitMaq, - "LeakyBuildingPit": timml.LeakyBuildingPitMaq, + "Constant": timflow.steady.Constant, + "Uflow": timflow.steady.Uflow, + "CircAreaSink": timflow.steady.CircAreaSink, + "Well": timflow.steady.Well, + "HeadWell": timflow.steady.HeadWell, + "PolygonInhomMaq": timflow.steady.PolygonInhomMaq, + "RiverString": timflow.steady.RiverString, + "DitchString": timflow.steady.DitchString, + "LeakyWallString": timflow.steady.LeakyWallString, + "ImpermeableWallString": timflow.steady.ImpermeableWallString, + "BuildingPit": timflow.steady.BuildingPitMaq, + "LeakyBuildingPit": timflow.steady.LeakyBuildingPitMaq, } TTIM_MAPPING = { - "CircAreaSink": ttim.CircAreaSink, - "Well": ttim.Well, - "HeadWell": ttim.HeadWell, - "RiverString": ttim.RiverString, - "DitchString": ttim.DitchString, - "LeakyWallString": ttim.LeakyWallString, + "CircAreaSink": timflow.transient.CircAreaSink, + "Well": timflow.transient.Well, + "HeadWell": timflow.transient.HeadWell, + "RiverString": timflow.transient.RiverString, + "DitchString": timflow.transient.DitchString, + "LeakyWallString": timflow.transient.LeakyWallString, } @@ -49,14 +48,14 @@ def initialize_elements(model, mapping, data): def initialize_timml(data): aquifer = data.pop("ModelMaq") - timml_model = timml.ModelMaq(**aquifer) + timml_model = timflow.steady.ModelMaq(**aquifer) elements = initialize_elements(timml_model, TIMML_MAPPING, data) return timml_model, elements def initialize_ttim(data, timml_model): aquifer = data.pop("ModelMaq") - ttim_model = ttim.ModelMaq(**aquifer, steady=timml_model) + ttim_model = timflow.transient.ModelMaq(**aquifer, steady=timml_model) elements = initialize_elements(ttim_model, TTIM_MAPPING, data) return ttim_model, elements @@ -68,7 +67,7 @@ def headgrid(model, **kwargs): @headgrid.register def _( - model: timml.Model, + model: timflow.steady.Model, xmin: float, xmax: float, ymin: float, @@ -82,7 +81,7 @@ def _( Parameters ---------- - model: timml.Model + model: timflow.steady.Model Solved model to get heads from data: Dict[str, Any] @@ -107,7 +106,7 @@ def _( @headgrid.register def _( - model: ttim.ModelMaq, + model: timflow.transient.ModelMaq, xmin: float, xmax: float, ymin: float, @@ -150,7 +149,7 @@ def compute_head_observations(model, observations): @compute_head_observations.register def _( - model: timml.Model, + model: timflow.steady.Model, observations: Dict, **_, ) -> Dict[str, pd.DataFrame]: @@ -169,7 +168,7 @@ def _( @compute_head_observations.register def _( - model: ttim.ModelMaq, observations: Dict, start_date: pd.Timestamp + model: timflow.transient.ModelMaq, observations: Dict, start_date: pd.Timestamp ) -> Dict[str, pd.DataFrame]: d = { "geometry": [], @@ -205,7 +204,7 @@ def extract_discharges(elements, nlayers, **_): for layername, content in elements.items(): sample = content[0] - if isinstance(sample, timml.WellBase): + if isinstance(sample, timflow.steady.WellBase): table_rows = [] for well in content: row = {f"discharge_layer{i}": q for i, q in enumerate(well.discharge())} @@ -216,7 +215,9 @@ def extract_discharges(elements, nlayers, **_): table_rows.append(row) tables[f"discharge-{layername}"] = pd.DataFrame.from_records(table_rows) - elif isinstance(sample, (timml.DitchString, timml.RiverString)): + elif isinstance( + sample, (timflow.steady.DitchString, timflow.steady.RiverString) + ): table_rows = [] for linestring in content: discharges = linestring.discharge_per_linesink() @@ -239,7 +240,7 @@ def compute_discharge_observations(model, observations): @compute_discharge_observations.register -def _(model: timml.Model, observations: Dict): +def _(model: timflow.steady.Model, observations: Dict): table_rows = [] for kwargs in observations: xy = kwargs["xy"] @@ -261,13 +262,13 @@ def _(model: timml.Model, observations: Dict): @compute_discharge_observations.register -def _(model: ttim.ModelMaq, observations: Dict): +def _(model: timflow.transient.ModelMaq, observations: Dict): # intnormflux is not supported by ttim (yet). return None def write_output( - model: Union[timml.Model, ttim.ModelMaq], + model: Union[timflow.steady.Model, timflow.transient.ModelMaq], elements: Dict[str, Any], data: Dict[str, Any], path: Union[pathlib.Path, str], diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index 76f6d37..7d934c6 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -148,7 +148,7 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): if plugin_name == "Head Observation": # Should not be added to the model. # Would result in e.g.: - # observation_piezometer_0 = timml.head( + # observation_piezometer_0 = timflow.steady.head( # x=10.0, # y=20.0, # ) @@ -164,7 +164,7 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): else: # Has to be added to the model. # Would result in e.g.: - # timml_extraction_0 = timml.Well( + # timml_extraction_0 = timflow.steady.Well( # model=timml_model, # ... # ) @@ -183,9 +183,9 @@ def timml_script_content(data: Dict[str, Any]): strings = [ "import numpy as np", - "from timflow import steady as timml", + "import timflow", "", - f"timml_model = timml.ModelMaq(\n{format_kwargs(aquifer_data)}\n)", + f"timml_model = timflow.steady.ModelMaq(\n{format_kwargs(aquifer_data)}\n)", ] element_strings, observations = elements_and_observations( @@ -215,7 +215,7 @@ def ttim_script(timml_data: Dict[str, Any], ttim_data: Dict[str, Any]) -> str: data.pop("start_date") strings.append( - f"\nttim_model = ttim.ModelMaq(\n{format_kwargs(aquifer_data)}\n{PREFIX}steady=timml_model,\n)" + f"\nttim_model = timflow.transient.ModelMaq(\n{format_kwargs(aquifer_data)}\n{PREFIX}steady=timml_model,\n)" ) element_strings, observations = elements_and_observations( From c59b65ef7edf5e36f06b29137f73b95e761a89ad Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 15:12:51 +0200 Subject: [PATCH 12/27] Remove unused import --- plugin/qgistim/core/formatting.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index 7d934c6..461d3e5 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -207,7 +207,6 @@ def timml_script(data: Dict[str, Any]) -> str: def ttim_script(timml_data: Dict[str, Any], ttim_data: Dict[str, Any]) -> str: strings, _ = timml_script_content(timml_data) - strings.insert(2, "from timflow import transient as ttim") data = ttim_data.copy() # avoid side-effects aquifer_data = data.pop("timml Aquifer:Aquifer") From 123196497b7707ce5bc9b374c0eddb15db8d4bd4 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 15:42:55 +0200 Subject: [PATCH 13/27] Fix formatting --- plugin/qgistim/core/formatting.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index 461d3e5..09c7a1a 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -137,6 +137,11 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): strings = [] observations = [] model_string = textwrap.indent(f"model={tim}_model,", prefix=PREFIX) + if tim == "ttim": + module_name = "transient" + else: + module_name = "steady" + for layername, element_data in data.items(): prefix, name = layername.split(":") plugin_name = re.split("timml |ttim ", prefix)[1] @@ -170,7 +175,7 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): # ) kwargs = format_kwargs(kwargs) strings.append( - f"{tim}_{sanitized(name)}_{i} = {tim}.{tim_name}(\n{model_string}\n{kwargs}\n)" + f"{tim}_{sanitized(name)}_{i} = timflow.{module_name}.{tim_name}(\n{model_string}\n{kwargs}\n)" ) return strings, observations From 19136c095167a162e6da18963d1a30c7cfe8caf8 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 15:58:32 +0200 Subject: [PATCH 14/27] Add TODO --- plugin/qgistim/core/formatting.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index 09c7a1a..920261c 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -137,6 +137,8 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): strings = [] observations = [] model_string = textwrap.indent(f"model={tim}_model,", prefix=PREFIX) + # TODO: Rename everything to "steady" and "transient" instead of "timml" and + # "ttim", and remove the conditional. ``tim`` will call if tim == "ttim": module_name = "transient" else: From b1a7b180e8451fc9dc45de845a3e1606a30bfb1a Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 16:16:48 +0200 Subject: [PATCH 15/27] remove unnecessary mention of "timml" --- plugin/qgistim/qgistim.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugin/qgistim/qgistim.py b/plugin/qgistim/qgistim.py index 8eebe69..cd077a9 100644 --- a/plugin/qgistim/qgistim.py +++ b/plugin/qgistim/qgistim.py @@ -41,11 +41,9 @@ def add_action(self, icon_name, text="", callback=None, add_to_menu=False): def initGui(self): icon_name = "icon.png" - self.action_timml = self.add_action( - icon_name, "QGIS-Tim", self.toggle_timml, True - ) + self.action_tim = self.add_action(icon_name, "QGIS-Tim", self.toggle_tim, True) - def toggle_timml(self): + def toggle_tim(self): if self.tim_widget is None: from .widgets.tim_widget import QgisTimWidget From 57f9f6c7a6a9a5ec99a0759b56f6be617089cca6 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 16:28:34 +0200 Subject: [PATCH 16/27] Rename variables and functions to steady and transient --- gistim/compute.py | 48 ++++++++++++----------- plugin/qgistim/core/formatting.py | 64 ++++++++++++++++--------------- 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/gistim/compute.py b/gistim/compute.py index cbc1b1d..ea065df 100644 --- a/gistim/compute.py +++ b/gistim/compute.py @@ -12,7 +12,7 @@ from gistim.geopackage import CoordinateReferenceSystem, write_geopackage from gistim.netcdf import write_raster, write_ugrid -TIMML_MAPPING = { +STEADY_MAPPING = { "Constant": timflow.steady.Constant, "Uflow": timflow.steady.Uflow, "CircAreaSink": timflow.steady.CircAreaSink, @@ -26,7 +26,7 @@ "BuildingPit": timflow.steady.BuildingPitMaq, "LeakyBuildingPit": timflow.steady.LeakyBuildingPitMaq, } -TTIM_MAPPING = { +TRANSIENT_MAPPING = { "CircAreaSink": timflow.transient.CircAreaSink, "Well": timflow.transient.Well, "HeadWell": timflow.transient.HeadWell, @@ -46,23 +46,23 @@ def initialize_elements(model, mapping, data): return elements -def initialize_timml(data): +def initialize_steady(data): aquifer = data.pop("ModelMaq") - timml_model = timflow.steady.ModelMaq(**aquifer) - elements = initialize_elements(timml_model, TIMML_MAPPING, data) - return timml_model, elements + steady_model = timflow.steady.ModelMaq(**aquifer) + elements = initialize_elements(steady_model, STEADY_MAPPING, data) + return steady_model, elements -def initialize_ttim(data, timml_model): +def initialize_transient(data, steady_model): aquifer = data.pop("ModelMaq") - ttim_model = timflow.transient.ModelMaq(**aquifer, steady=timml_model) - elements = initialize_elements(ttim_model, TTIM_MAPPING, data) - return ttim_model, elements + transient_model = timflow.transient.ModelMaq(**aquifer, steady=steady_model) + elements = initialize_elements(transient_model, TRANSIENT_MAPPING, data) + return transient_model, elements @singledispatch def headgrid(model, **kwargs): - raise TypeError("Expected timml or ttim model") + raise TypeError("Expected steady or transient model") @headgrid.register @@ -76,7 +76,7 @@ def _( **_, ) -> xr.DataArray: """ - Compute the headgrid of the TimML model, and store the results + Compute the headgrid of the steady model, and store the results in an xarray DataArray with the appropriate dimensions. Parameters @@ -144,7 +144,7 @@ def _( @singledispatch def compute_head_observations(model, observations): - raise TypeError("Expected timml or ttim model") + raise TypeError("Expected steady or transient model") @compute_head_observations.register @@ -236,7 +236,7 @@ def extract_discharges(elements, nlayers, **_): @singledispatch def compute_discharge_observations(model, observations): - raise TypeError("Expected timml or ttim model") + raise TypeError("Expected steady or transient model") @compute_discharge_observations.register @@ -318,11 +318,11 @@ def compute_steady( with open(path, "r") as f: data = json.load(f) - timml_model, elements = initialize_timml(data["timml"]) - timml_model.solve() + steady_model, elements = initialize_steady(data["timml"]) + steady_model.solve() write_output( - timml_model, + steady_model, elements, data, path, @@ -336,14 +336,16 @@ def compute_transient( with open(path, "r") as f: data = json.load(f) - timml_model, _ = initialize_timml(data["timml"]) - ttim_model, ttim_elements = initialize_ttim(data["ttim"], timml_model) - timml_model.solve() - ttim_model.solve() + steady_model, _ = initialize_steady(data["timml"]) + transient_model, transient_elements = initialize_transient( + data["ttim"], steady_model + ) + steady_model.solve() + transient_model.solve() write_output( - ttim_model, - ttim_elements, + transient_model, + transient_elements, data, path, ) diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index 920261c..2e8cd64 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -12,7 +12,7 @@ from qgistim.widgets.compute_widget import OutputOptions -TIMML_MAPPING = { +STEADY_MAPPING = { "Constant": "Constant", "Uniform Flow": "Uflow", "Circular Area Sink": "CircAreaSink", @@ -33,7 +33,7 @@ } # In TTim, a constant or uniform flow may be added, but they have no effect on # the transient superposed result. -TTIM_MAPPING = { +TRANSIENT_MAPPING = { "Constant": None, "Uniform Flow": None, "Circular Area Sink": "CircAreaSink", @@ -183,7 +183,7 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): return strings, observations -def timml_script_content(data: Dict[str, Any]): +def steady_script_content(data: Dict[str, Any]): data = data.copy() # avoid side-effects aquifer_data = data.pop("timml Aquifer:Aquifer") data.pop("timml Domain:Domain") @@ -196,14 +196,14 @@ def timml_script_content(data: Dict[str, Any]): ] element_strings, observations = elements_and_observations( - data, TIMML_MAPPING, tim="timml" + data, STEADY_MAPPING, tim="timml" ) strings = strings + element_strings return strings, observations -def timml_script(data: Dict[str, Any]) -> str: - strings, observations = timml_script_content(data) +def steady_script(data: Dict[str, Any]) -> str: + strings, observations = steady_script_content(data) strings.append("\ntimml_model.solve()\n") xg, yg, _ = headgrid_code(data["timml Domain:Domain"]) strings.append(f"head = timml_model.headgrid(\n{xg},\n{yg}\n)") @@ -212,10 +212,12 @@ def timml_script(data: Dict[str, Any]) -> str: return "\n".join(strings) -def ttim_script(timml_data: Dict[str, Any], ttim_data: Dict[str, Any]) -> str: - strings, _ = timml_script_content(timml_data) +def transient_script( + steady_data: Dict[str, Any], transient_data: Dict[str, Any] +) -> str: + strings, _ = steady_script_content(steady_data) - data = ttim_data.copy() # avoid side-effects + data = transient_data.copy() # avoid side-effects aquifer_data = data.pop("timml Aquifer:Aquifer") domain_data = data.pop("timml Domain:Domain") data.pop("start_date") @@ -225,7 +227,7 @@ def ttim_script(timml_data: Dict[str, Any], ttim_data: Dict[str, Any]) -> str: ) element_strings, observations = elements_and_observations( - data, TTIM_MAPPING, tim="ttim" + data, TRANSIENT_MAPPING, tim="ttim" ) strings = strings + element_strings strings.append("\ntimml_model.solve()\nttim_model.solve()\n") @@ -240,13 +242,13 @@ def ttim_script(timml_data: Dict[str, Any], ttim_data: Dict[str, Any]) -> str: def data_to_script( - timml_data: Dict[str, Any], - ttim_data: Union[Dict[str, Any], None], + steady_data: Dict[str, Any], + transient_data: Union[Dict[str, Any], None], ) -> str: - if ttim_data is None: - return timml_script(timml_data) + if transient_data is None: + return steady_script(steady_data) else: - return ttim_script(timml_data, ttim_data) + return transient_script(steady_data, transient_data) def json_elements_and_observations(data, mapping: Dict[str, str]): @@ -273,14 +275,14 @@ def json_elements_and_observations(data, mapping: Dict[str, str]): return tim_data, observations, discharge_observations -def timml_json( - timml_data: Dict[str, Any], +def steady_json( + steady_data: Dict[str, Any], output_options: OutputOptions, ) -> Dict[str, Any]: """ Take the data and add: - * the TimML type + * the timflow type * the layer name Parameters @@ -294,10 +296,10 @@ def timml_json( Data ready to dump to JSON. """ # Process TimML elements - data = timml_data.copy() # avoid side-effects + data = steady_data.copy() # avoid side-effects domain_data = data.pop("timml Domain:Domain") elements, observations, discharge_observations = json_elements_and_observations( - data, mapping=TIMML_MAPPING + data, mapping=STEADY_MAPPING ) json_data = { "timml": elements, @@ -311,18 +313,18 @@ def timml_json( return json_data -def ttim_json( - timml_data: Dict[str, Any], - ttim_data: Dict[str, Any], +def transient_json( + steady_data: Dict[str, Any], + transient_data: Dict[str, Any], output_options: OutputOptions, ) -> Dict[str, Any]: - json_data = timml_json(timml_data, output_options) + json_data = steady_json(steady_data, output_options) - data = ttim_data.copy() + data = transient_data.copy() domain_data = data.pop("timml Domain:Domain") start_date = data.pop("start_date") elements, observations, _ = json_elements_and_observations( - data, mapping=TTIM_MAPPING + data, mapping=TRANSIENT_MAPPING ) json_data["ttim"] = elements @@ -334,11 +336,11 @@ def ttim_json( def data_to_json( - timml_data: Dict[str, Any], - ttim_data: Union[Dict[str, Any], None], + steady_data: Dict[str, Any], + transient_data: Union[Dict[str, Any], None], output_options: OutputOptions, ) -> Dict[str, Any]: - if ttim_data is None: - return timml_json(timml_data, output_options) + if transient_data is None: + return steady_json(steady_data, output_options) else: - return ttim_json(timml_data, ttim_data, output_options) + return transient_json(steady_data, transient_data, output_options) From afbb0c55a5ded2d73d51fabf589134146d7aaffc Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 16:39:38 +0200 Subject: [PATCH 17/27] Rename validation scheme attributes --- plugin/qgistim/core/elements/aquifer.py | 8 ++++---- plugin/qgistim/core/elements/building_pit.py | 6 +++--- .../qgistim/core/elements/circular_area_sink.py | 6 +++--- plugin/qgistim/core/elements/constant.py | 4 ++-- .../core/elements/discharge_observation.py | 2 +- plugin/qgistim/core/elements/domain.py | 2 +- plugin/qgistim/core/elements/head_line_sink.py | 6 +++--- plugin/qgistim/core/elements/headwell.py | 6 +++--- .../core/elements/impermeable_line_doublet.py | 2 +- .../qgistim/core/elements/leaky_building_pit.py | 6 +++--- .../qgistim/core/elements/leaky_line_doublet.py | 2 +- plugin/qgistim/core/elements/line_sink_ditch.py | 6 +++--- plugin/qgistim/core/elements/observation.py | 4 ++-- .../qgistim/core/elements/polygon_area_sink.py | 2 +- .../core/elements/polygon_inhomogeneity.py | 6 +++--- .../core/elements/polygon_semi_confined_top.py | 2 +- plugin/qgistim/core/elements/schemata.py | 16 ++++++++++------ plugin/qgistim/core/elements/uniform_flow.py | 4 ++-- plugin/qgistim/core/elements/well.py | 8 ++++---- 19 files changed, 51 insertions(+), 47 deletions(-) diff --git a/plugin/qgistim/core/elements/aquifer.py b/plugin/qgistim/core/elements/aquifer.py index 5c04091..6dac140 100644 --- a/plugin/qgistim/core/elements/aquifer.py +++ b/plugin/qgistim/core/elements/aquifer.py @@ -19,7 +19,7 @@ class AquiferSchema(TableSchema): - timml_schemata = { + steady_schemata = { "layer": AllRequired(Range()), "aquifer_top": AllRequired(StrictlyDecreasing()), "aquifer_bottom": AllRequired(StrictlyDecreasing()), @@ -28,18 +28,18 @@ class AquiferSchema(TableSchema): "semiconf_top": OptionalFirstOnly(), "semiconf_head": OptionalFirstOnly(), } - timml_consistency_schemata = ( + steady_consistency_schemata = ( SemiConfined(), AllGreaterEqual("aquifer_top", "aquifer_bottom"), ) - ttim_schemata = { + transient_schemata = { "aquitard_s": OffsetAllRequired(Positive()), "aquifer_s": AllRequired(Positive()), } class TemporalSettingsSchema(SingleRowSchema): - ttim_schemata = { + transient_schemata = { "time_min": Required(StrictlyPositive()), "laplace_inversion_M": Required(StrictlyPositive()), "start_date": Required(), diff --git a/plugin/qgistim/core/elements/building_pit.py b/plugin/qgistim/core/elements/building_pit.py index 645a51c..70ff917 100644 --- a/plugin/qgistim/core/elements/building_pit.py +++ b/plugin/qgistim/core/elements/building_pit.py @@ -23,7 +23,7 @@ class BuildingPitSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "inhomogeneity_id": Required(Membership("properties inhomogeneity_id")), "order": Required(Positive()), @@ -32,7 +32,7 @@ class BuildingPitSchema(RowWiseSchema): class AssociatedBuildingPitSchema(TableSchema): - timml_schemata = { + steady_schemata = { "inhomogeneity_id": AllRequired(), "layer": AllRequired(Equals("aquifer layers")), "aquifer_top": AllRequired(StrictlyDecreasing()), @@ -43,7 +43,7 @@ class AssociatedBuildingPitSchema(TableSchema): "semiconf_head": OptionalFirstOnly(), "wall_in_layer": AllRequired(AtleastOneTrue()), } - timml_consistency_schemata = ( + steady_consistency_schemata = ( SemiConfined(), AllGreaterEqual("aquifer_top", "aquifer_bottom"), ) diff --git a/plugin/qgistim/core/elements/circular_area_sink.py b/plugin/qgistim/core/elements/circular_area_sink.py index 4c1b69b..78abfb2 100644 --- a/plugin/qgistim/core/elements/circular_area_sink.py +++ b/plugin/qgistim/core/elements/circular_area_sink.py @@ -20,17 +20,17 @@ class CircularAreaSinkSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(CircularGeometry()), "rate": Required(), "layer": Required(Membership("aquifer layers")), } - ttim_schemata = { + transient_schemata = { "time_start": Optional(Positive()), "time_end": Optional(Positive()), "timeseries_id": Optional(Membership("ttim timeseries IDs")), } - ttim_consistency_schemata = ( + transient_consistency_schemata = ( AllOrNone("time_start", "time_end", "rate_transient"), NotBoth("time_start", "timeseries_id"), ) diff --git a/plugin/qgistim/core/elements/constant.py b/plugin/qgistim/core/elements/constant.py index 085cd24..8e67a37 100644 --- a/plugin/qgistim/core/elements/constant.py +++ b/plugin/qgistim/core/elements/constant.py @@ -8,12 +8,12 @@ class ConstantSchema(SingleRowSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "head": Required(), "layer": Required(Membership("aquifer layers")), } - timml_consistency_schemata = (RequiresConfinedAquifer(),) + steady_consistency_schemata = (RequiresConfinedAquifer(),) class Constant(Element): diff --git a/plugin/qgistim/core/elements/discharge_observation.py b/plugin/qgistim/core/elements/discharge_observation.py index 4fec743..8c060dd 100644 --- a/plugin/qgistim/core/elements/discharge_observation.py +++ b/plugin/qgistim/core/elements/discharge_observation.py @@ -11,7 +11,7 @@ class DischargeObservationSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "legendre_method": Required(), "ndegrees": Required(Positive()), diff --git a/plugin/qgistim/core/elements/domain.py b/plugin/qgistim/core/elements/domain.py index cd01bd1..87b9b97 100644 --- a/plugin/qgistim/core/elements/domain.py +++ b/plugin/qgistim/core/elements/domain.py @@ -16,7 +16,7 @@ class DomainSchema(SingleRowSchema): - timml_schemata = {"geometry": Required()} + steady_schemata = {"geometry": Required()} timeseries_schemata = { "time": AllRequired(Positive(), StrictlyIncreasing()), } diff --git a/plugin/qgistim/core/elements/head_line_sink.py b/plugin/qgistim/core/elements/head_line_sink.py index 259d1a7..52c5de4 100644 --- a/plugin/qgistim/core/elements/head_line_sink.py +++ b/plugin/qgistim/core/elements/head_line_sink.py @@ -18,7 +18,7 @@ class RiverSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "head": Required(), "resistance": Required(Positive()), @@ -26,11 +26,11 @@ class RiverSchema(RowWiseSchema): "order": Required(Positive()), "layer": Required(Membership("aquifer layers")), } - ttim_consistency_schemata = ( + transient_consistency_schemata = ( AllOrNone("time_start", "time_end", "head_transient"), NotBoth("time_start", "timeseries_id"), ) - ttim_schemata = { + transient_schemata = { "time_start": Optional(Positive()), "time_end": Optional(Positive()), "timeseries_id": Optional(Membership("ttim timeseries IDs")), diff --git a/plugin/qgistim/core/elements/headwell.py b/plugin/qgistim/core/elements/headwell.py index 1de149e..715fa61 100644 --- a/plugin/qgistim/core/elements/headwell.py +++ b/plugin/qgistim/core/elements/headwell.py @@ -27,19 +27,19 @@ class HeadWellSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "head": Required(), "radius": Required(StrictlyPositive()), "resistance": Required(Positive()), "layer": Required(Membership("aquifer layers")), } - ttim_schemata = { + transient_schemata = { "time_start": Optional(Positive()), "time_end": Optional(Positive()), "timeseries_id": Optional(Membership("ttim timeseries IDs")), } - ttim_consistency_schemata = ( + transient_consistency_schemata = ( AllOrNone(("time_start", "time_end", "head_transient")), NotBoth("time_start", "timeseries_id"), ) diff --git a/plugin/qgistim/core/elements/impermeable_line_doublet.py b/plugin/qgistim/core/elements/impermeable_line_doublet.py index f7bccec..3327450 100644 --- a/plugin/qgistim/core/elements/impermeable_line_doublet.py +++ b/plugin/qgistim/core/elements/impermeable_line_doublet.py @@ -8,7 +8,7 @@ class ImpermeableWallSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "order": Required(Positive()), "layer": Required(Membership("aquifer layers")), diff --git a/plugin/qgistim/core/elements/leaky_building_pit.py b/plugin/qgistim/core/elements/leaky_building_pit.py index c46c0ac..457845b 100644 --- a/plugin/qgistim/core/elements/leaky_building_pit.py +++ b/plugin/qgistim/core/elements/leaky_building_pit.py @@ -24,7 +24,7 @@ class LeakyBuildingPitSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "inhomogeneity_id": Required(Membership("properties inhomogeneity_id")), "order": Required(Positive()), @@ -33,7 +33,7 @@ class LeakyBuildingPitSchema(RowWiseSchema): class AssociatedLeakyBuildingPitchema(TableSchema): - timml_schemata = { + steady_schemata = { "inhomogeneity_id": AllRequired(), "layer": AllRequired(Equals("aquifer layers")), "aquifer_top": AllRequired(StrictlyDecreasing()), @@ -45,7 +45,7 @@ class AssociatedLeakyBuildingPitchema(TableSchema): "resistance": RequiredFirstOnly(StrictlyPositive()), "wall_in_layer": AllRequired(AtleastOneTrue()), } - timml_consistency_schemata = ( + steady_consistency_schemata = ( SemiConfined(), AllGreaterEqual("aquifer_top", "aquifer_bottom"), ) diff --git a/plugin/qgistim/core/elements/leaky_line_doublet.py b/plugin/qgistim/core/elements/leaky_line_doublet.py index a50f878..ace3282 100644 --- a/plugin/qgistim/core/elements/leaky_line_doublet.py +++ b/plugin/qgistim/core/elements/leaky_line_doublet.py @@ -8,7 +8,7 @@ class LeakyWallSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "resistance": Required(StrictlyPositive()), "order": Required(Positive()), diff --git a/plugin/qgistim/core/elements/line_sink_ditch.py b/plugin/qgistim/core/elements/line_sink_ditch.py index 4eb99c4..096ae47 100644 --- a/plugin/qgistim/core/elements/line_sink_ditch.py +++ b/plugin/qgistim/core/elements/line_sink_ditch.py @@ -18,7 +18,7 @@ class DitchSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "discharge": Required(), "resistance": Required(Positive()), @@ -26,11 +26,11 @@ class DitchSchema(RowWiseSchema): "order": Required(Positive()), "layer": Required(Membership("aquifer layers")), } - ttim_consistency_schemata = ( + transient_consistency_schemata = ( AllOrNone("time_start", "time_end", "discharge_transient"), NotBoth("time_start", "timeseries_id"), ) - ttim_schemata = { + transient_schemata = { "time_start": Optional(Positive()), "time_end": Optional(Positive()), "timeseries_id": Optional(Membership("ttim timeseries IDs")), diff --git a/plugin/qgistim/core/elements/observation.py b/plugin/qgistim/core/elements/observation.py index 142cbab..d00106a 100644 --- a/plugin/qgistim/core/elements/observation.py +++ b/plugin/qgistim/core/elements/observation.py @@ -14,10 +14,10 @@ class HeadObservationSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), } - ttim_schemata = {"timeseries_id": Required(Membership("ttim timeseries IDs"))} + transient_schemata = {"timeseries_id": Required(Membership("ttim timeseries IDs"))} timeseries_schemata = { "timeseries_id": AllRequired(), "time": AllRequired(Positive(), StrictlyIncreasing()), diff --git a/plugin/qgistim/core/elements/polygon_area_sink.py b/plugin/qgistim/core/elements/polygon_area_sink.py index bfbcf36..4733470 100644 --- a/plugin/qgistim/core/elements/polygon_area_sink.py +++ b/plugin/qgistim/core/elements/polygon_area_sink.py @@ -10,7 +10,7 @@ class PolygonAreaSinkSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "rate": Required(), "order": Required(Positive()), diff --git a/plugin/qgistim/core/elements/polygon_inhomogeneity.py b/plugin/qgistim/core/elements/polygon_inhomogeneity.py index a2d078d..b5d540c 100644 --- a/plugin/qgistim/core/elements/polygon_inhomogeneity.py +++ b/plugin/qgistim/core/elements/polygon_inhomogeneity.py @@ -22,7 +22,7 @@ class PolygonInhomogeneitySchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "inhomogeneity_id": Required(Membership("properties inhomogeneity_id")), "order": Required(Positive()), @@ -31,7 +31,7 @@ class PolygonInhomogeneitySchema(RowWiseSchema): class AssociatedPolygonInhomogeneitySchema(TableSchema): - timml_schemata = { + steady_schemata = { "inhomogeneity_id": AllRequired(), "layer": AllRequired(Equals("aquifer layers")), "aquifer_top": AllRequired(StrictlyDecreasing()), @@ -42,7 +42,7 @@ class AssociatedPolygonInhomogeneitySchema(TableSchema): "semiconf_head": OptionalFirstOnly(), "rate": OptionalFirstOnly(), } - timml_consistency_schemata = ( + steady_consistency_schemata = ( SemiConfined(), AllGreaterEqual("aquifer_top", "aquifer_bottom"), ) diff --git a/plugin/qgistim/core/elements/polygon_semi_confined_top.py b/plugin/qgistim/core/elements/polygon_semi_confined_top.py index b5d5f86..0bb3a7e 100644 --- a/plugin/qgistim/core/elements/polygon_semi_confined_top.py +++ b/plugin/qgistim/core/elements/polygon_semi_confined_top.py @@ -10,7 +10,7 @@ class PolygonSemiConfinedTopSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "aquitard_c": Required(StrictlyPositive()), "semiconf_top": Required(), diff --git a/plugin/qgistim/core/elements/schemata.py b/plugin/qgistim/core/elements/schemata.py index ee8ed47..10d5b36 100644 --- a/plugin/qgistim/core/elements/schemata.py +++ b/plugin/qgistim/core/elements/schemata.py @@ -19,10 +19,10 @@ class ValidationData(NamedTuple): class SchemaBase(abc.ABC): # TODO: check for presence of columns - timml_schemata: Dict[str, Union[SchemaContainer, IterableSchemaContainer]] = {} - timml_consistency_schemata: Tuple[ConsistencySchema] = () - ttim_schemata: Dict[str, Union[SchemaContainer, IterableSchemaContainer]] = {} - ttim_consistency_schemata: Tuple[ConsistencySchema] = () + steady_schemata: Dict[str, Union[SchemaContainer, IterableSchemaContainer]] = {} + steady_consistency_schemata: Tuple[ConsistencySchema] = () + transient_schemata: Dict[str, Union[SchemaContainer, IterableSchemaContainer]] = {} + transient_consistency_schemata: Tuple[ConsistencySchema] = () timeseries_schemata: Dict[str, Union[SchemaContainer, IterableSchemaContainer]] = {} @staticmethod @@ -55,7 +55,7 @@ def validate_timml( cls, name: str, data: Dict[str, Any], other=None ) -> Dict[str, List]: vd = ValidationData( - cls.timml_schemata, cls.timml_consistency_schemata, name, data, other + cls.steady_schemata, cls.steady_consistency_schemata, name, data, other ) return cls._validate(vd) @@ -64,7 +64,11 @@ def validate_ttim( cls, name: str, data: Dict[str, Any], other=None ) -> Dict[str, List]: vd = ValidationData( - cls.ttim_schemata, cls.ttim_consistency_schemata, name, data, other + cls.transient_schemata, + cls.transient_consistency_schemata, + name, + data, + other, ) return cls._validate(vd) diff --git a/plugin/qgistim/core/elements/uniform_flow.py b/plugin/qgistim/core/elements/uniform_flow.py index 8e01b52..e2ddf0b 100644 --- a/plugin/qgistim/core/elements/uniform_flow.py +++ b/plugin/qgistim/core/elements/uniform_flow.py @@ -7,11 +7,11 @@ class UniformFlowSchema(SingleRowSchema): - timml_schemata = { + steady_schemata = { "slope": Required(), "angle": Required(), } - timml_consistency_schemata = (RequiresConfinedAquifer(),) + steady_consistency_schemata = (RequiresConfinedAquifer(),) class UniformFlow(Element): diff --git a/plugin/qgistim/core/elements/well.py b/plugin/qgistim/core/elements/well.py index affaf25..f1feec9 100644 --- a/plugin/qgistim/core/elements/well.py +++ b/plugin/qgistim/core/elements/well.py @@ -20,22 +20,22 @@ class WellSchema(RowWiseSchema): - timml_schemata = { + steady_schemata = { "geometry": Required(), "discharge": Required(), "radius": Required(StrictlyPositive()), "resistance": Required(Positive()), "layer": Required(Membership("aquifer layers")), } - timml_consistency_schemata = (ConditionallyRequired("slug", "caisson_radius"),) - ttim_schemata = { + steady_consistency_schemata = (ConditionallyRequired("slug", "caisson_radius"),) + transient_schemata = { "caisson_radius": Optional(StrictlyPositive()), "slug": Required(), "time_start": Optional(Positive()), "time_end": Optional(Positive()), "timeseries_id": Optional(Membership("ttim timeseries IDs")), } - ttim_consistency_schemata = ( + transient_consistency_schemata = ( AllOrNone(("time_start", "time_end", "discharge_transient")), NotBoth("time_start", "timeseries_id"), ) From b99d60dad25330e4abcadfe6c5fd0362f8ae1b3b Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 16:54:03 +0200 Subject: [PATCH 18/27] Rename class variables --- plugin/qgistim/core/elements/aquifer.py | 6 +++--- plugin/qgistim/core/elements/building_pit.py | 4 ++-- .../core/elements/circular_area_sink.py | 4 ++-- plugin/qgistim/core/elements/constant.py | 2 +- .../core/elements/discharge_observation.py | 4 ++-- plugin/qgistim/core/elements/domain.py | 2 +- plugin/qgistim/core/elements/element.py | 20 +++++++++---------- .../qgistim/core/elements/head_line_sink.py | 6 +++--- plugin/qgistim/core/elements/headwell.py | 6 +++--- .../core/elements/impermeable_line_doublet.py | 4 ++-- .../core/elements/leaky_building_pit.py | 4 ++-- .../core/elements/leaky_line_doublet.py | 4 ++-- .../qgistim/core/elements/line_sink_ditch.py | 6 +++--- plugin/qgistim/core/elements/observation.py | 8 ++++---- .../core/elements/polygon_area_sink.py | 4 ++-- .../core/elements/polygon_inhomogeneity.py | 4 ++-- .../elements/polygon_semi_confined_top.py | 4 ++-- plugin/qgistim/core/elements/uniform_flow.py | 2 +- plugin/qgistim/core/elements/well.py | 6 +++--- 19 files changed, 50 insertions(+), 50 deletions(-) diff --git a/plugin/qgistim/core/elements/aquifer.py b/plugin/qgistim/core/elements/aquifer.py index 6dac140..6381831 100644 --- a/plugin/qgistim/core/elements/aquifer.py +++ b/plugin/qgistim/core/elements/aquifer.py @@ -49,7 +49,7 @@ class TemporalSettingsSchema(SingleRowSchema): class Aquifer(TransientElement): element_type = "Aquifer" geometry_type = "No Geometry" - timml_attributes = [ + steady_attributes = [ QgsField("layer", QVariant.Int), QgsField("aquifer_top", QVariant.Double), QgsField("aquifer_bottom", QVariant.Double), @@ -62,12 +62,12 @@ class Aquifer(TransientElement): QgsField("aquitard_npor", QVariant.Double), QgsField("aquifer_npor", QVariant.Double), ] - ttim_attributes = ( + transient_attributes = ( QgsField("time_min", QVariant.Double), QgsField("laplace_inversion_M", QVariant.Int), QgsField("start_date", QVariant.DateTime), ) - ttim_defaults = { + transient_defaults = { "time_min": QgsDefaultValue("0.01"), "laplace_inversion_M": QgsDefaultValue("10"), } diff --git a/plugin/qgistim/core/elements/building_pit.py b/plugin/qgistim/core/elements/building_pit.py index 70ff917..fe38fdf 100644 --- a/plugin/qgistim/core/elements/building_pit.py +++ b/plugin/qgistim/core/elements/building_pit.py @@ -52,7 +52,7 @@ class AssociatedBuildingPitSchema(TableSchema): class BuildingPit(AssociatedElement): element_type = "Building Pit" geometry_type = "Polygon" - timml_attributes = ( + steady_attributes = ( QgsField("inhomogeneity_id", QVariant.Int), QgsField("order", QVariant.Int), QgsField("ndegrees", QVariant.Int), @@ -70,7 +70,7 @@ class BuildingPit(AssociatedElement): QgsField("aquitard_npor", QVariant.Double), QgsField("aquifer_npor", QVariant.Double), ] - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), "ndegrees": QgsDefaultValue("6"), "inhomogeneity_id": QgsDefaultValue("1"), diff --git a/plugin/qgistim/core/elements/circular_area_sink.py b/plugin/qgistim/core/elements/circular_area_sink.py index 78abfb2..dae5569 100644 --- a/plugin/qgistim/core/elements/circular_area_sink.py +++ b/plugin/qgistim/core/elements/circular_area_sink.py @@ -44,7 +44,7 @@ class CircularAreaSinkSchema(RowWiseSchema): class CircularAreaSink(TransientElement): element_type = "Circular Area Sink" geometry_type = "Polygon" - timml_attributes = ( + steady_attributes = ( QgsField("rate", QVariant.Double), QgsField("layer", QVariant.Int), QgsField("label", QVariant.String), @@ -53,7 +53,7 @@ class CircularAreaSink(TransientElement): QgsField("rate_transient", QVariant.Double), QgsField("timeseries_id", QVariant.Int), ) - ttim_attributes = ( + transient_attributes = ( QgsField("timeseries_id", QVariant.Int), QgsField("time_start", QVariant.Double), QgsField("rate", QVariant.Double), diff --git a/plugin/qgistim/core/elements/constant.py b/plugin/qgistim/core/elements/constant.py index 8e67a37..6199e29 100644 --- a/plugin/qgistim/core/elements/constant.py +++ b/plugin/qgistim/core/elements/constant.py @@ -19,7 +19,7 @@ class ConstantSchema(SingleRowSchema): class Constant(Element): element_type = "Constant" geometry_type = "Point" - timml_attributes = ( + steady_attributes = ( QgsField("head", QVariant.Double), QgsField("layer", QVariant.Int), QgsField("label", QVariant.String), diff --git a/plugin/qgistim/core/elements/discharge_observation.py b/plugin/qgistim/core/elements/discharge_observation.py index 8c060dd..d7da210 100644 --- a/plugin/qgistim/core/elements/discharge_observation.py +++ b/plugin/qgistim/core/elements/discharge_observation.py @@ -21,12 +21,12 @@ class DischargeObservationSchema(RowWiseSchema): class DischargeObservation(Element): element_type = "Discharge Observation" geometry_type = "Linestring" - timml_attributes = ( + steady_attributes = ( QgsField("legendre_method", QVariant.Bool), QgsField("ndegrees", QVariant.Int), QgsField("label", QVariant.String), ) - timml_defaults = { + steady_defaults = { "legendre_method": QgsDefaultValue("True"), "ndegrees": QgsDefaultValue("10"), } diff --git a/plugin/qgistim/core/elements/domain.py b/plugin/qgistim/core/elements/domain.py index 87b9b97..68ceaf0 100644 --- a/plugin/qgistim/core/elements/domain.py +++ b/plugin/qgistim/core/elements/domain.py @@ -25,7 +25,7 @@ class DomainSchema(SingleRowSchema): class Domain(TransientElement): element_type = "Domain" geometry_type = "Polygon" - ttim_attributes = (QgsField("time", QVariant.Double),) + transient_attributes = (QgsField("time", QVariant.Double),) schema = DomainSchema() def __init__(self, path: str, name: str): diff --git a/plugin/qgistim/core/elements/element.py b/plugin/qgistim/core/elements/element.py index 6792849..2618368 100644 --- a/plugin/qgistim/core/elements/element.py +++ b/plugin/qgistim/core/elements/element.py @@ -110,12 +110,12 @@ class Element(ExtractorMixin, abc.ABC): element_type = None geometry_type = None - timml_attributes = () - ttim_attributes = () + steady_attributes = () + transient_attributes = () assoc_attributes = () transient_columns = () - timml_defaults = {} - ttim_defaults = {} + steady_defaults = {} + transient_defaults = {} assoc_defaults = {} def _initialize_default(self, path, name): @@ -164,7 +164,7 @@ def create_timml_layer(self, crs: Any): crs=crs, geometry_type=self.geometry_type, name=self.timml_name, - attributes=self.timml_attributes, + attributes=self.steady_attributes, ) def create_ttim_layer(self, crs: Any): @@ -181,7 +181,7 @@ def create_layers(self, crs: Any): def set_defaults(self): for layer, defaults in zip( (self.timml_layer, self.ttim_layer, self.assoc_layer), - (self.timml_defaults, self.ttim_defaults, self.assoc_defaults), + (self.steady_defaults, self.transient_defaults, self.assoc_defaults), ): if layer is None: continue @@ -267,7 +267,7 @@ def _check_table_columns(attributes, layer) -> Dict[str, List]: def check_timml_columns(self): return self._check_table_columns( - attributes=self.timml_attributes, layer=self.timml_layer + attributes=self.steady_attributes, layer=self.timml_layer ) def to_timml(self, other=None) -> ElementExtraction: @@ -368,7 +368,7 @@ def create_ttim_layer(self, crs: Any): crs=crs, geometry_type="No Geometry", name=self.ttim_name, - attributes=self.ttim_attributes, + attributes=self.transient_attributes, ) def ttim_layer_from_geopackage(self): @@ -436,7 +436,7 @@ def transient_input( def check_ttim_columns(self): return self._check_table_columns( - attributes=self.ttim_attributes, layer=self.ttim_layer + attributes=self.transient_attributes, layer=self.ttim_layer ) def to_ttim(self, other): @@ -522,7 +522,7 @@ def remove_from_geopackage(self): def to_timml(self, other) -> ElementExtraction: missing = self._check_table_columns( - attributes=self.timml_attributes, layer=self.timml_layer + attributes=self.steady_attributes, layer=self.timml_layer ) if missing: return ElementExtraction(errors=missing) diff --git a/plugin/qgistim/core/elements/head_line_sink.py b/plugin/qgistim/core/elements/head_line_sink.py index 52c5de4..78c9d22 100644 --- a/plugin/qgistim/core/elements/head_line_sink.py +++ b/plugin/qgistim/core/elements/head_line_sink.py @@ -45,7 +45,7 @@ class RiverSchema(RowWiseSchema): class River(TransientElement): element_type = "River" geometry_type = "Linestring" - timml_attributes = ( + steady_attributes = ( QgsField("head", QVariant.Double), QgsField("resistance", QVariant.Double), QgsField("width", QVariant.Double), @@ -57,12 +57,12 @@ class River(TransientElement): QgsField("head_transient", QVariant.Double), QgsField("timeseries_id", QVariant.Int), ) - ttim_attributes = ( + transient_attributes = ( QgsField("timeseries_id", QVariant.Int), QgsField("time_start", QVariant.Double), QgsField("head", QVariant.Double), ) - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), } transient_columns = ( diff --git a/plugin/qgistim/core/elements/headwell.py b/plugin/qgistim/core/elements/headwell.py index 715fa61..2663125 100644 --- a/plugin/qgistim/core/elements/headwell.py +++ b/plugin/qgistim/core/elements/headwell.py @@ -53,7 +53,7 @@ class HeadWellSchema(RowWiseSchema): class HeadWell(TransientElement): element_type = "Head Well" geometry_type = "Point" - timml_attributes = ( + steady_attributes = ( QgsField("head", QVariant.Double), QgsField("radius", QVariant.Double), QgsField("resistance", QVariant.Double), @@ -64,12 +64,12 @@ class HeadWell(TransientElement): QgsField("head_transient", QVariant.Double), QgsField("timeseries_id", QVariant.Int), ) - ttim_attributes = ( + transient_attributes = ( QgsField("timeseries_id", QVariant.Int), QgsField("time_start", QVariant.Double), QgsField("head", QVariant.Double), ) - timml_defaults = { + steady_defaults = { "radius": QgsDefaultValue("0.1"), "resistance": QgsDefaultValue("0.0"), } diff --git a/plugin/qgistim/core/elements/impermeable_line_doublet.py b/plugin/qgistim/core/elements/impermeable_line_doublet.py index 3327450..cb7a96b 100644 --- a/plugin/qgistim/core/elements/impermeable_line_doublet.py +++ b/plugin/qgistim/core/elements/impermeable_line_doublet.py @@ -18,12 +18,12 @@ class ImpermeableWallSchema(RowWiseSchema): class ImpermeableWall(Element): element_type = "Impermeable Wall" geometry_type = "Linestring" - timml_attributes = ( + steady_attributes = ( QgsField("order", QVariant.Int), QgsField("layer", QVariant.Int), QgsField("label", QVariant.String), ) - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), } schema = ImpermeableWallSchema() diff --git a/plugin/qgistim/core/elements/leaky_building_pit.py b/plugin/qgistim/core/elements/leaky_building_pit.py index 457845b..f8ed857 100644 --- a/plugin/qgistim/core/elements/leaky_building_pit.py +++ b/plugin/qgistim/core/elements/leaky_building_pit.py @@ -54,7 +54,7 @@ class AssociatedLeakyBuildingPitchema(TableSchema): class LeakyBuildingPit(AssociatedElement): element_type = "Leaky Building Pit" geometry_type = "Polygon" - timml_attributes = ( + steady_attributes = ( QgsField("inhomogeneity_id", QVariant.Int), QgsField("order", QVariant.Int), QgsField("ndegrees", QVariant.Int), @@ -73,7 +73,7 @@ class LeakyBuildingPit(AssociatedElement): QgsField("aquitard_npor", QVariant.Double), QgsField("aquifer_npor", QVariant.Double), ] - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), "ndegrees": QgsDefaultValue("6"), "inhomogeneity_id": QgsDefaultValue("1"), diff --git a/plugin/qgistim/core/elements/leaky_line_doublet.py b/plugin/qgistim/core/elements/leaky_line_doublet.py index ace3282..f1fb3d0 100644 --- a/plugin/qgistim/core/elements/leaky_line_doublet.py +++ b/plugin/qgistim/core/elements/leaky_line_doublet.py @@ -19,13 +19,13 @@ class LeakyWallSchema(RowWiseSchema): class LeakyWall(Element): element_type = "Leaky Wall" geometry_type = "Linestring" - timml_attributes = ( + steady_attributes = ( QgsField("resistance", QVariant.Double), QgsField("order", QVariant.Int), QgsField("layer", QVariant.Int), QgsField("label", QVariant.String), ) - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), } schema = LeakyWallSchema() diff --git a/plugin/qgistim/core/elements/line_sink_ditch.py b/plugin/qgistim/core/elements/line_sink_ditch.py index 096ae47..36faf19 100644 --- a/plugin/qgistim/core/elements/line_sink_ditch.py +++ b/plugin/qgistim/core/elements/line_sink_ditch.py @@ -45,7 +45,7 @@ class DitchSchema(RowWiseSchema): class Ditch(TransientElement): element_type = "Ditch" geometry_type = "Linestring" - timml_attributes = ( + steady_attributes = ( QgsField("discharge", QVariant.Double), QgsField("resistance", QVariant.Double), QgsField("width", QVariant.Double), @@ -57,12 +57,12 @@ class Ditch(TransientElement): QgsField("discharge_transient", QVariant.Double), QgsField("timeseries_id", QVariant.Int), ) - ttim_attributes = ( + transient_attributes = ( QgsField("timeseries_id", QVariant.Int), QgsField("time_start", QVariant.Double), QgsField("discharge", QVariant.Double), ) - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), } transient_columns = ( diff --git a/plugin/qgistim/core/elements/observation.py b/plugin/qgistim/core/elements/observation.py index d00106a..9429f21 100644 --- a/plugin/qgistim/core/elements/observation.py +++ b/plugin/qgistim/core/elements/observation.py @@ -27,18 +27,18 @@ class HeadObservationSchema(RowWiseSchema): class HeadObservation(TransientElement): element_type = "Head Observation" geometry_type = "Point" - timml_attributes = ( + steady_attributes = ( QgsField("label", QVariant.String), QgsField("timeseries_id", QVariant.Int), ) - ttim_attributes = ( + transient_attributes = ( QgsField("timeseries_id", QVariant.Int), QgsField("time", QVariant.Double), ) - timml_defaults = { + steady_defaults = { "timeseries_id": QgsDefaultValue("1"), } - ttim_defaults = { + transient_defaults = { "timeseries_id": QgsDefaultValue("1"), } transient_columns = ("timeseries_id",) diff --git a/plugin/qgistim/core/elements/polygon_area_sink.py b/plugin/qgistim/core/elements/polygon_area_sink.py index 4733470..8bbe2cb 100644 --- a/plugin/qgistim/core/elements/polygon_area_sink.py +++ b/plugin/qgistim/core/elements/polygon_area_sink.py @@ -21,12 +21,12 @@ class PolygonAreaSinkSchema(RowWiseSchema): class PolygonAreaSink(Element): element_type = "Polygon Area Sink" geometry_type = "Polygon" - timml_attributes = ( + steady_attributes = ( QgsField("rate", QVariant.Double), QgsField("order", QVariant.Int), QgsField("ndegrees", QVariant.Int), ) - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), "ndegrees": QgsDefaultValue("6"), } diff --git a/plugin/qgistim/core/elements/polygon_inhomogeneity.py b/plugin/qgistim/core/elements/polygon_inhomogeneity.py index b5d540c..c09fdb1 100644 --- a/plugin/qgistim/core/elements/polygon_inhomogeneity.py +++ b/plugin/qgistim/core/elements/polygon_inhomogeneity.py @@ -51,7 +51,7 @@ class AssociatedPolygonInhomogeneitySchema(TableSchema): class PolygonInhomogeneity(AssociatedElement): element_type = "Polygon Inhomogeneity" geometry_type = "Polygon" - timml_attributes = ( + steady_attributes = ( QgsField("inhomogeneity_id", QVariant.Int), QgsField("order", QVariant.Int), QgsField("ndegrees", QVariant.Int), @@ -69,7 +69,7 @@ class PolygonInhomogeneity(AssociatedElement): QgsField("aquitard_npor", QVariant.Double), QgsField("aquifer_npor", QVariant.Double), ] - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), "ndegrees": QgsDefaultValue("6"), "inhomogeneity_id": QgsDefaultValue("1"), diff --git a/plugin/qgistim/core/elements/polygon_semi_confined_top.py b/plugin/qgistim/core/elements/polygon_semi_confined_top.py index 0bb3a7e..092534d 100644 --- a/plugin/qgistim/core/elements/polygon_semi_confined_top.py +++ b/plugin/qgistim/core/elements/polygon_semi_confined_top.py @@ -23,14 +23,14 @@ class PolygonSemiConfinedTopSchema(RowWiseSchema): class PolygonSemiConfinedTop(Element): element_type = "Polygon Semi-Confined Top" geometry_type = "Polygon" - timml_attributes = ( + steady_attributes = ( QgsField("aquitard_c", QVariant.Double), QgsField("semiconf_top", QVariant.Double), QgsField("semiconf_head", QVariant.Double), QgsField("order", QVariant.Int), QgsField("ndegrees", QVariant.Int), ) - timml_defaults = { + steady_defaults = { "order": QgsDefaultValue("4"), "ndegrees": QgsDefaultValue("6"), } diff --git a/plugin/qgistim/core/elements/uniform_flow.py b/plugin/qgistim/core/elements/uniform_flow.py index e2ddf0b..f7aef9d 100644 --- a/plugin/qgistim/core/elements/uniform_flow.py +++ b/plugin/qgistim/core/elements/uniform_flow.py @@ -17,7 +17,7 @@ class UniformFlowSchema(SingleRowSchema): class UniformFlow(Element): element_type = "Uniform Flow" geometry_type = "No geometry" - timml_attributes = ( + steady_attributes = ( QgsField("slope", QVariant.Double), QgsField("angle", QVariant.Double), QgsField("label", QVariant.String), diff --git a/plugin/qgistim/core/elements/well.py b/plugin/qgistim/core/elements/well.py index f1feec9..a8c0d38 100644 --- a/plugin/qgistim/core/elements/well.py +++ b/plugin/qgistim/core/elements/well.py @@ -49,7 +49,7 @@ class WellSchema(RowWiseSchema): class Well(TransientElement): element_type = "Well" geometry_type = "Point" - timml_attributes = ( + steady_attributes = ( QgsField("discharge", QVariant.Double), QgsField("radius", QVariant.Double), QgsField("resistance", QVariant.Double), @@ -62,12 +62,12 @@ class Well(TransientElement): QgsField("slug", QVariant.Bool), QgsField("timeseries_id", QVariant.Int), ) - ttim_attributes = ( + transient_attributes = ( QgsField("timeseries_id", QVariant.Int), QgsField("time_start", QVariant.Double), QgsField("discharge", QVariant.Double), ) - timml_defaults = { + steady_defaults = { "radius": QgsDefaultValue("0.1"), "resistance": QgsDefaultValue("0.0"), "slug": QgsDefaultValue("False"), From 2188380a15bc73160c0179c29058ec618172d8ce Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 16:59:21 +0200 Subject: [PATCH 19/27] Update extraction attribute names --- plugin/qgistim/widgets/dataset_widget.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugin/qgistim/widgets/dataset_widget.py b/plugin/qgistim/widgets/dataset_widget.py index b480a7d..a213883 100644 --- a/plugin/qgistim/widgets/dataset_widget.py +++ b/plugin/qgistim/widgets/dataset_widget.py @@ -59,8 +59,8 @@ class Extraction(NamedTuple): - timml: Dict[str, Any] = None - ttim: Dict[str, Any] = None + steady: Dict[str, Any] = None + transient: Dict[str, Any] = None success: bool = True @@ -586,7 +586,7 @@ def _extract_data(self, transient: bool) -> Extraction: self.validation_dialog = ValidationDialog(errors) return Extraction(success=False) - return Extraction(timml=timml_data, ttim=ttim_data) + return Extraction(steady=timml_data, transient=ttim_data) def save_as_python(self) -> None: outpath, _ = QFileDialog.getSaveFileName(self, "Select file", "", "*.py") @@ -597,7 +597,7 @@ def save_as_python(self) -> None: if not extraction.success: return - script = data_to_script(extraction.timml, extraction.ttim) + script = data_to_script(extraction.steady, extraction.transient) with open(outpath, "w") as f: f.write(script) @@ -631,8 +631,8 @@ def convert_to_json( return True json_data = data_to_json( - extraction.timml, - extraction.ttim, + extraction.steady, + extraction.transient, output_options=self.parent.compute_widget.output_options, ) From 4a0fa61694d46565c7e13d020bad3800ea6ac0e8 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 17:05:34 +0200 Subject: [PATCH 20/27] Migrate all attribute names to steady and transient --- plugin/qgistim/core/elements/aquifer.py | 24 +++---- plugin/qgistim/core/elements/domain.py | 14 ++-- plugin/qgistim/core/elements/element.py | 88 ++++++++++++------------ plugin/qgistim/widgets/dataset_widget.py | 36 +++++----- plugin/qgistim/widgets/tim_widget.py | 4 +- 5 files changed, 84 insertions(+), 82 deletions(-) diff --git a/plugin/qgistim/core/elements/aquifer.py b/plugin/qgistim/core/elements/aquifer.py index 6381831..41c41c7 100644 --- a/plugin/qgistim/core/elements/aquifer.py +++ b/plugin/qgistim/core/elements/aquifer.py @@ -82,15 +82,15 @@ class Aquifer(TransientElement): def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.timml_name = f"timml {self.element_type}:Aquifer" - self.ttim_name = "ttim Temporal Settings:Aquifer" + self.steady_name = f"timml {self.element_type}:Aquifer" + self.transient_name = "ttim Temporal Settings:Aquifer" def write(self): - self.timml_layer = geopackage.write_layer( - self.path, self.timml_layer, self.timml_name, newfile=True + self.steady_layer = geopackage.write_layer( + self.path, self.steady_layer, self.steady_name, newfile=True ) - self.ttim_layer = geopackage.write_layer( - self.path, self.ttim_layer, self.ttim_name + self.transient_layer = geopackage.write_layer( + self.path, self.transient_layer, self.transient_name ) self.set_defaults() @@ -103,8 +103,8 @@ def to_timml(self) -> ElementExtraction: if missing: return ElementExtraction(errors=missing) - data = self.table_to_dict(layer=self.timml_layer) - errors = self.schema.validate_timml(name=self.timml_layer.name(), data=data) + data = self.table_to_dict(layer=self.steady_layer) + errors = self.schema.validate_timml(name=self.steady_layer.name(), data=data) return ElementExtraction(errors=errors, data=data) def to_ttim(self) -> ElementExtraction: @@ -112,12 +112,12 @@ def to_ttim(self) -> ElementExtraction: if missing: return ElementExtraction(errors=missing) - data = self.table_to_dict(layer=self.timml_layer) - time_data = self.table_to_records(layer=self.ttim_layer) + data = self.table_to_dict(layer=self.steady_layer) + time_data = self.table_to_records(layer=self.transient_layer) errors = { - **self.schema.validate_ttim(name=self.timml_layer.name(), data=data), + **self.schema.validate_ttim(name=self.steady_layer.name(), data=data), **self.assoc_schema.validate_ttim( - name=self.ttim_layer.name(), data=time_data + name=self.transient_layer.name(), data=time_data ), } if errors: diff --git a/plugin/qgistim/core/elements/domain.py b/plugin/qgistim/core/elements/domain.py index 68ceaf0..2729e3e 100644 --- a/plugin/qgistim/core/elements/domain.py +++ b/plugin/qgistim/core/elements/domain.py @@ -30,8 +30,8 @@ class Domain(TransientElement): def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.timml_name = f"timml {self.element_type}:Domain" - self.ttim_name = "ttim Computation Times:Domain" + self.steady_name = f"timml {self.element_type}:Domain" + self.transient_name = "ttim Computation Times:Domain" @classmethod def renderer(cls) -> QgsSingleSymbolRenderer: @@ -46,7 +46,7 @@ def remove_from_geopackage(self): pass def update_extent(self, iface: Any) -> Tuple[float, float]: - provider = self.timml_layer.dataProvider() + provider = self.steady_layer.dataProvider() provider.truncate() # removes all features canvas = iface.mapCanvas() extent = canvas.extent() @@ -67,9 +67,9 @@ def update_extent(self, iface: Any) -> Tuple[float, float]: return ymax, ymin def to_timml(self, other) -> ElementExtraction: - data = self.table_to_records(layer=self.timml_layer) + data = self.table_to_records(layer=self.steady_layer) errors = self.schema.validate_timml( - name=self.timml_layer.name(), data=data, other=other + name=self.steady_layer.name(), data=data, other=other ) if errors: return ElementExtraction(errors=errors) @@ -89,9 +89,9 @@ def to_ttim(self, other) -> ElementExtraction: timml_extraction = self.to_timml(other) data = timml_extraction.data - timeseries = self.table_to_dict(layer=self.ttim_layer) + timeseries = self.table_to_dict(layer=self.transient_layer) errors = self.schema.validate_timeseries( - name=self.ttim_layer.name(), data=timeseries + name=self.transient_layer.name(), data=timeseries ) if errors: return ElementExtraction(errors=errors) diff --git a/plugin/qgistim/core/elements/element.py b/plugin/qgistim/core/elements/element.py index 2618368..5f58c35 100644 --- a/plugin/qgistim/core/elements/element.py +++ b/plugin/qgistim/core/elements/element.py @@ -121,17 +121,17 @@ class Element(ExtractorMixin, abc.ABC): def _initialize_default(self, path, name): self.name = name self.path = path - self.timml_name = None - self.ttim_name = None + self.steady_name = None + self.transient_name = None self.assoc_name = None - self.timml_layer = None - self.ttim_layer = None + self.steady_layer = None + self.transient_layer = None self.assoc_layer = None self.item = None def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.timml_name = f"timml {self.element_type}:{name}" + self.steady_name = f"timml {self.element_type}:{name}" @classmethod def dialog(cls, path: str, crs: Any, iface: Any, names: List[str]): @@ -160,10 +160,10 @@ def create_layer( return layer def create_timml_layer(self, crs: Any): - self.timml_layer = self.create_layer( + self.steady_layer = self.create_layer( crs=crs, geometry_type=self.geometry_type, - name=self.timml_name, + name=self.steady_name, attributes=self.steady_attributes, ) @@ -180,7 +180,7 @@ def create_layers(self, crs: Any): def set_defaults(self): for layer, defaults in zip( - (self.timml_layer, self.ttim_layer, self.assoc_layer), + (self.steady_layer, self.transient_layer, self.assoc_layer), (self.steady_defaults, self.transient_defaults, self.assoc_defaults), ): if layer is None: @@ -211,8 +211,8 @@ def renderer(cls): return None def timml_layer_from_geopackage(self) -> QgsVectorLayer: - self.timml_layer = QgsVectorLayer( - f"{self.path}|layername={self.timml_name}", self.timml_name + self.steady_layer = QgsVectorLayer( + f"{self.path}|layername={self.steady_name}", self.steady_name ) def ttim_layer_from_geopackage(self): @@ -222,20 +222,20 @@ def assoc_layer_from_geopackage(self): return def load_layers_from_geopackage(self) -> None: - self.timml_layer_from_geopackage() - self.ttim_layer_from_geopackage() + self.steady_layer_from_geopackage() + self.transient_layer_from_geopackage() self.assoc_layer_from_geopackage() self.set_defaults() return def write(self): - self.timml_layer = geopackage.write_layer( - self.path, self.timml_layer, self.timml_name + self.steady_layer = geopackage.write_layer( + self.path, self.steady_layer, self.steady_name ) self.set_defaults() def remove_from_geopackage(self): - geopackage.remove_layer(self.path, self.timml_name) + geopackage.remove_layer(self.path, self.steady_name) def on_transient_changed(self, _): return @@ -267,7 +267,7 @@ def _check_table_columns(attributes, layer) -> Dict[str, List]: def check_timml_columns(self): return self._check_table_columns( - attributes=self.steady_attributes, layer=self.timml_layer + attributes=self.steady_attributes, layer=self.steady_layer ) def to_timml(self, other=None) -> ElementExtraction: @@ -275,9 +275,9 @@ def to_timml(self, other=None) -> ElementExtraction: if missing: return ElementExtraction(errors=missing) - data = self.table_to_records(layer=self.timml_layer) + data = self.table_to_records(layer=self.steady_layer) errors = self.schema.validate_timml( - name=self.timml_layer.name(), data=data, other=other + name=self.steady_layer.name(), data=data, other=other ) if errors: @@ -360,48 +360,48 @@ class TransientElement(Element, abc.ABC): def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.timml_name = f"timml {self.element_type}:{name}" - self.ttim_name = f"ttim {self.element_type}:{name}" + self.steady_name = f"timml {self.element_type}:{name}" + self.transient_name = f"ttim {self.element_type}:{name}" def create_ttim_layer(self, crs: Any): - self.ttim_layer = self.create_layer( + self.transient_layer = self.create_layer( crs=crs, geometry_type="No Geometry", - name=self.ttim_name, + name=self.transient_name, attributes=self.transient_attributes, ) def ttim_layer_from_geopackage(self): - self.ttim_layer = QgsVectorLayer( - f"{self.path}|layername={self.ttim_name}", - self.ttim_name, + self.transient_layer = QgsVectorLayer( + f"{self.path}|layername={self.transient_name}", + self.transient_name, ) def write(self): - self.timml_layer = geopackage.write_layer( - self.path, self.timml_layer, self.timml_name + self.steady_layer = geopackage.write_layer( + self.path, self.steady_layer, self.steady_name ) - self.ttim_layer = geopackage.write_layer( - self.path, self.ttim_layer, self.ttim_name + self.transient_layer = geopackage.write_layer( + self.path, self.transient_layer, self.transient_name ) self.set_defaults() def remove_from_geopackage(self): - geopackage.remove_layer(self.path, self.timml_name) - geopackage.remove_layer(self.path, self.ttim_name) + geopackage.remove_layer(self.path, self.steady_name) + geopackage.remove_layer(self.path, self.transient_name) def on_transient_changed(self, transient: bool): if len(self.transient_columns) == 0: return - config = self.timml_layer.attributeTableConfig() + config = self.steady_layer.attributeTableConfig() columns = config.columns() for i, column in enumerate(columns): if column.name in self.transient_columns: config.setColumnHidden(i, not transient) - self.timml_layer.setAttributeTableConfig(config) + self.steady_layer.setAttributeTableConfig(config) return @staticmethod @@ -436,7 +436,7 @@ def transient_input( def check_ttim_columns(self): return self._check_table_columns( - attributes=self.transient_attributes, layer=self.ttim_layer + attributes=self.transient_attributes, layer=self.transient_layer ) def to_ttim(self, other): @@ -445,15 +445,15 @@ def to_ttim(self, other): return ElementExtraction(errors=missing) other = other.copy() # avoid side-effects - timeseries = self.table_to_dict(self.ttim_layer) + timeseries = self.table_to_dict(self.transient_layer) if timeseries: other["ttim timeseries IDs"] = set(timeseries["timeseries_id"]) else: other["ttim timeseries IDs"] = {None} - data = self.table_to_records(self.timml_layer) + data = self.table_to_records(self.steady_layer) errors = self.schema.validate_ttim( - name=self.timml_layer.name(), data=data, other=other + name=self.steady_layer.name(), data=data, other=other ) if errors: return ElementExtraction(errors=errors) @@ -490,7 +490,7 @@ class AssociatedElement(Element, abc.ABC): def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.timml_name = f"timml {self.element_type}:{name}" + self.steady_name = f"timml {self.element_type}:{name}" self.assoc_name = f"timml {self.element_type} Properties:{name}" def create_assoc_layer(self, crs: Any): @@ -508,8 +508,8 @@ def assoc_layer_from_geopackage(self): ) def write(self): - self.timml_layer = geopackage.write_layer( - self.path, self.timml_layer, self.timml_name + self.steady_layer = geopackage.write_layer( + self.path, self.steady_layer, self.steady_name ) self.assoc_layer = geopackage.write_layer( self.path, self.assoc_layer, self.assoc_name @@ -517,12 +517,12 @@ def write(self): self.set_defaults() def remove_from_geopackage(self): - geopackage.remove_layer(self.path, self.timml_name) + geopackage.remove_layer(self.path, self.steady_name) geopackage.remove_layer(self.path, self.assoc_name) def to_timml(self, other) -> ElementExtraction: missing = self._check_table_columns( - attributes=self.steady_attributes, layer=self.timml_layer + attributes=self.steady_attributes, layer=self.steady_layer ) if missing: return ElementExtraction(errors=missing) @@ -536,9 +536,9 @@ def to_timml(self, other) -> ElementExtraction: else: other["properties inhomogeneity_id"] = [None] - data = self.table_to_records(self.timml_layer) + data = self.table_to_records(self.steady_layer) errors = self.schema.validate_timml( - name=self.timml_layer.name(), + name=self.steady_layer.name(), data=data, other=other, ) diff --git a/plugin/qgistim/widgets/dataset_widget.py b/plugin/qgistim/widgets/dataset_widget.py index a213883..515efa9 100644 --- a/plugin/qgistim/widgets/dataset_widget.py +++ b/plugin/qgistim/widgets/dataset_widget.py @@ -94,10 +94,10 @@ def reset(self): def add_item(self, timml_name: str, ttim_name: str = None, enabled: bool = True): item = QTreeWidgetItem() self.addTopLevelItem(item) - item.timml_checkbox = QCheckBox() - item.timml_checkbox.setChecked(True) - item.timml_checkbox.setEnabled(enabled) - self.setItemWidget(item, 0, item.timml_checkbox) + item.steady_checkbox = QCheckBox() + item.steady_checkbox.setChecked(True) + item.steady_checkbox.setEnabled(enabled) + self.setItemWidget(item, 0, item.steady_checkbox) item.setText(1, timml_name) item.setText(2, ttim_name) item.assoc_item = None @@ -111,7 +111,9 @@ def add_element(self, element) -> None: enabled = True item = self.add_item( - timml_name=element.timml_name, ttim_name=element.ttim_name, enabled=enabled + timml_name=element.steady_name, + ttim_name=element.transient_name, + enabled=enabled, ) item.element = element return @@ -127,8 +129,8 @@ def on_transient_changed(self, transient: bool) -> None: prefix, _ = item.text(1).split(":") _, elementtype = prefix.split("timml ") if elementtype not in SUPPORTED_TTIM_ELEMENTS: - item.timml_checkbox.setChecked(not transient) - item.timml_checkbox.setEnabled(not transient) + item.steady_checkbox.setChecked(not transient) + item.steady_checkbox.setEnabled(not transient) # Hide transient columns in the TimML layers: item.element.on_transient_changed(transient) @@ -173,8 +175,8 @@ def remove_geopackage_layers(self) -> None: for element in elements: for layer in [ - element.timml_layer, - element.ttim_layer, + element.steady_layer, + element.transient_layer, element.assoc_layer, ]: # QGIS layers @@ -213,7 +215,7 @@ def extract_data(self, transient: bool) -> Tuple[Dict[str, Any], Dict[str, Any]] elements = { item.text(1): item.element for item in self.items() - if item.timml_checkbox.isChecked() + if item.steady_checkbox.isChecked() } # First convert the aquifer, since we need its data to validate @@ -361,12 +363,12 @@ def add_item_to_qgis(self, item) -> None: suppress = self.suppress_popup_checkbox.isChecked() # Start adding the layers maplayer = self.parent.input_group.add_layer( - element.timml_layer, "timml", element.renderer(), suppress + element.steady_layer, "timml", element.renderer(), suppress ) - self.parent.input_group.add_layer(element.ttim_layer, "ttim") + self.parent.input_group.add_layer(element.transient_layer, "ttim") self.parent.input_group.add_layer(element.assoc_layer, "timml") # Set cell size if the item is a domain layer - if item.element.timml_name.split(":")[0] == "timml Domain": + if item.element.steady_name.split(":")[0] == "timml Domain": if maplayer.featureCount() <= 0: return feature = next(iter(maplayer.getFeatures())) @@ -405,7 +407,7 @@ def load_geopackage(self, input_group: str = None) -> None: self.dataset_tree.sortByColumn(0, Qt.SortOrder.AscendingOrder) self.parent.enable_geopackage_buttons() self.on_transient_changed() - self.model_crs = self.domain_item().element.timml_layer.crs() + self.model_crs = self.domain_item().element.steady_layer.crs() self.parent.qgs_project.writeEntry("qgistim", "geopackage_path", self.path) self.parent.qgs_project.writeEntry("qgistim", "input_group", input_group) return @@ -531,7 +533,7 @@ def on_transient_changed(self) -> None: def suppress_popup_changed(self): suppress = self.suppress_popup_checkbox.isChecked() for item in self.dataset_tree.items(): - layer = item.element.timml_layer + layer = item.element.steady_layer if layer is not None: config = layer.editFormConfig() config.setSuppress(suppress) @@ -541,8 +543,8 @@ def suppress_popup_changed(self): def active_elements(self): active_elements = {} for item in self.dataset_tree.items(): - active_elements[item.text(1)] = not (item.timml_checkbox.isChecked() == 0) - active_elements[item.text(2)] = not (item.timml_checkbox.isChecked() == 0) + active_elements[item.text(1)] = not (item.steady_checkbox.isChecked() == 0) + active_elements[item.text(2)] = not (item.steady_checkbox.isChecked() == 0) return active_elements def domain_item(self): diff --git a/plugin/qgistim/widgets/tim_widget.py b/plugin/qgistim/widgets/tim_widget.py index 7e61c4f..1a86cbe 100644 --- a/plugin/qgistim/widgets/tim_widget.py +++ b/plugin/qgistim/widgets/tim_widget.py @@ -321,12 +321,12 @@ def add_element(self, element: Any): suppress = self.dataset_widget.suppress_popup_checkbox.isChecked() self.dataset_widget.add_element(element) self.input_group.add_layer( - element.timml_layer, + element.steady_layer, "timml", renderer=element.renderer(), suppress=suppress, ) - self.input_group.add_layer(element.ttim_layer, "ttim") + self.input_group.add_layer(element.transient_layer, "ttim") self.input_group.add_layer(element.assoc_layer, "timml") # QGIS layers From 3b8faaf94eeb7d043cc983efc2175af1a8bb0736 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 17:17:26 +0200 Subject: [PATCH 21/27] Rename method names to steady and transient --- plugin/qgistim/core/elements/aquifer.py | 18 +++---- plugin/qgistim/core/elements/building_pit.py | 2 +- .../core/elements/circular_area_sink.py | 4 +- plugin/qgistim/core/elements/constant.py | 2 +- .../core/elements/discharge_observation.py | 2 +- plugin/qgistim/core/elements/domain.py | 8 +-- plugin/qgistim/core/elements/element.py | 52 +++++++++---------- .../qgistim/core/elements/head_line_sink.py | 4 +- plugin/qgistim/core/elements/headwell.py | 6 +-- .../core/elements/impermeable_line_doublet.py | 6 +-- .../core/elements/leaky_building_pit.py | 2 +- .../core/elements/leaky_line_doublet.py | 2 +- .../qgistim/core/elements/line_sink_ditch.py | 4 +- plugin/qgistim/core/elements/observation.py | 4 +- .../core/elements/polygon_area_sink.py | 2 +- .../core/elements/polygon_inhomogeneity.py | 2 +- .../elements/polygon_semi_confined_top.py | 2 +- plugin/qgistim/core/elements/uniform_flow.py | 2 +- plugin/qgistim/core/elements/well.py | 4 +- test_plugin/test_aquifer_schemata.py | 10 ++-- 20 files changed, 69 insertions(+), 69 deletions(-) diff --git a/plugin/qgistim/core/elements/aquifer.py b/plugin/qgistim/core/elements/aquifer.py index 41c41c7..8e024b2 100644 --- a/plugin/qgistim/core/elements/aquifer.py +++ b/plugin/qgistim/core/elements/aquifer.py @@ -98,25 +98,25 @@ def remove_from_geopackage(self): """This element may not be removed.""" pass - def to_timml(self) -> ElementExtraction: - missing = self.check_timml_columns() + def extract_steady_data(self) -> ElementExtraction: + missing = self.check_steady_columns() if missing: return ElementExtraction(errors=missing) data = self.table_to_dict(layer=self.steady_layer) - errors = self.schema.validate_timml(name=self.steady_layer.name(), data=data) + errors = self.schema.validate_steady(name=self.steady_layer.name(), data=data) return ElementExtraction(errors=errors, data=data) - def to_ttim(self) -> ElementExtraction: - missing = self.check_ttim_columns() + def extract_transient_data(self) -> ElementExtraction: + missing = self.check_transient_columns() if missing: return ElementExtraction(errors=missing) data = self.table_to_dict(layer=self.steady_layer) time_data = self.table_to_records(layer=self.transient_layer) errors = { - **self.schema.validate_ttim(name=self.steady_layer.name(), data=data), - **self.assoc_schema.validate_ttim( + **self.schema.validate_transient(name=self.steady_layer.name(), data=data), + **self.assoc_schema.validate_transient( name=self.transient_layer.name(), data=time_data ), } @@ -126,6 +126,6 @@ def to_ttim(self) -> ElementExtraction: def extract_data(self, transient: bool) -> ElementExtraction: if transient: - return self.to_ttim() + return self.extract_transient_data() else: - return self.to_timml() + return self.extract_steady_data() diff --git a/plugin/qgistim/core/elements/building_pit.py b/plugin/qgistim/core/elements/building_pit.py index fe38fdf..82d6924 100644 --- a/plugin/qgistim/core/elements/building_pit.py +++ b/plugin/qgistim/core/elements/building_pit.py @@ -88,7 +88,7 @@ def renderer(cls) -> QgsSingleSymbolRenderer: color=TRANSPARENT_RED, color_border=RED, width_border="0.75" ) - def process_timml_row(self, row: Dict[str, Any], grouped: Dict[int, Any]): + def process_steady_row(self, row: Dict[str, Any], grouped: Dict[int, Any]): inhom_id = row["inhomogeneity_id"] raw_data = grouped[inhom_id] layers = [i for i, active in enumerate(raw_data["wall_in_layer"]) if active] diff --git a/plugin/qgistim/core/elements/circular_area_sink.py b/plugin/qgistim/core/elements/circular_area_sink.py index dae5569..bc2d3fe 100644 --- a/plugin/qgistim/core/elements/circular_area_sink.py +++ b/plugin/qgistim/core/elements/circular_area_sink.py @@ -80,7 +80,7 @@ def _centroid_and_radius(self, row): radius = ((x - xc) ** 2 + (y - yc) ** 2) ** 0.5 return xc, yc, radius - def process_timml_row(self, row, other=None) -> Dict[str, Any]: + def process_steady_row(self, row, other=None) -> Dict[str, Any]: xc, yc, radius = self._centroid_and_radius(row) return { "xc": xc, @@ -90,7 +90,7 @@ def process_timml_row(self, row, other=None) -> Dict[str, Any]: "label": row["label"], } - def process_ttim_row(self, row, grouped): + def process_transient_row(self, row, grouped): xc, yc, radius = self._centroid_and_radius(row) tsandN, times = self.transient_input(row, grouped, "rate") return { diff --git a/plugin/qgistim/core/elements/constant.py b/plugin/qgistim/core/elements/constant.py index 6199e29..2b13526 100644 --- a/plugin/qgistim/core/elements/constant.py +++ b/plugin/qgistim/core/elements/constant.py @@ -30,7 +30,7 @@ class Constant(Element): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.marker_renderer(color=RED, name="star", size="5") - def process_timml_row(self, row, other=None): + def process_steady_row(self, row, other=None): x, y = self.point_xy(row) return { "xr": x, diff --git a/plugin/qgistim/core/elements/discharge_observation.py b/plugin/qgistim/core/elements/discharge_observation.py index d7da210..7f6610d 100644 --- a/plugin/qgistim/core/elements/discharge_observation.py +++ b/plugin/qgistim/core/elements/discharge_observation.py @@ -36,7 +36,7 @@ class DischargeObservation(Element): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.line_renderer(color=LIGHT_BLUE, width="0.75", outline_style="dash") - def process_timml_row(self, row, other=None): + def process_steady_row(self, row, other=None): return { "xy": self.linestring_xy(row), "method": "legendre" if row["legendre_method"] else "quad", diff --git a/plugin/qgistim/core/elements/domain.py b/plugin/qgistim/core/elements/domain.py index 2729e3e..f68be72 100644 --- a/plugin/qgistim/core/elements/domain.py +++ b/plugin/qgistim/core/elements/domain.py @@ -66,9 +66,9 @@ def update_extent(self, iface: Any) -> Tuple[float, float]: canvas.refresh() return ymax, ymin - def to_timml(self, other) -> ElementExtraction: + def extract_steady_data(self, other) -> ElementExtraction: data = self.table_to_records(layer=self.steady_layer) - errors = self.schema.validate_timml( + errors = self.schema.validate_steady( name=self.steady_layer.name(), data=data, other=other ) if errors: @@ -85,8 +85,8 @@ def to_timml(self, other) -> ElementExtraction: } ) - def to_ttim(self, other) -> ElementExtraction: - timml_extraction = self.to_timml(other) + def extract_transient_data(self, other) -> ElementExtraction: + timml_extraction = self.extract_steady_data(other) data = timml_extraction.data timeseries = self.table_to_dict(layer=self.transient_layer) diff --git a/plugin/qgistim/core/elements/element.py b/plugin/qgistim/core/elements/element.py index 5f58c35..1fe1818 100644 --- a/plugin/qgistim/core/elements/element.py +++ b/plugin/qgistim/core/elements/element.py @@ -159,7 +159,7 @@ def create_layer( layer.setCrs(crs) return layer - def create_timml_layer(self, crs: Any): + def create_steady_layer(self, crs: Any): self.steady_layer = self.create_layer( crs=crs, geometry_type=self.geometry_type, @@ -167,15 +167,15 @@ def create_timml_layer(self, crs: Any): attributes=self.steady_attributes, ) - def create_ttim_layer(self, crs: Any): + def create_transient_layer(self, crs: Any): pass def create_assoc_layer(self, crs: Any): pass def create_layers(self, crs: Any): - self.create_timml_layer(crs) - self.create_ttim_layer(crs) + self.create_steady_layer(crs) + self.create_transient_layer(crs) self.create_assoc_layer(crs) def set_defaults(self): @@ -210,12 +210,12 @@ def polygon_renderer(**kwargs): def renderer(cls): return None - def timml_layer_from_geopackage(self) -> QgsVectorLayer: + def steady_layer_from_geopackage(self) -> QgsVectorLayer: self.steady_layer = QgsVectorLayer( f"{self.path}|layername={self.steady_name}", self.steady_name ) - def ttim_layer_from_geopackage(self): + def transient_layer_from_geopackage(self): return def assoc_layer_from_geopackage(self): @@ -265,35 +265,35 @@ def _check_table_columns(attributes, layer) -> Dict[str, List]: return {"Table:": [msg]} return {} - def check_timml_columns(self): + def check_steady_columns(self): return self._check_table_columns( attributes=self.steady_attributes, layer=self.steady_layer ) - def to_timml(self, other=None) -> ElementExtraction: - missing = self.check_timml_columns() + def extract_steady_data(self, other=None) -> ElementExtraction: + missing = self.check_steady_columns() if missing: return ElementExtraction(errors=missing) data = self.table_to_records(layer=self.steady_layer) - errors = self.schema.validate_timml( + errors = self.schema.validate_steady( name=self.steady_layer.name(), data=data, other=other ) if errors: return ElementExtraction(errors=errors) else: - elements = [self.process_timml_row(row=row, other=other) for row in data] + elements = [self.process_steady_row(row=row, other=other) for row in data] return ElementExtraction(data=elements) - def to_ttim(self, other=None) -> ElementExtraction: - return self.to_timml(other) + def extract_transient_data(self, other=None) -> ElementExtraction: + return self.extract_steady_data(other) def extract_data(self, transient: bool, other=None) -> ElementExtraction: if transient: - return self.to_ttim(other) + return self.extract_transient_data(other) else: - return self.to_timml(other) + return self.extract_steady_data(other) @staticmethod def aquifer_data(data, transient: bool): @@ -363,7 +363,7 @@ def __init__(self, path: str, name: str): self.steady_name = f"timml {self.element_type}:{name}" self.transient_name = f"ttim {self.element_type}:{name}" - def create_ttim_layer(self, crs: Any): + def create_transient_layer(self, crs: Any): self.transient_layer = self.create_layer( crs=crs, geometry_type="No Geometry", @@ -371,7 +371,7 @@ def create_ttim_layer(self, crs: Any): attributes=self.transient_attributes, ) - def ttim_layer_from_geopackage(self): + def transient_layer_from_geopackage(self): self.transient_layer = QgsVectorLayer( f"{self.path}|layername={self.transient_name}", self.transient_name, @@ -439,8 +439,8 @@ def check_ttim_columns(self): attributes=self.transient_attributes, layer=self.transient_layer ) - def to_ttim(self, other): - missing = self.check_ttim_columns() + def extract_transient_data(self, other): + missing = self.check_transient_columns() if missing: return ElementExtraction(errors=missing) @@ -452,7 +452,7 @@ def to_ttim(self, other): other["ttim timeseries IDs"] = {None} data = self.table_to_records(self.steady_layer) - errors = self.schema.validate_ttim( + errors = self.schema.validate_transient( name=self.steady_layer.name(), data=data, other=other ) if errors: @@ -475,7 +475,7 @@ def to_ttim(self, other): elements = [] times = set() for row in data: - row_data, row_times = self.process_ttim_row(row, grouped) + row_data, row_times = self.process_transient_row(row, grouped) elements.append(row_data) times.update(row_times) @@ -520,7 +520,7 @@ def remove_from_geopackage(self): geopackage.remove_layer(self.path, self.steady_name) geopackage.remove_layer(self.path, self.assoc_name) - def to_timml(self, other) -> ElementExtraction: + def extract_steady_data(self, other) -> ElementExtraction: missing = self._check_table_columns( attributes=self.steady_attributes, layer=self.steady_layer ) @@ -537,7 +537,7 @@ def to_timml(self, other) -> ElementExtraction: other["properties inhomogeneity_id"] = [None] data = self.table_to_records(self.steady_layer) - errors = self.schema.validate_timml( + errors = self.schema.validate_steady( name=self.steady_layer.name(), data=data, other=other, @@ -548,7 +548,7 @@ def to_timml(self, other) -> ElementExtraction: grouped = self.groupby(properties, "inhomogeneity_id") errors = {} for inhom_id, group in grouped.items(): - _errors = self.assoc_schema.validate_timml( + _errors = self.assoc_schema.validate_steady( name=f"Properties, inhomogeneity_id {inhom_id}", data=group, other=other, @@ -558,8 +558,8 @@ def to_timml(self, other) -> ElementExtraction: if errors: return ElementExtraction(errors=errors) - elements = [self.process_timml_row(row=row, grouped=grouped) for row in data] + elements = [self.process_steady_row(row=row, grouped=grouped) for row in data] return ElementExtraction(data=elements) - def to_ttim(self, _): + def extract_transient_data(self, _): raise NotImplementedError(f"{type(self).__name__} is not supported in TTim.") diff --git a/plugin/qgistim/core/elements/head_line_sink.py b/plugin/qgistim/core/elements/head_line_sink.py index 78c9d22..b23648c 100644 --- a/plugin/qgistim/core/elements/head_line_sink.py +++ b/plugin/qgistim/core/elements/head_line_sink.py @@ -77,7 +77,7 @@ class River(TransientElement): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.line_renderer(color=BLUE, width="0.75") - def process_timml_row(self, row, other=None): + def process_steady_row(self, row, other=None): return { "xy": self.linestring_xy(row), "hls": row["head"], @@ -88,7 +88,7 @@ def process_timml_row(self, row, other=None): "label": row["label"], } - def process_ttim_row(self, row, grouped): + def process_transient_row(self, row, grouped): tsandh, times = self.transient_input(row, grouped, "head") return { "xy": self.linestring_xy(row), diff --git a/plugin/qgistim/core/elements/headwell.py b/plugin/qgistim/core/elements/headwell.py index 2663125..b71a66d 100644 --- a/plugin/qgistim/core/elements/headwell.py +++ b/plugin/qgistim/core/elements/headwell.py @@ -85,7 +85,7 @@ class HeadWell(TransientElement): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.marker_renderer(color=BLUE, size="3") - def process_timml_row(self, row, other=None) -> Dict[str, Any]: + def process_steady_row(self, row, other=None) -> Dict[str, Any]: x, y = self.point_xy(row) return { "xw": x, @@ -97,7 +97,7 @@ def process_timml_row(self, row, other=None) -> Dict[str, Any]: "label": row["label"], } - def process_ttim_row(self, row, grouped): + def process_transient_row(self, row, grouped): x, y = self.point_xy(row) tsandh, times = self.transient_input(row, grouped, "head") return { @@ -125,7 +125,7 @@ def renderer(cls) -> QgsSingleSymbolRenderer: symbol.changeSymbolLayer(0, arrow) return QgsSingleSymbolRenderer(symbol) - def process_timml_row(self, row, other=None) -> Dict[str, Any]: + def process_steady_row(self, row, other=None) -> Dict[str, Any]: xy = self.linestring_xy(row) xw, yw = xy[-1] xc, yc = xy[0] diff --git a/plugin/qgistim/core/elements/impermeable_line_doublet.py b/plugin/qgistim/core/elements/impermeable_line_doublet.py index cb7a96b..c925460 100644 --- a/plugin/qgistim/core/elements/impermeable_line_doublet.py +++ b/plugin/qgistim/core/elements/impermeable_line_doublet.py @@ -32,7 +32,7 @@ class ImpermeableWall(Element): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.line_renderer(color=RED, width="0.75") - def process_timml_row(self, row, other=None): + def process_steady_row(self, row, other=None): return { "xy": self.linestring_xy(row), "layers": row["layer"], @@ -40,10 +40,10 @@ def process_timml_row(self, row, other=None): "label": row["label"], } - def to_ttim(self, other): + def extract_transient_data(self, other): # TTim doesn't have an ImpermeableWall, we need to add "imp" as # the resistance entry. - _, data = self.to_timml(other) + _, data = self.extract_steady_data(other) out = [] for row in data: out.append( diff --git a/plugin/qgistim/core/elements/leaky_building_pit.py b/plugin/qgistim/core/elements/leaky_building_pit.py index f8ed857..ffaf781 100644 --- a/plugin/qgistim/core/elements/leaky_building_pit.py +++ b/plugin/qgistim/core/elements/leaky_building_pit.py @@ -94,7 +94,7 @@ def renderer(cls) -> QgsSingleSymbolRenderer: outline_style="dash", ) - def process_timml_row(self, row: Dict[str, Any], grouped: Dict[int, Any]): + def process_steady_row(self, row: Dict[str, Any], grouped: Dict[int, Any]): inhom_id = row["inhomogeneity_id"] raw_data = grouped[inhom_id] aquifer_data = self.aquifer_data(raw_data, transient=False) diff --git a/plugin/qgistim/core/elements/leaky_line_doublet.py b/plugin/qgistim/core/elements/leaky_line_doublet.py index f1fb3d0..f7c8fac 100644 --- a/plugin/qgistim/core/elements/leaky_line_doublet.py +++ b/plugin/qgistim/core/elements/leaky_line_doublet.py @@ -34,7 +34,7 @@ class LeakyWall(Element): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.line_renderer(color=RED, width="0.75", outline_style="dash") - def process_timml_row(self, row, other=None): + def process_steady_row(self, row, other=None): return { "xy": self.linestring_xy(row), "res": row["resistance"], diff --git a/plugin/qgistim/core/elements/line_sink_ditch.py b/plugin/qgistim/core/elements/line_sink_ditch.py index 36faf19..3f878cb 100644 --- a/plugin/qgistim/core/elements/line_sink_ditch.py +++ b/plugin/qgistim/core/elements/line_sink_ditch.py @@ -77,7 +77,7 @@ class Ditch(TransientElement): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.line_renderer(color=GREEN, width="0.75") - def process_timml_row(self, row, other=None): + def process_steady_row(self, row, other=None): return { "xy": self.linestring_xy(row), "Qls": row["discharge"], @@ -88,7 +88,7 @@ def process_timml_row(self, row, other=None): "label": row["label"], } - def process_ttim_row(self, row, grouped): + def process_transient_row(self, row, grouped): tsandQ, times = self.transient_input(row, grouped, "discharge") return { "xy": self.linestring_xy(row), diff --git a/plugin/qgistim/core/elements/observation.py b/plugin/qgistim/core/elements/observation.py index 9429f21..79c8db7 100644 --- a/plugin/qgistim/core/elements/observation.py +++ b/plugin/qgistim/core/elements/observation.py @@ -48,7 +48,7 @@ class HeadObservation(TransientElement): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.marker_renderer(color=LIGHT_BLUE, name="triangle", size="3") - def process_timml_row(self, row, other=None): + def process_steady_row(self, row, other=None): x, y = self.point_xy(row) return { "x": x, @@ -56,7 +56,7 @@ def process_timml_row(self, row, other=None): "label": row["label"], } - def process_ttim_row(self, row, grouped): + def process_transient_row(self, row, grouped): x, y = self.point_xy(row) times = grouped[row["timeseries_id"]]["time"] return { diff --git a/plugin/qgistim/core/elements/polygon_area_sink.py b/plugin/qgistim/core/elements/polygon_area_sink.py index 8bbe2cb..0b0e4fa 100644 --- a/plugin/qgistim/core/elements/polygon_area_sink.py +++ b/plugin/qgistim/core/elements/polygon_area_sink.py @@ -38,7 +38,7 @@ def renderer(cls) -> QgsSingleSymbolRenderer: color=TRANSPARENT_GREEN, color_border=GREEN, width_border="0.75" ) - def process_timml_row(self, row, other): + def process_steady_row(self, row, other): raw_data = deepcopy(other["global_aquifer"]) raw_data["aquitard_c"][0] = None raw_data["semiconf_top"][0] = None diff --git a/plugin/qgistim/core/elements/polygon_inhomogeneity.py b/plugin/qgistim/core/elements/polygon_inhomogeneity.py index c09fdb1..2465a5f 100644 --- a/plugin/qgistim/core/elements/polygon_inhomogeneity.py +++ b/plugin/qgistim/core/elements/polygon_inhomogeneity.py @@ -86,7 +86,7 @@ def renderer(cls) -> QgsSingleSymbolRenderer: color=TRANSPARENT_GREY, color_border=GREY, width_border="0.75" ) - def process_timml_row(self, row: Dict[str, Any], grouped: Dict[int, Any]): + def process_steady_row(self, row: Dict[str, Any], grouped: Dict[int, Any]): inhom_id = row["inhomogeneity_id"] raw_data = grouped[inhom_id] aquifer_data = self.aquifer_data(raw_data, transient=False) diff --git a/plugin/qgistim/core/elements/polygon_semi_confined_top.py b/plugin/qgistim/core/elements/polygon_semi_confined_top.py index 092534d..213729c 100644 --- a/plugin/qgistim/core/elements/polygon_semi_confined_top.py +++ b/plugin/qgistim/core/elements/polygon_semi_confined_top.py @@ -42,7 +42,7 @@ def renderer(cls) -> QgsSingleSymbolRenderer: color=TRANSPARENT_BLUE, color_border=BLUE, width_border="0.75" ) - def process_timml_row(self, row, other): + def process_steady_row(self, row, other): raw_data = deepcopy(other["global_aquifer"]) raw_data["aquitard_c"][0] = row["aquitard_c"] raw_data["semiconf_top"][0] = row["semiconf_top"] diff --git a/plugin/qgistim/core/elements/uniform_flow.py b/plugin/qgistim/core/elements/uniform_flow.py index f7aef9d..13957be 100644 --- a/plugin/qgistim/core/elements/uniform_flow.py +++ b/plugin/qgistim/core/elements/uniform_flow.py @@ -24,7 +24,7 @@ class UniformFlow(Element): ) schema = UniformFlowSchema() - def process_timml_row(self, row, other=None): + def process_steady_row(self, row, other=None): return { "slope": row["slope"], "angle": row["angle"], diff --git a/plugin/qgistim/core/elements/well.py b/plugin/qgistim/core/elements/well.py index a8c0d38..b87e5df 100644 --- a/plugin/qgistim/core/elements/well.py +++ b/plugin/qgistim/core/elements/well.py @@ -86,7 +86,7 @@ class Well(TransientElement): def renderer(cls) -> QgsSingleSymbolRenderer: return cls.marker_renderer(color=GREEN, size="3") - def process_timml_row(self, row, other=None) -> Dict[str, Any]: + def process_steady_row(self, row, other=None) -> Dict[str, Any]: x, y = self.point_xy(row) return { "xw": x, @@ -98,7 +98,7 @@ def process_timml_row(self, row, other=None) -> Dict[str, Any]: "label": row["label"], } - def process_ttim_row(self, row, grouped): + def process_transient_row(self, row, grouped): x, y = self.point_xy(row) tsandQ, times = self.transient_input(row, grouped, "discharge") return { diff --git a/test_plugin/test_aquifer_schemata.py b/test_plugin/test_aquifer_schemata.py index 7691664..ae7597d 100644 --- a/test_plugin/test_aquifer_schemata.py +++ b/test_plugin/test_aquifer_schemata.py @@ -15,12 +15,12 @@ def test_validate(self): "semiconf_top": [None], "semiconf_head": [None], } - self.assertEqual(schema.validate_timml(data), {}) + self.assertEqual(schema.validate_steady(data), {}) def test_validate_empty(self): schema = AquiferSchema() data = {} - self.assertEqual(schema.validate_timml(data), {"Table:": ["Table is empty."]}) + self.assertEqual(schema.validate_steady(data), {"Table:": ["Table is empty."]}) def test_validate_two_layer(self): schema = AquiferSchema() @@ -33,7 +33,7 @@ def test_validate_two_layer(self): "semiconf_top": [None], "semiconf_head": [None], } - self.assertEqual(schema.validate_timml(data), {}) + self.assertEqual(schema.validate_steady(data), {}) def test_validate_two_layer_invalid(self): schema = AquiferSchema() @@ -47,7 +47,7 @@ def test_validate_two_layer_invalid(self): "semiconf_head": [None], } expected = {"aquitard_c": ["No values provided at row(s): 2"]} - self.assertEqual(schema.validate_timml(data), expected) + self.assertEqual(schema.validate_steady(data), expected) def test_validate_two_layer_consistency(self): schema = AquiferSchema() @@ -65,4 +65,4 @@ def test_validate_two_layer_consistency(self): "aquifer_top is not greater or equal to aquifer_bottom at row(s): 1, 2" ] } - self.assertEqual(schema.validate_timml(data), expected) + self.assertEqual(schema.validate_steady(data), expected) From e9473c05a36afb90b2b9db4120adff401cd70f15 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 17:18:27 +0200 Subject: [PATCH 22/27] Rename missed method --- plugin/qgistim/core/elements/schemata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/qgistim/core/elements/schemata.py b/plugin/qgistim/core/elements/schemata.py index 10d5b36..229f7e8 100644 --- a/plugin/qgistim/core/elements/schemata.py +++ b/plugin/qgistim/core/elements/schemata.py @@ -51,7 +51,7 @@ def validate_timeseries( return cls._validate_table(vd) @classmethod - def validate_timml( + def validate_steady( cls, name: str, data: Dict[str, Any], other=None ) -> Dict[str, List]: vd = ValidationData( @@ -60,7 +60,7 @@ def validate_timml( return cls._validate(vd) @classmethod - def validate_ttim( + def validate_transient( cls, name: str, data: Dict[str, Any], other=None ) -> Dict[str, List]: vd = ValidationData( From cac421a1497709b1c9c406c42e6e5402777dad15 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 17:19:24 +0200 Subject: [PATCH 23/27] Update docstring --- plugin/qgistim/core/elements/element.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/qgistim/core/elements/element.py b/plugin/qgistim/core/elements/element.py index 1fe1818..d8b07d5 100644 --- a/plugin/qgistim/core/elements/element.py +++ b/plugin/qgistim/core/elements/element.py @@ -105,7 +105,7 @@ def __init__(self, parent=None): class Element(ExtractorMixin, abc.ABC): """ - Abstract base class for "ordinary" timml elements. + Abstract base class for "ordinary" tim elements. """ element_type = None From aa553a68a6550d98ebaf6220185f3f951baa807d Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Wed, 10 Jun 2026 17:22:21 +0200 Subject: [PATCH 24/27] Update last variable names --- plugin/qgistim/core/elements/domain.py | 4 ++-- plugin/qgistim/widgets/dataset_widget.py | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/plugin/qgistim/core/elements/domain.py b/plugin/qgistim/core/elements/domain.py index f68be72..654708c 100644 --- a/plugin/qgistim/core/elements/domain.py +++ b/plugin/qgistim/core/elements/domain.py @@ -86,8 +86,8 @@ def extract_steady_data(self, other) -> ElementExtraction: ) def extract_transient_data(self, other) -> ElementExtraction: - timml_extraction = self.extract_steady_data(other) - data = timml_extraction.data + steady_extraction = self.extract_steady_data(other) + data = steady_extraction.data timeseries = self.table_to_dict(layer=self.transient_layer) errors = self.schema.validate_timeseries( diff --git a/plugin/qgistim/widgets/dataset_widget.py b/plugin/qgistim/widgets/dataset_widget.py index 515efa9..98d7634 100644 --- a/plugin/qgistim/widgets/dataset_widget.py +++ b/plugin/qgistim/widgets/dataset_widget.py @@ -91,15 +91,17 @@ def reset(self): self.takeTopLevelItem(index) return - def add_item(self, timml_name: str, ttim_name: str = None, enabled: bool = True): + def add_item( + self, steady_name: str, transient_name: str = None, enabled: bool = True + ): item = QTreeWidgetItem() self.addTopLevelItem(item) item.steady_checkbox = QCheckBox() item.steady_checkbox.setChecked(True) item.steady_checkbox.setEnabled(enabled) self.setItemWidget(item, 0, item.steady_checkbox) - item.setText(1, timml_name) - item.setText(2, ttim_name) + item.setText(1, steady_name) + item.setText(2, transient_name) item.assoc_item = None return item @@ -111,8 +113,8 @@ def add_element(self, element) -> None: enabled = True item = self.add_item( - timml_name=element.steady_name, - ttim_name=element.transient_name, + steady_name=element.steady_name, + transient_name=element.transient_name, enabled=enabled, ) item.element = element @@ -576,19 +578,19 @@ def _extract_data(self, transient: bool) -> Extraction: self.validation_dialog.close() self.validation_dialog = None - errors, timml_data = self.dataset_tree.extract_data(transient=False) + errors, steady_data = self.dataset_tree.extract_data(transient=False) if errors: self.validation_dialog = ValidationDialog(errors) return Extraction(success=False) - ttim_data = None + transient_data = None if transient: - errors, ttim_data = self.dataset_tree.extract_data(transient=True) + errors, transient_data = self.dataset_tree.extract_data(transient=True) if errors: self.validation_dialog = ValidationDialog(errors) return Extraction(success=False) - return Extraction(steady=timml_data, transient=ttim_data) + return Extraction(steady=steady_data, transient=transient_data) def save_as_python(self) -> None: outpath, _ = QFileDialog.getSaveFileName(self, "Select file", "", "*.py") From c780ef1a227c43e088b235e652c993d435021264 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Thu, 11 Jun 2026 13:47:26 +0200 Subject: [PATCH 25/27] Rename "timml" to "steady-state" and "ttim" to "transient" in all strings --- gistim/compute.py | 8 +-- plugin/qgistim/core/elements/__init__.py | 18 +++---- plugin/qgistim/core/elements/aquifer.py | 4 +- .../core/elements/circular_area_sink.py | 2 +- plugin/qgistim/core/elements/domain.py | 4 +- plugin/qgistim/core/elements/element.py | 18 +++---- .../qgistim/core/elements/head_line_sink.py | 2 +- plugin/qgistim/core/elements/headwell.py | 2 +- .../qgistim/core/elements/line_sink_ditch.py | 2 +- plugin/qgistim/core/elements/observation.py | 4 +- plugin/qgistim/core/elements/well.py | 2 +- plugin/qgistim/core/formatting.py | 52 ++++++++----------- plugin/qgistim/widgets/compute_widget.py | 6 +-- plugin/qgistim/widgets/dataset_widget.py | 18 +++---- plugin/qgistim/widgets/tim_widget.py | 12 ++--- 15 files changed, 75 insertions(+), 79 deletions(-) diff --git a/gistim/compute.py b/gistim/compute.py index ea065df..553dab7 100644 --- a/gistim/compute.py +++ b/gistim/compute.py @@ -263,7 +263,7 @@ def _(model: timflow.steady.Model, observations: Dict): @compute_discharge_observations.register def _(model: timflow.transient.ModelMaq, observations: Dict): - # intnormflux is not supported by ttim (yet). + # intnormflux is not supported by transient (yet). return None @@ -318,7 +318,7 @@ def compute_steady( with open(path, "r") as f: data = json.load(f) - steady_model, elements = initialize_steady(data["timml"]) + steady_model, elements = initialize_steady(data["steady-state"]) steady_model.solve() write_output( @@ -336,9 +336,9 @@ def compute_transient( with open(path, "r") as f: data = json.load(f) - steady_model, _ = initialize_steady(data["timml"]) + steady_model, _ = initialize_steady(data["steady-state"]) transient_model, transient_elements = initialize_transient( - data["ttim"], steady_model + data["transient"], steady_model ) steady_model.solve() transient_model.solve() diff --git a/plugin/qgistim/core/elements/__init__.py b/plugin/qgistim/core/elements/__init__.py index ce106dd..dec00bd 100644 --- a/plugin/qgistim/core/elements/__init__.py +++ b/plugin/qgistim/core/elements/__init__.py @@ -54,15 +54,15 @@ def parse_name(layername: str) -> Tuple[str, str, str]: """ Based on the layer name find out: - * whether it's a timml or ttim element; + * whether it's a steady-state or transient element; * which element type it is; * what the user provided name is. For example: - parse_name("timml Headwell:drainage") -> ("timml", "Head Well", "drainage") + parse_name("steady-state Headwell:drainage") -> ("steady-state", "Head Well", "drainage") """ prefix, name = layername.split(":") - element_type = re.split("timml |ttim ", prefix)[1] + element_type = re.split("steady-state |transient ", prefix)[1] mapping = { "Computation Times": "Domain", "Temporal Settings": "Aquifer", @@ -71,15 +71,15 @@ def parse_name(layername: str) -> Tuple[str, str, str]: "Leaky Building Pit Properties": "Leaky Building Pit", } element_type = mapping.get(element_type, element_type) - if "timml" in prefix: + if "steady-state" in prefix: if "Properties" in prefix: - tim_type = "timml_assoc" + tim_type = "steady-state_assoc" else: - tim_type = "timml" - elif "ttim" in prefix: - tim_type = "ttim" + tim_type = "steady-state" + elif "transient" in prefix: + tim_type = "transient" else: - raise ValueError("Neither timml nor ttim in layername") + raise ValueError("Neither steady-state nor transient in layername") return tim_type, element_type, name diff --git a/plugin/qgistim/core/elements/aquifer.py b/plugin/qgistim/core/elements/aquifer.py index 8e024b2..4ebbd61 100644 --- a/plugin/qgistim/core/elements/aquifer.py +++ b/plugin/qgistim/core/elements/aquifer.py @@ -82,8 +82,8 @@ class Aquifer(TransientElement): def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.steady_name = f"timml {self.element_type}:Aquifer" - self.transient_name = "ttim Temporal Settings:Aquifer" + self.steady_name = f"steady-state {self.element_type}:Aquifer" + self.transient_name = "transient Temporal Settings:Aquifer" def write(self): self.steady_layer = geopackage.write_layer( diff --git a/plugin/qgistim/core/elements/circular_area_sink.py b/plugin/qgistim/core/elements/circular_area_sink.py index bc2d3fe..aff6f02 100644 --- a/plugin/qgistim/core/elements/circular_area_sink.py +++ b/plugin/qgistim/core/elements/circular_area_sink.py @@ -28,7 +28,7 @@ class CircularAreaSinkSchema(RowWiseSchema): transient_schemata = { "time_start": Optional(Positive()), "time_end": Optional(Positive()), - "timeseries_id": Optional(Membership("ttim timeseries IDs")), + "timeseries_id": Optional(Membership("transient timeseries IDs")), } transient_consistency_schemata = ( AllOrNone("time_start", "time_end", "rate_transient"), diff --git a/plugin/qgistim/core/elements/domain.py b/plugin/qgistim/core/elements/domain.py index 654708c..329f930 100644 --- a/plugin/qgistim/core/elements/domain.py +++ b/plugin/qgistim/core/elements/domain.py @@ -30,8 +30,8 @@ class Domain(TransientElement): def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.steady_name = f"timml {self.element_type}:Domain" - self.transient_name = "ttim Computation Times:Domain" + self.steady_name = f"steady-state {self.element_type}:Domain" + self.transient_name = "transient Computation Times:Domain" @classmethod def renderer(cls) -> QgsSingleSymbolRenderer: diff --git a/plugin/qgistim/core/elements/element.py b/plugin/qgistim/core/elements/element.py index d8b07d5..fca3208 100644 --- a/plugin/qgistim/core/elements/element.py +++ b/plugin/qgistim/core/elements/element.py @@ -131,7 +131,7 @@ def _initialize_default(self, path, name): def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.steady_name = f"timml {self.element_type}:{name}" + self.steady_name = f"steady-state {self.element_type}:{name}" @classmethod def dialog(cls, path: str, crs: Any, iface: Any, names: List[str]): @@ -355,13 +355,13 @@ def interleave(a, b): class TransientElement(Element, abc.ABC): """ - Abstract base class for transient (ttim) elements. + Abstract base class for transient (transient) elements. """ def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.steady_name = f"timml {self.element_type}:{name}" - self.transient_name = f"ttim {self.element_type}:{name}" + self.steady_name = f"steady-state {self.element_type}:{name}" + self.transient_name = f"transient {self.element_type}:{name}" def create_transient_layer(self, crs: Any): self.transient_layer = self.create_layer( @@ -434,7 +434,7 @@ def transient_input( else: return [(0.0, 0.0)], {0.0} - def check_ttim_columns(self): + def check_transient_columns(self): return self._check_table_columns( attributes=self.transient_attributes, layer=self.transient_layer ) @@ -447,9 +447,9 @@ def extract_transient_data(self, other): other = other.copy() # avoid side-effects timeseries = self.table_to_dict(self.transient_layer) if timeseries: - other["ttim timeseries IDs"] = set(timeseries["timeseries_id"]) + other["transient timeseries IDs"] = set(timeseries["timeseries_id"]) else: - other["ttim timeseries IDs"] = {None} + other["transient timeseries IDs"] = {None} data = self.table_to_records(self.steady_layer) errors = self.schema.validate_transient( @@ -490,8 +490,8 @@ class AssociatedElement(Element, abc.ABC): def __init__(self, path: str, name: str): self._initialize_default(path, name) - self.steady_name = f"timml {self.element_type}:{name}" - self.assoc_name = f"timml {self.element_type} Properties:{name}" + self.steady_name = f"steady-state {self.element_type}:{name}" + self.assoc_name = f"steady-state {self.element_type} Properties:{name}" def create_assoc_layer(self, crs: Any): self.assoc_layer = self.create_layer( diff --git a/plugin/qgistim/core/elements/head_line_sink.py b/plugin/qgistim/core/elements/head_line_sink.py index b23648c..1cf7677 100644 --- a/plugin/qgistim/core/elements/head_line_sink.py +++ b/plugin/qgistim/core/elements/head_line_sink.py @@ -33,7 +33,7 @@ class RiverSchema(RowWiseSchema): transient_schemata = { "time_start": Optional(Positive()), "time_end": Optional(Positive()), - "timeseries_id": Optional(Membership("ttim timeseries IDs")), + "timeseries_id": Optional(Membership("transient timeseries IDs")), } timeseries_schemata = { "timeseries_id": AllRequired(), diff --git a/plugin/qgistim/core/elements/headwell.py b/plugin/qgistim/core/elements/headwell.py index b71a66d..6fb02b4 100644 --- a/plugin/qgistim/core/elements/headwell.py +++ b/plugin/qgistim/core/elements/headwell.py @@ -37,7 +37,7 @@ class HeadWellSchema(RowWiseSchema): transient_schemata = { "time_start": Optional(Positive()), "time_end": Optional(Positive()), - "timeseries_id": Optional(Membership("ttim timeseries IDs")), + "timeseries_id": Optional(Membership("transient timeseries IDs")), } transient_consistency_schemata = ( AllOrNone(("time_start", "time_end", "head_transient")), diff --git a/plugin/qgistim/core/elements/line_sink_ditch.py b/plugin/qgistim/core/elements/line_sink_ditch.py index 3f878cb..898ee61 100644 --- a/plugin/qgistim/core/elements/line_sink_ditch.py +++ b/plugin/qgistim/core/elements/line_sink_ditch.py @@ -33,7 +33,7 @@ class DitchSchema(RowWiseSchema): transient_schemata = { "time_start": Optional(Positive()), "time_end": Optional(Positive()), - "timeseries_id": Optional(Membership("ttim timeseries IDs")), + "timeseries_id": Optional(Membership("transient timeseries IDs")), } timeseries_schemata = { "timeseries_id": AllRequired(), diff --git a/plugin/qgistim/core/elements/observation.py b/plugin/qgistim/core/elements/observation.py index 79c8db7..d7c7352 100644 --- a/plugin/qgistim/core/elements/observation.py +++ b/plugin/qgistim/core/elements/observation.py @@ -17,7 +17,9 @@ class HeadObservationSchema(RowWiseSchema): steady_schemata = { "geometry": Required(), } - transient_schemata = {"timeseries_id": Required(Membership("ttim timeseries IDs"))} + transient_schemata = { + "timeseries_id": Required(Membership("transient timeseries IDs")) + } timeseries_schemata = { "timeseries_id": AllRequired(), "time": AllRequired(Positive(), StrictlyIncreasing()), diff --git a/plugin/qgistim/core/elements/well.py b/plugin/qgistim/core/elements/well.py index b87e5df..132649d 100644 --- a/plugin/qgistim/core/elements/well.py +++ b/plugin/qgistim/core/elements/well.py @@ -33,7 +33,7 @@ class WellSchema(RowWiseSchema): "slug": Required(), "time_start": Optional(Positive()), "time_end": Optional(Positive()), - "timeseries_id": Optional(Membership("ttim timeseries IDs")), + "timeseries_id": Optional(Membership("transient timeseries IDs")), } transient_consistency_schemata = ( AllOrNone(("time_start", "time_end", "discharge_transient")), diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index 2e8cd64..14e9308 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -137,16 +137,10 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): strings = [] observations = [] model_string = textwrap.indent(f"model={tim}_model,", prefix=PREFIX) - # TODO: Rename everything to "steady" and "transient" instead of "timml" and - # "ttim", and remove the conditional. ``tim`` will call - if tim == "ttim": - module_name = "transient" - else: - module_name = "steady" for layername, element_data in data.items(): prefix, name = layername.split(":") - plugin_name = re.split("timml |ttim ", prefix)[1] + plugin_name = re.split("steady-state |transient ", prefix)[1] tim_name = mapping[plugin_name] if tim_name is None: continue @@ -171,13 +165,13 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): else: # Has to be added to the model. # Would result in e.g.: - # timml_extraction_0 = timflow.steady.Well( - # model=timml_model, + # steady-state_extraction_0 = timflow.steady.Well( + # model=steady-state_model, # ... # ) kwargs = format_kwargs(kwargs) strings.append( - f"{tim}_{sanitized(name)}_{i} = timflow.{module_name}.{tim_name}(\n{model_string}\n{kwargs}\n)" + f"{tim}_{sanitized(name)}_{i} = timflow.{tim}.{tim_name}(\n{model_string}\n{kwargs}\n)" ) return strings, observations @@ -185,18 +179,18 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): def steady_script_content(data: Dict[str, Any]): data = data.copy() # avoid side-effects - aquifer_data = data.pop("timml Aquifer:Aquifer") - data.pop("timml Domain:Domain") + aquifer_data = data.pop("steady-state Aquifer:Aquifer") + data.pop("steady-state Domain:Domain") strings = [ "import numpy as np", "import timflow", "", - f"timml_model = timflow.steady.ModelMaq(\n{format_kwargs(aquifer_data)}\n)", + f"steady-state_model = timflow.steady.ModelMaq(\n{format_kwargs(aquifer_data)}\n)", ] element_strings, observations = elements_and_observations( - data, STEADY_MAPPING, tim="timml" + data, STEADY_MAPPING, tim="steady-state" ) strings = strings + element_strings return strings, observations @@ -204,9 +198,9 @@ def steady_script_content(data: Dict[str, Any]): def steady_script(data: Dict[str, Any]) -> str: strings, observations = steady_script_content(data) - strings.append("\ntimml_model.solve()\n") - xg, yg, _ = headgrid_code(data["timml Domain:Domain"]) - strings.append(f"head = timml_model.headgrid(\n{xg},\n{yg}\n)") + strings.append("\nsteady-state_model.solve()\n") + xg, yg, _ = headgrid_code(data["steady-state Domain:Domain"]) + strings.append(f"head = steady-state_model.headgrid(\n{xg},\n{yg}\n)") strings.append("\n") strings.extend(observations) return "\n".join(strings) @@ -218,23 +212,23 @@ def transient_script( strings, _ = steady_script_content(steady_data) data = transient_data.copy() # avoid side-effects - aquifer_data = data.pop("timml Aquifer:Aquifer") - domain_data = data.pop("timml Domain:Domain") + aquifer_data = data.pop("steady-state Aquifer:Aquifer") + domain_data = data.pop("steady-state Domain:Domain") data.pop("start_date") strings.append( - f"\nttim_model = timflow.transient.ModelMaq(\n{format_kwargs(aquifer_data)}\n{PREFIX}steady=timml_model,\n)" + f"\ntransient_model = timflow.transient.ModelMaq(\n{format_kwargs(aquifer_data)}\n{PREFIX}steady=steady-state_model,\n)" ) element_strings, observations = elements_and_observations( - data, TRANSIENT_MAPPING, tim="ttim" + data, TRANSIENT_MAPPING, tim="transient" ) strings = strings + element_strings - strings.append("\ntimml_model.solve()\nttim_model.solve()\n") + strings.append("\nsteady-state_model.solve()\ntransient_model.solve()\n") if domain_data.get("time"): xg, yg, t = headgrid_code(domain_data) - strings.append(f"head = ttim_model.headgrid(\n{xg},\n{yg},\n{t}\n)") + strings.append(f"head = transient_model.headgrid(\n{xg},\n{yg},\n{t}\n)") strings.append("\n") strings.extend(observations) @@ -252,14 +246,14 @@ def data_to_script( def json_elements_and_observations(data, mapping: Dict[str, str]): - aquifer_data = data.pop("timml Aquifer:Aquifer") + aquifer_data = data.pop("steady-state Aquifer:Aquifer") observations = {} discharge_observations = {} tim_data = {"ModelMaq": aquifer_data} for layername, element_data in data.items(): prefix, name = layername.split(":") - plugin_name = re.split("timml |ttim ", prefix)[1] + plugin_name = re.split("steady-state |transient ", prefix)[1] tim_name = mapping[plugin_name] if tim_name is None: continue @@ -297,12 +291,12 @@ def steady_json( """ # Process TimML elements data = steady_data.copy() # avoid side-effects - domain_data = data.pop("timml Domain:Domain") + domain_data = data.pop("steady-state Domain:Domain") elements, observations, discharge_observations = json_elements_and_observations( data, mapping=STEADY_MAPPING ) json_data = { - "timml": elements, + "steady-state": elements, "observations": observations, "discharge_observations": discharge_observations, "window": domain_data, @@ -321,13 +315,13 @@ def transient_json( json_data = steady_json(steady_data, output_options) data = transient_data.copy() - domain_data = data.pop("timml Domain:Domain") + domain_data = data.pop("steady-state Domain:Domain") start_date = data.pop("start_date") elements, observations, _ = json_elements_and_observations( data, mapping=TRANSIENT_MAPPING ) - json_data["ttim"] = elements + json_data["transient"] = elements json_data["start_date"] = start_date json_data["observations"] = observations if output_options.mesh or output_options.raster: diff --git a/plugin/qgistim/widgets/compute_widget.py b/plugin/qgistim/widgets/compute_widget.py index 65bbffd..c5ac520 100644 --- a/plugin/qgistim/widgets/compute_widget.py +++ b/plugin/qgistim/widgets/compute_widget.py @@ -512,11 +512,11 @@ def load_vector_result(self, path: Union[Path, str]) -> None: # Special-case the labelling for observations and discharge. if ( - "timml Head Observation:" in layername - or "ttim Head Observation" in layername + "steady-state Head Observation:" in layername + or "transient Head Observation" in layername ): labels = layer_styling.number_labels("head_layer0") - elif "timml Discharge Observation:" in layername: + elif "steady-state Discharge Observation:" in layername: labels = layer_styling.number_labels("discharge_layer0") elif "discharge-" in layername: labels = layer_styling.number_labels("discharge_layer0") diff --git a/plugin/qgistim/widgets/dataset_widget.py b/plugin/qgistim/widgets/dataset_widget.py index 98d7634..8962302 100644 --- a/plugin/qgistim/widgets/dataset_widget.py +++ b/plugin/qgistim/widgets/dataset_widget.py @@ -3,7 +3,7 @@ This widget also allows enabling or disabling individual elements for a computation. It also forms the link between the geometry layers and the -associated layers for homogeneities, or for timeseries layers for ttim +associated layers for homogeneities, or for timeseries layers for transient elements. Not every TimML element has a TTim equivalent (yet). This means that when a @@ -126,10 +126,10 @@ def on_transient_changed(self, transient: bool) -> None: Inhomogeneities, or switch them on again. """ self.setColumnHidden(2, not transient) - # Disable unsupported ttim items, such as inhomogeneities + # Disable unsupported transient items, such as inhomogeneities for item in self.items(): prefix, _ = item.text(1).split(":") - _, elementtype = prefix.split("timml ") + _, elementtype = prefix.split("steady-state ") if elementtype not in SUPPORTED_TTIM_ELEMENTS: item.steady_checkbox.setChecked(not transient) item.steady_checkbox.setEnabled(not transient) @@ -222,7 +222,7 @@ def extract_data(self, transient: bool) -> Tuple[Dict[str, Any], Dict[str, Any]] # First convert the aquifer, since we need its data to validate # other elements. - name = "timml Aquifer:Aquifer" + name = "steady-state Aquifer:Aquifer" aquifer = elements.pop(name) aquifer_extraction = aquifer.extract_data(transient) if aquifer_extraction.errors: @@ -262,7 +262,7 @@ def extract_data(self, transient: bool) -> Tuple[Dict[str, Any], Dict[str, Any]] if transient: if times and (times != {0}): - data["timml Aquifer:Aquifer"]["tmax"] = max(times) + data["steady-state Aquifer:Aquifer"]["tmax"] = max(times) else: errors["Model"] = {"TTim input:": ["No transient forcing defined."]} @@ -365,12 +365,12 @@ def add_item_to_qgis(self, item) -> None: suppress = self.suppress_popup_checkbox.isChecked() # Start adding the layers maplayer = self.parent.input_group.add_layer( - element.steady_layer, "timml", element.renderer(), suppress + element.steady_layer, "steady-state", element.renderer(), suppress ) - self.parent.input_group.add_layer(element.transient_layer, "ttim") - self.parent.input_group.add_layer(element.assoc_layer, "timml") + self.parent.input_group.add_layer(element.transient_layer, "transient") + self.parent.input_group.add_layer(element.assoc_layer, "steady-state") # Set cell size if the item is a domain layer - if item.element.steady_name.split(":")[0] == "timml Domain": + if item.element.steady_name.split(":")[0] == "steady-state Domain": if maplayer.featureCount() <= 0: return feature = next(iter(maplayer.getFeatures())) diff --git a/plugin/qgistim/widgets/tim_widget.py b/plugin/qgistim/widgets/tim_widget.py index 1a86cbe..a5d858d 100644 --- a/plugin/qgistim/widgets/tim_widget.py +++ b/plugin/qgistim/widgets/tim_widget.py @@ -121,7 +121,7 @@ def add_layer( ---------- layer: QGIS map layer, raster or vector layer. May be None, in which case - nothing is done (useful for optional ttim and associated layers). + nothing is done (useful for optional transient and associated layers). destination: str Legend group renderer: @@ -165,8 +165,8 @@ def add_layer( class InputGroup(LayersPanelGroup): def create_group(self) -> None: self._create_group() - self.create_subgroup("timml") - self.create_subgroup("ttim") + self.create_subgroup("steady-state") + self.create_subgroup("transient") return @@ -322,12 +322,12 @@ def add_element(self, element: Any): self.dataset_widget.add_element(element) self.input_group.add_layer( element.steady_layer, - "timml", + "steady-state", renderer=element.renderer(), suppress=suppress, ) - self.input_group.add_layer(element.transient_layer, "ttim") - self.input_group.add_layer(element.assoc_layer, "timml") + self.input_group.add_layer(element.transient_layer, "transient") + self.input_group.add_layer(element.assoc_layer, "steady-state") # QGIS layers # ----------- From 4ca41d30b9126b041b48fb2cb3f71c3df1e9db81 Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Thu, 11 Jun 2026 13:49:01 +0200 Subject: [PATCH 26/27] Better argname --- plugin/qgistim/core/formatting.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugin/qgistim/core/formatting.py b/plugin/qgistim/core/formatting.py index 14e9308..54d8137 100644 --- a/plugin/qgistim/core/formatting.py +++ b/plugin/qgistim/core/formatting.py @@ -133,10 +133,10 @@ def headgrid_code(domain) -> Tuple[str, str]: return xg, yg, t -def elements_and_observations(data, mapping: Dict[str, str], tim: str): +def elements_and_observations(data, mapping: Dict[str, str], temporal_mode: str): strings = [] observations = [] - model_string = textwrap.indent(f"model={tim}_model,", prefix=PREFIX) + model_string = textwrap.indent(f"model={temporal_mode}_model,", prefix=PREFIX) for layername, element_data in data.items(): prefix, name = layername.split(":") @@ -155,12 +155,12 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): # ) kwargs.pop("label") observations.append( - f"observation_{sanitized(name)}_{i}={tim}_model.head(\n{format_kwargs(kwargs)}\n)" + f"observation_{sanitized(name)}_{i}={temporal_mode}_model.head(\n{format_kwargs(kwargs)}\n)" ) elif plugin_name == "Discharge Observation": kwargs.pop("label") observations.append( - f"discharge_observation_{sanitized(name)}_{i}={tim}_model.intnormflux(\n{format_kwargs(kwargs)}\n)" + f"discharge_observation_{sanitized(name)}_{i}={temporal_mode}_model.intnormflux(\n{format_kwargs(kwargs)}\n)" ) else: # Has to be added to the model. @@ -171,7 +171,7 @@ def elements_and_observations(data, mapping: Dict[str, str], tim: str): # ) kwargs = format_kwargs(kwargs) strings.append( - f"{tim}_{sanitized(name)}_{i} = timflow.{tim}.{tim_name}(\n{model_string}\n{kwargs}\n)" + f"{temporal_mode}_{sanitized(name)}_{i} = timflow.{temporal_mode}.{tim_name}(\n{model_string}\n{kwargs}\n)" ) return strings, observations @@ -190,7 +190,7 @@ def steady_script_content(data: Dict[str, Any]): ] element_strings, observations = elements_and_observations( - data, STEADY_MAPPING, tim="steady-state" + data, STEADY_MAPPING, temporal_mode="steady-state" ) strings = strings + element_strings return strings, observations @@ -221,7 +221,7 @@ def transient_script( ) element_strings, observations = elements_and_observations( - data, TRANSIENT_MAPPING, tim="transient" + data, TRANSIENT_MAPPING, temporal_mode="transient" ) strings = strings + element_strings strings.append("\nsteady-state_model.solve()\ntransient_model.solve()\n") From a3f42cc07197835da98a99e564963fe46e693d5a Mon Sep 17 00:00:00 2001 From: JoerivanEngelen Date: Thu, 11 Jun 2026 14:28:06 +0200 Subject: [PATCH 27/27] Update text in the docs --- docs/tutorial_Rijsenhout.qmd | 54 ++++++++++++++++++------------------ docs/tutorial_TheHague.qmd | 48 ++++++++++++++++---------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/docs/tutorial_Rijsenhout.qmd b/docs/tutorial_Rijsenhout.qmd index fcc1595..4b3b338 100644 --- a/docs/tutorial_Rijsenhout.qmd +++ b/docs/tutorial_Rijsenhout.qmd @@ -152,13 +152,13 @@ Your window looks like in @fig-Panel-QGIS-Tim. ![QGIS-Tim panel](figures/tutorial/Panel-QGIS-Tim.png){width=50% #fig-Panel-QGIS-Tim} -(@) Check in the *Layers* panel on the left that your new geopackage is added as a group.
A sub group **timml** for the steady state model input and the sub group **ttim** for the transient model input. +(@) Check in the *Layers* panel on the left that your new geopackage is added as a group.
A sub group **steady-state** for the steady state model input and the sub group **transient** for the transient model input. If you had no introduction to the Tim plugin, read the Intermezzo below for a general explanation of the components. > **Intermezzo:** *introduction Tabs on the Tim panel* > -> - Model Manager: an overview of the elements in your geopackage. In case you switch to transient modelling, an extra column with *ttim* elements is added. +> - Model Manager: an overview of the elements in your geopackage. In case you switch to transient modelling, an extra column with *transient* elements is added. > - Elements: a list of at least 16 Tim elements from which you can build your model. > - Results: here you can define your domain and cell size, decide if your model is transient or not and manage the output files. @@ -168,7 +168,7 @@ Now we are ready to define our first steady state model by parameterizing our Aq We start with a very simple 'model', only the parameters of a single aquifer.
Important message: all editing of model parameters and model elements you do in the *Layers* panel on the left! -(@) So select the layer "timml Aquifer:Aquifer" on the left. +(@) So select the layer "steady-state Aquifer:Aquifer" on the left. (@) Click your right mouse button and from the menu select *Attribute Table* to open the table in a new window.
**NB** Alternative is to press F6 or use the button *Open Attribute Table* (![](figures/tutorial/button-Qgis-OpenAttributeTable.png){width=3%}). (@) Start the editing mode with a click on the *Toggle Editing Mode* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). (@) Hover with your mouse over the buttons and find the *Add Feature* button (![](figures/tutorial/button-AttributeTable-AddFeature.png){width=20%}). Perhaps button 5 from left. @@ -223,9 +223,9 @@ The calculation result is now visible and we see a mesh with just the value 0, n (@) Click on the element "Well" and a window opens to create a new (vector) layer in QGIS. (@) Give the layer a name, e.g. "DewateringWell" and click *OK*. -See that layer "timml Well:DewateringWell" is added to the timml sub group in your geopackage with 'point' as geometry. Also in the ttim sub group an element with the same name is added. This is a table that can store transient well data while referring to the x/y locations in the timml layer. Next step is to add the actual well, both the location and its parameters. +See that layer "steady-state Well:DewateringWell" is added to the steady-state sub group in your geopackage with 'point' as geometry. Also in the transient sub group an element with the same name is added. This is a table that can store transient well data while referring to the x/y locations in the steady-state layer. Next step is to add the actual well, both the location and its parameters. -(@) Select the layer "timml Well:DewateringWell". +(@) Select the layer "steady-state Well:DewateringWell". (@) Click your right mouse button and select the *Toggle Editing Mode* (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). (@) To add a new well (feature) to the layer click the *Add Point Feature* button (![](figures/tutorial/button_AddPointFeature.png){width=4%}). (@) With your mouse, click on a location in the centre of the group of bombs. @@ -275,7 +275,7 @@ A single aquifer is of course not enough to describe the geology of our project ![Project area cross section (left) lifting the World War II bomb (right)](figures/tutorial/photo-fieldwork-liftbomb-crosssection.jpg){width=100% #fig-photo-fieldwork-liftbomb-crosssection} -(@) In your geopackage select the layer "timml Aquifer:Aquifer" and click your right mouse button. +(@) In your geopackage select the layer "steady-state Aquifer:Aquifer" and click your right mouse button. (@) From the menu select *Open Attribute Table* and the table opens in a new window. Once again, press F6 for a quick open of the Attribute Table. (@) Start the editing mode with a click on the *Toggle Editing Mode* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). (@) Add three extra aquifers / features; click three times on the *Add Feature* button (![](figures/tutorial/button-AttributeTable-AddFeature.png){width=15%}). @@ -310,7 +310,7 @@ Now we introduce a new but frequently used element: the sheet pile. (@) Return to the QGIS-Tim panel and go to the tab *Elements*. (@) Click on the element "Leaky Wall". (@) Give the layer a name, e.g. "sheetpile". -(@) In your geopackage select the layer "timml Leaky Wall:sheetpile" and start editing using the *Toggle Editing Mode* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). +(@) In your geopackage select the layer "steady-state Leaky Wall:sheetpile" and start editing using the *Toggle Editing Mode* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). (@) In the editing mode, the *Add Line Feature* button (![](figures/tutorial/button_AddLineFeature.png){width=4%}) is available. Click the button and draw a box around the 5 bombs (click left to start, click right to close). (@) In the *Feature Attributes* window make resistance = 1500 and layer = 0. (@) Click *OK*. @@ -365,11 +365,11 @@ To prevent damage on the private properties caused by the dewatering, the author (@) On the tab *Elements* in QGIS-Tim click on the element "Ditch". (@) Give the layer a name, e.g. "InfiltrationWell". -See that layer "timml Ditch:InfiltrationWell" is added to the timml sub group in your geopackage with 'line' as geometry. For the transient version of the model a table with the same name is added to the ttim sub group. Next step is to add the location of the horizontal well and its capacity. +See that layer "steady-state Ditch:InfiltrationWell" is added to the steady-state sub group in your geopackage with 'line' as geometry. For the transient version of the model a table with the same name is added to the transient sub group. Next step is to add the location of the horizontal well and its capacity. (@) Click the *Measure Line" button (![](figures/tutorial/button_MeasureLine.png){width=4%}) from the "Attributes Toolbar". (@) With your left mouse button try to get an idea what a distance of 400 m along the road looks like. Close the window. -(@) Select the layer "timml Ditch:InfiltrationWell". +(@) Select the layer "steady-state Ditch:InfiltrationWell". (@) Start editing with the *Toggle Editing Mode*. (@) Use the *Add Line Feature* button (![](figures/tutorial/button_AddLineFeature.png){width=4%}) to draw a 400 m line (click left to start, click right to close). (@) Fill these feature within the table: discharge = -1000 (negative abstraction is flux into the model), resistance = 1, width = 1, layer = 0! not *NULL* ;-). By default order = 4. @@ -385,11 +385,11 @@ We have the Value Tool and the Cross section tool to check for calculated values (@) On the tab *Elements* in QGIS-Tim click on the element "Head Observation". (@) Give the layer a name, e.g. "Piezometers". -(@) Select the new layer "timml Head Observation:Piezometers". +(@) Select the new layer "steady-state Head Observation:Piezometers". (@) Start editing with the *Toggle Editing Mode* and use *Add Point Feature* button (![](figures/tutorial/button_AddPointFeature.png){width=4%}). (@) Click with your left mouse button to place a point near point A. (@) In the poped up window fill in Label = A and click *OK*. -(@) Go to the layer "timml Head Observation:Piezometers", click your right mouse button and activate "![](figures/tutorial/icon-showlabels.png){width=4%} show labels" +(@) Go to the layer "steady-state Head Observation:Piezometers", click your right mouse button and activate "![](figures/tutorial/icon-showlabels.png){width=4%} show labels" (@) Add point B close to the dwatering well (@fig-figure_ObservationsLocations). ![Observation locations (*A*-*E*) together with other Tim elements](figures/tutorial/figure_ObservationsLocations.png){width=80% #fig-figure_ObservationsLocations} @@ -398,13 +398,13 @@ Are you tired of the pop-up window every time you add a point? There is an optio (@) On the tab *Model Manager*, in the lowest section, check the option "Suppress attribute form pop-up after feature creation". (@) Place points C to E. -(@) Open the Attribute Table from layer "timml Head Observation:Piezometers" and fill in the Labels C to E. +(@) Open the Attribute Table from layer "steady-state Head Observation:Piezometers" and fill in the Labels C to E. (@) Save your changes and stop the editing mode. (@) Compute the model again. The observed values are saved in a new layer under the existing group "case-Rijsenhout output" and sub group "vector". -(@) In this sub group select the layer "case-Rijsenhout-timml Head Observation:Piezometers" and check the calculated values within this layer by opening the Attribute Table (F6). +(@) In this sub group select the layer "case-Rijsenhout-steady-state Head Observation:Piezometers" and check the calculated values within this layer by opening the Attribute Table (F6). (@) Close the Attribute Table. ### Draw Contour Lines @@ -420,10 +420,10 @@ A layer with your contours is saved in the group "case-Rijsenhout-output:vector" ## Model 7: determine the influence of the nearby lake East of the project area there is a large lake. What will be the influence of this lake? Let's find out.
-In Tim a lake is added as an inhomogeneity within the total model domain. This domain is described in table "timml Aquifer:Aquifer" we filled in with the first model. +In Tim a lake is added as an inhomogeneity within the total model domain. This domain is described in table "steady-state Aquifer:Aquifer" we filled in with the first model. (@) On the tab *Elements* in QGIS-Tim click on the element "Polygon Semi-Confined Top". -(@) Give the layer a name, e.g. "Lake" and find out that layer "timml Polygon Semi-Confined Top:Lake" is added to the geopackage. +(@) Give the layer a name, e.g. "Lake" and find out that layer "steady-state Polygon Semi-Confined Top:Lake" is added to the geopackage. (@) Start editing with the *Toggle Editing Mode* and use *Add Polygon Feature* button (![](figures/tutorial/button_AddPolygonFeature.png){width=4%}) to add the Lake contour.
**NB** Try to minimize the number of segments because each segment slows down the calculations. With QGIS it is tempting to use detail but the influence of detail on the outcome is small. (@) Fill the Lake feature with the following parameters: aquitard_c = 500, semiconf_top = -7 (bottom of the Lake) and semiconf_head = -2 (water level). (@) Save your changes and rerun the model. @@ -434,7 +434,7 @@ In Tim a lake is added as an inhomogeneity within the total model domain. This d You can not miss the effect of the Lake in this calculation. In many cases you like to analyse or even save this difference. Let's see how we can use Tim and QGIS to isolate the effect. Therefor we rerun the model without the Lake and rename the output. (@) In QGIS-Tim go to the tab *Model Manager*. -(@) In the list of Steady State elements switch off "timml Polygon Semi-Confined Top:Lake". +(@) In the list of Steady State elements switch off "steady-state Polygon Semi-Confined Top:Lake". (@) Go to the tab *Results*. (@) Click the button *Set path as ...* and change the name of the output, e.g. "case-Rijsenhout-NoLake". (@) Click *Compute* to run the model without the Lake. @@ -457,48 +457,48 @@ Now you are ready for the last step: make your model transient. We keep it simpl (@) In the section *Model Setup* turn on the option "Transient". (@) See below that only 5 elements have a transient component. -By selecting the "transient" option, columns containing extra parameters necessary for a transient model have been unhidden now. First of all we see it in the layer "timml Aquifer:Aquifer" where columns "storage" and "porosity are visible now. +By selecting the "transient" option, columns containing extra parameters necessary for a transient model have been unhidden now. First of all we see it in the layer "steady-state Aquifer:Aquifer" where columns "storage" and "porosity are visible now. -(@) In your geopackage select the layer "timml Aquifer:Aquifer". +(@) In your geopackage select the layer "steady-state Aquifer:Aquifer". (@) Open its table, start the editing mode and for every layer set both acquifer_s and acquitard_s to 0.001. Acquitard_s (layer 0) = 0.25. You can use copy and paste to do it quickly. **NB!** In transient mode, Tim can not handle aquitard with zero thickness so let's set the aquitard thickness to 0.1 m (@) Change the values in the column "aquifer_top" to -17.0, -22.1, -27.1 and -47.1 m. -(@) In your geopackage select the layer "ttim Temporal Settings:Aquifer" to define the temporal properties of the model. +(@) In your geopackage select the layer "transient Temporal Settings:Aquifer" to define the temporal properties of the model. (@) Open its table, start the editing mode and add a new feature. (@) Make sure that tmin=0.01, tmax=30, tstart=0, reference_date=2023-03-23 00:00:00. -(@) In your geopackage select the layer "ttim Computation Times:Domain" in order to define the moments in time for which raster output is saved. +(@) In your geopackage select the layer "transient Computation Times:Domain" in order to define the moments in time for which raster output is saved. (@) Open its table, start the editing mode and add 7 features / periods (click 7 times "Add feature"). (@) In the column "time" add the moments 1,2,5,10, 15, 20 and 30. (@) Save and Close the table. For the observations we can define a different set of output moments. -(@) In your geopackage select the layer "ttim Head Observation:Piezometers". +(@) In your geopackage select the layer "transient Head Observation:Piezometers". (@) Open its table, start the editing mode and add 10 features / periods (click 10 times "Add feature"). (@) In the column "time" add the moments 1,2,3,4,5,10,15,20,25 and 30. (@) Save and Close the table. Special attention for the Well package while it has 2 options to make it transient: -- Simple: a well can be switched on and off only once. Parameters are set in the stationary part of the model, so in "timml Well:DewateringWell". -- Detailed: a well can be switched on and off multiple times within the modelled period. Parameters are set in the transient part of the model, so in "ttim Well:DewateringWell". +- Simple: a well can be switched on and off only once. Parameters are set in the stationary part of the model, so in "steady-state Well:DewateringWell". +- Detailed: a well can be switched on and off multiple times within the modelled period. Parameters are set in the transient part of the model, so in "transient Well:DewateringWell". In this tutorial we show you the simple version. -(@) In your geopackage select the layer "timml Well:DewateringWell". +(@) In your geopackage select the layer "steady-state Well:DewateringWell". (@) Open its table, start the editing mode and see that 6 extra columns with time dependent parameters are visible now ("time_start", "time_end", "discharge_transient", "caisson_radius", "slug" and "timeseries_id"). (@) Switch off the Steady State abstraction, make discharge = 0 (was 2000). (@) Switch on the Transient abstraction: time_start = 2, time_end = 30, discharge_transient = 2000, caisson_radius = 1. (@) Save your changes. (@) Compute your transient model in the tab *Results*. -In case of a successful calculation a new layer is added to your Vector output: case-Rijsenhout-ttim Head Observation:Piezometers. This layer contains transient data which is indicated with the clock icon right from the layer name. There are 2 ways to visualize these calculated heads in the observations point a) animation over time and b) timeseries at location. +In case of a successful calculation a new layer is added to your Vector output: case-Rijsenhout-transient Head Observation:Piezometers. This layer contains transient data which is indicated with the clock icon right from the layer name. There are 2 ways to visualize these calculated heads in the observations point a) animation over time and b) timeseries at location. (@) For the animation over time, activate the *Temporal Control Panel* with the button ![](figures/tutorial/button_TemporalControllerPanel.png){width=4%} on the Map Navigation Toolbar. (@) For timeseries at location activate the Timeseries panel with the *Timeseries* button (![](figures/tutorial/button_iMOD-TimeSeries.png){width=4%}) on the iMOD Toolbar. -(@) Be sure that "case-Rijsenhout-ttim Head Observation:Piezometers" is checked and "case-Rijsenhout-timml Head Observation:Piezometers" is unchecked. +(@) Be sure that "case-Rijsenhout-transient Head Observation:Piezometers" is checked and "case-Rijsenhout-steady-state Head Observation:Piezometers" is unchecked. (@) In the Temporal Controller panel click the green play button (![](figures/tutorial/button_TemporalControllerPanel-menu.png){width=14%}). Navigation buttons appear. (@) Increase the *Step* to 16 hours and start the animation with a click on the *Play* button (![](figures/tutorial/button_TemporalControler-play.png){width=4%}). @@ -514,7 +514,7 @@ Only the first few days you see most prominent drawdown. Let's now display the t In the same way you can display the time series from the Observations. -(@) In the iMOD time series panel select the layer "case-Rijsenhout-ttim Head Observation:Piezometers". +(@) In the iMOD time series panel select the layer "case-Rijsenhout-transient Head Observation:Piezometers". (@) For "ID column:" select *label* and for "Variable:" select *head_layer0*. Don't forget to **deselect *fid***. (@) Click the button *Select Points* and draw a box with your mouse to select one or more observation points. (@) Click the *Plot* button and the selected timeseries are added to the chart. diff --git a/docs/tutorial_TheHague.qmd b/docs/tutorial_TheHague.qmd index ff80d9f..b01997e 100644 --- a/docs/tutorial_TheHague.qmd +++ b/docs/tutorial_TheHague.qmd @@ -244,13 +244,13 @@ Your window looks like in @fig-Panel-QGIS-Tim_TheHague. ![QGIS-Tim panel](figures/tutorial/Panel-QGIS-Tim_TheHague.png){width=50% #fig-Panel-QGIS-Tim_TheHague fig-align="left"} -(@) Check in the *Layers* panel on the left that your new geopackage is added as a group.
A sub group **timml** for the steady state model input, the sub group **ttim** for the transient model input and a series of output formats (vector/mesh/raster). +(@) Check in the *Layers* panel on the left that your new geopackage is added as a group.
A sub group **steady-state** for the steady state model input, the sub group **transient** for the transient model input and a series of output formats (vector/mesh/raster). If you had no introduction to the Tim plugin, read the Intermezzo below for a general explanation of the components. > **Intermezzo:** *introduction Tabs on the Tim panel* > -> - Model Manager: an overview of the elements in your geopackage. In case you switch to transient modelling, an extra column with *ttim* elements is added. +> - Model Manager: an overview of the elements in your geopackage. In case you switch to transient modelling, an extra column with *transient* elements is added. > - Elements: a list of at least 16 Tim elements from which you can build your model. > - Results: here you can define your domain and cell size, decide if your model is transient or not and manage the output files. @@ -281,7 +281,7 @@ For marine deposits at -12 a value of 50 to 100 days per meter layer thickness i We are now ready to define our first steady state model by parameterizing our Aquifer. -(@) From the *Layers* panel, select the layer *timml Aquifer:Aquifer*. +(@) From the *Layers* panel, select the layer *steady-state Aquifer:Aquifer*. (@) Click your right mouse button and from the menu select *Open Attribute table* (![](figures/tutorial/button-Qgis-OpenAttributeTable.png){width=3%}). Search for the same icon somewhere on the *Attributes Toolbar*. (@) Switch to the editing mode in the table with a click on (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}) *Toggle Editing*. (@) Then by clicking 3 times on (![](figures/tutorial/button-Qgis-AttributeTable-AddFeature.png){width=4%}) *Add feature* you will see new rows are added. @@ -307,7 +307,7 @@ In the QGIS-Tim Window we now introduce the following elements for ground water First, we will *draw* the location of the sheet pile before *adding* the parameter values. -(@) In the *Layers* panel right click on the layer ![](figures/tutorial/figure_Leakylinedoublet_icon.png){width=4%} *timml Leaky Wall:sheet_pile* and start the editing mode by clicking the *Toggle Editing* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). +(@) In the *Layers* panel right click on the layer ![](figures/tutorial/figure_Leakylinedoublet_icon.png){width=4%} *steady-state Leaky Wall:sheet_pile* and start the editing mode by clicking the *Toggle Editing* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). Two important remarks before drawing the sheet pile: @@ -336,7 +336,7 @@ Two important remarks before drawing the sheet pile: (@) In GIS-Tim go to the tab *Elements* and select the *Well* element. (@) A name for the element can be given in the pop-up panel, e.g. *pumping_wells*. -(@) In the *Layers* panel right click on the layer ![](figures/tutorial/figure_well_icon.png){width=3%} *timml Well:pumping_wells* and start the editing mode by clicking the *Toggle Editing* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). +(@) In the *Layers* panel right click on the layer ![](figures/tutorial/figure_well_icon.png){width=3%} *steady-state Well:pumping_wells* and start the editing mode by clicking the *Toggle Editing* button (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png ){width=4%}). (@) Next click on *Add point feature* (![](figures/tutorial/button_AddPointFeature.png){width=4%}). (@) With you left mouse button add the first well location similar to point 1 in @fig-SchematizationTheHague. (@) In the pop-up window, fill in the well parameters discharge (50 m3/d), radius (0.1 m), resistance (1 d) and layer (0). @@ -344,10 +344,10 @@ Two important remarks before drawing the sheet pile: ![Schematization of the pumping wells, sheet piles and observation locations](figures/tutorial/figure_SchematizationTheHague.png){width=60% #fig-SchematizationTheHague fig-align="left"} -(@) In the *Layers* panel right select layer *timml Well:pumping_wells* and open the *Attribute Table (F6)*. +(@) In the *Layers* panel right select layer *steady-state Well:pumping_wells* and open the *Attribute Table (F6)*. (@) Start the editing mode and fill in the values shown in @fig-WellAttributeTable. Don't forget the column 'Label'.
The discharge value in the table is a first guess to be adjusted later to desired level of -3.5 m groundwater lowering in the building pit. (@) Stop the editing mode, save your work and close the window. -(@) Select layer *timml Well:pumping_wells* again, click right and from the menu select *Show labels*. +(@) Select layer *steady-state Well:pumping_wells* again, click right and from the menu select *Show labels*. ![Well properties](figures/tutorial/figure_WellAttributeTable.png){width=100% #fig-WellAttributeTable} @@ -393,7 +393,7 @@ The city authorities that perform quality checks on the effect of construction p (@) In the QGIS-Tim panel go to the *Elements* tab and select the element *Observation*. (@) Give a name in the pop-up panel, e.g. "observations". -(@) Then go to the *Layers* panel and select the layer ![](figures/tutorial/figure_Observation_icon.png){width=3%}*timml Observation:observations*. +(@) Then go to the *Layers* panel and select the layer ![](figures/tutorial/figure_Observation_icon.png){width=3%}*steady-state Observation:observations*. (@) Go to the toolbar with drawing options and activate Toggle editing (![](figures/tutorial/button-Qgis-AttributeTable-StartEditingMode.png){width=4%}). (@) Go right to the Add point feature (![](figures/tutorial/button_AddPointFeature.png){width=3%}) and drop some piezometers in the drawing.
We propose to use 5 points (see @fig-SchematizationTheHague): 1 point in the centre of the building pit, 1 near the lower corner outside, 1 outside near the middle of the eastern sheet pile section and just 2 near street corners. (@) Compute the model again. @@ -402,7 +402,7 @@ Results of calculations at the observation locations are presented as *Vector* d (@) Uncheck/check layers in order to display observation results only. -By default, the label at each observation location is the calculated head for layer 0. Perhaps you see a second number near the location. For your information: this is the "location number" label belonging to the model input in layer *timml Observation:observations*. +By default, the label at each observation location is the calculated head for layer 0. Perhaps you see a second number near the location. For your information: this is the "location number" label belonging to the model input in layer *steady-state Observation:observations*. We can observe that the lowering of groundwater around the building pit is quite high due to leakage of the sheet piles or leakage through the bottom clay layer with small resistance. Therefore, it is needed to improve the wall quality or the length. First we check the effect of the clay layer by studying a cross section. @@ -425,12 +425,12 @@ The authorities demand a drawdown effect of dewatering at a maximum of 0.10 m at To check whether the wall resistance or the bottom resistance of the layer 1 (below the building pit) is more important we can make 2 variations; one with C-clay=200 d and one with R-wall=500 d.
Of course you can change your model input, rerun the model and overwrite your model results. The next steps show you how to change the model input and save the results in separate *.gpkg and *.nc files. -(@) In the input group select layer *timml Aquifer:...* +(@) In the input group select layer *steady-state Aquifer:...* (@) Open the *Attrribute Table* (F6) and change the value for "aquitard_c" in layer 1 into 200 d. (@) In the QGIS-Tim panel go to the tab *Results* and change the name of the output, e.g. case-TheHague_v1. (@) Click *Compute* to run variant 1. -Check in the *Layers* panel and see that the results are not overwritten but added to the groups, e.g. layer *case-TheHague_v1-timml Observation:observations* is added to the group *Vector*. +Check in the *Layers* panel and see that the results are not overwritten but added to the groups, e.g. layer *case-TheHague_v1-steady-state Observation:observations* is added to the group *Vector*. (@) Fill in your calculated heads at the observation locations in @tbl-CalculatedHeads2Variants or use Excel. @@ -447,8 +447,8 @@ Check in the *Layers* panel and see that the results are not overwritten but add Let's now run Variant 2. -(@) In layer *timml Aquifer:...* reset the value for "aquitard_c" in layer 1 to the default of 40 d. -(@) In layer *timml Leaky Wall:...* change the value for "resistance" into 5000 d (500x10). +(@) In layer *steady-state Aquifer:...* reset the value for "aquitard_c" in layer 1 to the default of 40 d. +(@) In layer *steady-state Leaky Wall:...* change the value for "resistance" into 5000 d (500x10). (@) In the QGIS-Tim panel go to the tab *Results* and change the name of the output, e.g. case-TheHague_v2. (@) Click *Compute* to run variant 2. (@) Fill in your calculated heads at the observation locations in the table above. @@ -468,7 +468,7 @@ How to copy the sheet pile wall to an extra *Leaky Wall* element? (@) In the QGIS-Tim panel go to the tab *Elements* and add a second *Leaky Wall* and give it a name, e.g. "sheet_pile_L1" (@) Go to the tab *Model Manager* and see that the element separately is added to the list. Here is can switch this element on / off for a calculation. -(@) In the *Layers* panel select the new layer *timml Leaky Wall:sheet_pile_l1*. +(@) In the *Layers* panel select the new layer *steady-state Leaky Wall:sheet_pile_l1*. (@) Open its *Attribute Table* (F6) and start the editing mode. The table is empty. (@) Also open the *Attribute Table* of the first *Leaky Wall* and select the existing element. (@) Click on the *Copy* button (![](figures/tutorial/button_Copy_Selected_Row.png){width=3%}) in the source table to copy the selected row to the clipboard. @@ -534,7 +534,7 @@ QGIS-Tim offers the opportunity to export the geopackage of the created model to ![Python script](figures/tutorial/figure_PythonExport01.png){width=90% #fig-figure_PythonExport01} -As can be seen the converted Python file start with calls (e.g. import timml) to main necessary Python packages. After that, for each timm element in the model, all data coordinates and parameter values follow. At the end of the Python file the "model.solve" command is stated after which all head values in the domain with the desired mesh density are determined and also at demanded observation points. +As can be seen the converted Python file start with calls (e.g. import steady-state) to main necessary Python packages. After that, for each timm element in the model, all data coordinates and parameter values follow. At the end of the Python file the "model.solve" command is stated after which all head values in the domain with the desired mesh density are determined and also at demanded observation points. As can be seen the Python script for TimML is written in a very dedicated and condensed manner. @@ -701,7 +701,7 @@ Nevertheless in this section we want to guide you on setting up a basic transien (@) Return to QGIS and in the QGIS-Tim panel go to the tab *Model Manager*. (@) In the section *Model Setup* turn on the option "Transient". -(@) In the panel *Layers* select *timml Aquifer:Aquifer*. +(@) In the panel *Layers* select *steady-state Aquifer:Aquifer*. As can be seen in @fig-Panel-TimmlAquiferAttrTable_v02, the matrix of properties is extended in the transient mode with cells for transient parameters, like specific storage coefficients (aquitard_s, and aquifer_s) and porosities (aquitard_npor and aquifer_npor). Take care that specific storage coefficient is a storage per meter layer thickness. In older MWell course material a speadsheet is presented for estimation of coefficient values but there we calculated storage coefficients per whole layer. Those values should be divided by layer thickness. @@ -709,31 +709,31 @@ As can be seen in @fig-Panel-TimmlAquiferAttrTable_v02, the matrix of properties (@) Fill in the Table with the corresponding values. (@) In the TTim section in the *Layers panel* go to the list of elements for transient calculations. -(@) Select *ttim Temporal Settings:Aquifer* and open its *Attribute Table* (F6). Here the length of the time series is specified. +(@) Select *transient Temporal Settings:Aquifer* and open its *Attribute Table* (F6). Here the length of the time series is specified. (@) Set the starting time to 0. But calculations take place for the range of time steps between "time_min" and "time_max". The time unit is according to central settings in the project, mostly time in days. "Time_min" should not be zero but given a slight offset. Here we also find a "Stehfest_M" number, related to the number of terms in the calculation method performing transformation of formulas in solving differential equations. A reference date can be set to relate the calculation to real time data. (@) Fill in the table according to @fig-Panel-TTimAquiferAttrTable_v01. -![Table for *ttim Temporal Settings:Aquifer* ](figures/tutorial/Panel-TTim AquiferAttrTable_v01.png){width=70% #fig-Panel-TTimAquiferAttrTable_v01} +![Table for *transient Temporal Settings:Aquifer* ](figures/tutorial/Panel-TTim AquiferAttrTable_v01.png){width=70% #fig-Panel-TTimAquiferAttrTable_v01} **NB!**: In QGIS it is an obligation to use a "reference_date" to get the model running and present outcomes! -(@) Select *ttim Computation Times:Domain* and set the time values for time steps where we want to get calculations of spatially distributed heads in mesh or raster points and contours. +(@) Select *transient Computation Times:Domain* and set the time values for time steps where we want to get calculations of spatially distributed heads in mesh or raster points and contours. -![Table for *ttim Computation Times:Domain* ](figures/tutorial/Panel-TTim_DomainAttrTable_v01.png){width=30% #fig-Panel-TTim_DomainAttrTable_v01} +![Table for *transient Computation Times:Domain* ](figures/tutorial/Panel-TTim_DomainAttrTable_v01.png){width=30% #fig-Panel-TTim_DomainAttrTable_v01} For this case we will leave this table blank, because calculating several head distributions at different time steps is rather time consuming during this course. -(@) Select *ttim Observation:observations* and here we can set the time steps for a time series at certain points we want to monitor the calculation results. We set points at intervals that follow a (approximately) logarithmic increase in time intervals. Proposed values are shown in the next table. +(@) Select *transient Observation:observations* and here we can set the time steps for a time series at certain points we want to monitor the calculation results. We set points at intervals that follow a (approximately) logarithmic increase in time intervals. Proposed values are shown in the next table. -![Table for *ttim Observation:observations* ](figures/tutorial/Panel-TTim_ObservationsAttrTable_v01.png){width=40% #fig-Panel-TTim_ObservationsAttrTable_v01} +![Table for *transient Observation:observations* ](figures/tutorial/Panel-TTim_ObservationsAttrTable_v01.png){width=40% #fig-Panel-TTim_ObservationsAttrTable_v01} Don’t choose exactly the same time as when changing the flow. So if 60 is an end value, choose 59.9. -In the *Attribute Table* of layer *ttim Well:pumping_wells* we can set the discharge amount. The value might change during time when excavation is considered or construction is performed in phases. For each change we have to add a line of input. In case there are a lot of switch on/off moments, this is a lot of work.
We just leave this option without any change because there is an other option in case each well has only a singel start and end time. +In the *Attribute Table* of layer *transient Well:pumping_wells* we can set the discharge amount. The value might change during time when excavation is considered or construction is performed in phases. For each change we have to add a line of input. In case there are a lot of switch on/off moments, this is a lot of work.
We just leave this option without any change because there is an other option in case each well has only a singel start and end time. -(@) Therefor go to the layer *timml Well:pumping_wells* layer. This layer contains simple elements to make it behave as a simple Timm element. +(@) Therefor go to the layer *steady-state Well:pumping_wells* layer. This layer contains simple elements to make it behave as a simple Timm element. (@) In the *Attribute Table* make start_time=5, end_time=30 and discharge_transient=15. (@) But fill in a value of 0 m3/d in column "Discharge" because this variable is part of TimML well element. We use the "discharge_transient" variable to define flow in TTim. Remember: Solution of TTim is superposed on solution of TimML.