aquimodpy 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v4
10
+ - name: Install uv
11
+ uses: astral-sh/setup-uv@v5
12
+ with:
13
+ enable-cache: true
14
+ - name: Set up Python
15
+ run: uv python install 3.14
16
+ - name: Install dependencies
17
+ run: uv sync --group dev --group test
18
+ - name: Check formatting (Black)
19
+ run: uv run black --check src tests
20
+ - name: Type checking (Mypy)
21
+ run: uv run mypy src
22
+ - name: Run tests (Pytest)
23
+ run: uv run pytest tests
@@ -0,0 +1,19 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Pytest & MyPy
13
+ .pytest_cache/
14
+ .mypy_cache/
15
+ .coverage
16
+
17
+ # MkDocs
18
+ site/
19
+ EOF
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 aquimodpy contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: aquimodpy
3
+ Version: 1.0.0
4
+ Summary: Python wrapper for Aquimod 2
5
+ Author: Arran Clarke
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Python: >=3.14
12
+ Requires-Dist: pandas>=3.0.3
13
+ Description-Content-Type: text/markdown
14
+
15
+ # aquimodpy
16
+
17
+ A Python wrapper for the British Geological Survey's **AquiMod 2**, a lumped parameter groundwater model.
18
+
19
+ ## Features
20
+
21
+ - **IDE Support**: Full autocompletion and parameter validation in modern editors.
22
+ - **Modular Design**: Support for all Soil Zone (FAO, NSSS, SMAP), Unsaturated Zone (Weibull), and Saturated Zone (Q3K3S1, VKD, SA1D, etc.) components.
23
+ - **Automated Configuration**: Generates all required input files (`Input.txt`, `Observations.txt`, and component-specific parameter files) with correct Windows-style formatting for Wine compatibility.
24
+ - **Simulation Modes**: Full support for Evaluation, Monte Carlo calibration, and SCE-UA global optimization.
25
+ - **Cross-Platform**: Flexible execution support; specify your preferred command prefix (e.g., `["wine"]`, `["box86"]`) for running the Windows binary on non-Windows systems.
26
+ - **Data Integration**: Seamless integration with Pandas for observation input and result parsing.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ # Clone the repository
32
+ git clone https://github.com/your-repo/aquimodpy.git
33
+ cd aquimodpy
34
+
35
+ # Install dependencies (using uv)
36
+ uv pip install -e .
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ```python
42
+ import pandas as pd
43
+ from aquimodpy import Model, FAO, Weibull, Q3K3S1, Observations, EvaluationRunner
44
+
45
+ # 1. Initialize the model
46
+ model = Model(
47
+ model_name="MySimulation",
48
+ executable_path="~/Documents/AquiMod2/AquiMod2.exe",
49
+ working_directory="./simulation_results",
50
+ exec_prefix=["wine"] # Use ["wine"] for Linux or [] for native Windows
51
+ )
52
+
53
+ # 2. Add components using named arguments
54
+ # Units and special characters are handled automatically!
55
+ FAO(
56
+ model,
57
+ theta_fc=0.4,
58
+ theta_wp=0.1,
59
+ Z_r=1000,
60
+ p=0.5,
61
+ BFI=0.8
62
+ )
63
+
64
+ Weibull(
65
+ model,
66
+ k=2.0,
67
+ lambda_=5.0 # Use lambda_ as 'lambda' is a Python keyword
68
+ )
69
+
70
+ Q3K3S1(
71
+ model,
72
+ dx=1000,
73
+ K3=10,
74
+ K2=5,
75
+ K1=1,
76
+ S=0.01,
77
+ z3=50,
78
+ z2=40,
79
+ z1=30,
80
+ alpha=1
81
+ )
82
+
83
+ # 3. Add observations and map column names
84
+ df = pd.read_csv("my_data.csv")
85
+ Observations(model, df, {
86
+ "DATE": "date_col",
87
+ "RAIN": "rainfall_mm",
88
+ "PET": "pet_mm",
89
+ "GWL": "gw_level_m"
90
+ })
91
+
92
+ # 4. Configure and run
93
+ model.set_runner(EvaluationRunner(model))
94
+ model.setup()
95
+ model.run()
96
+
97
+ # 5. Analyze results
98
+ results = model.get_results()
99
+ print(results['Sat'].head())
100
+ ```
101
+
102
+ ## Calibration and Optimization
103
+
104
+ ### Monte Carlo Calibration
105
+ Provide `[min, max]` lists for parameters you wish to calibrate.
106
+ ```python
107
+ from aquimodpy import CalibrationRunner
108
+ model.set_runner(CalibrationRunner(model))
109
+ model.set_simulation_mode('m', n_runs=10000, threshold=0.5, variable='g')
110
+
111
+ # Calibrate Z_r and BFI, keep others fixed
112
+ FAO(
113
+ model,
114
+ theta_fc=0.35,
115
+ theta_wp=0.1,
116
+ Z_r=[500, 3000],
117
+ p=0.5,
118
+ BFI=[0.1, 0.99]
119
+ )
120
+ ```
121
+
122
+ ### SCE-UA Optimization
123
+ ```python
124
+ model.set_simulation_mode('s', n_loops=100, n_complexes=50, variable='g')
125
+ ```
126
+
127
+ ## License and Attribution
128
+
129
+ This library is licensed under the **MIT License**.
130
+
131
+ This project provides a wrapper for **AquiMod 2**, which is owned by the British Geological Survey (BGS) and is licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).
132
+
133
+ Please note that this library does not include the AquiMod 2 binary. You can download the AquiMod 2 software from the [official BGS website](https://www.bgs.ac.uk/technologies/software/aquimod/). Users are responsible for obtaining the binary independently and complying with the terms of the Open Government Licence as specified by the BGS.
134
+
@@ -0,0 +1,120 @@
1
+ # aquimodpy
2
+
3
+ A Python wrapper for the British Geological Survey's **AquiMod 2**, a lumped parameter groundwater model.
4
+
5
+ ## Features
6
+
7
+ - **IDE Support**: Full autocompletion and parameter validation in modern editors.
8
+ - **Modular Design**: Support for all Soil Zone (FAO, NSSS, SMAP), Unsaturated Zone (Weibull), and Saturated Zone (Q3K3S1, VKD, SA1D, etc.) components.
9
+ - **Automated Configuration**: Generates all required input files (`Input.txt`, `Observations.txt`, and component-specific parameter files) with correct Windows-style formatting for Wine compatibility.
10
+ - **Simulation Modes**: Full support for Evaluation, Monte Carlo calibration, and SCE-UA global optimization.
11
+ - **Cross-Platform**: Flexible execution support; specify your preferred command prefix (e.g., `["wine"]`, `["box86"]`) for running the Windows binary on non-Windows systems.
12
+ - **Data Integration**: Seamless integration with Pandas for observation input and result parsing.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ # Clone the repository
18
+ git clone https://github.com/your-repo/aquimodpy.git
19
+ cd aquimodpy
20
+
21
+ # Install dependencies (using uv)
22
+ uv pip install -e .
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```python
28
+ import pandas as pd
29
+ from aquimodpy import Model, FAO, Weibull, Q3K3S1, Observations, EvaluationRunner
30
+
31
+ # 1. Initialize the model
32
+ model = Model(
33
+ model_name="MySimulation",
34
+ executable_path="~/Documents/AquiMod2/AquiMod2.exe",
35
+ working_directory="./simulation_results",
36
+ exec_prefix=["wine"] # Use ["wine"] for Linux or [] for native Windows
37
+ )
38
+
39
+ # 2. Add components using named arguments
40
+ # Units and special characters are handled automatically!
41
+ FAO(
42
+ model,
43
+ theta_fc=0.4,
44
+ theta_wp=0.1,
45
+ Z_r=1000,
46
+ p=0.5,
47
+ BFI=0.8
48
+ )
49
+
50
+ Weibull(
51
+ model,
52
+ k=2.0,
53
+ lambda_=5.0 # Use lambda_ as 'lambda' is a Python keyword
54
+ )
55
+
56
+ Q3K3S1(
57
+ model,
58
+ dx=1000,
59
+ K3=10,
60
+ K2=5,
61
+ K1=1,
62
+ S=0.01,
63
+ z3=50,
64
+ z2=40,
65
+ z1=30,
66
+ alpha=1
67
+ )
68
+
69
+ # 3. Add observations and map column names
70
+ df = pd.read_csv("my_data.csv")
71
+ Observations(model, df, {
72
+ "DATE": "date_col",
73
+ "RAIN": "rainfall_mm",
74
+ "PET": "pet_mm",
75
+ "GWL": "gw_level_m"
76
+ })
77
+
78
+ # 4. Configure and run
79
+ model.set_runner(EvaluationRunner(model))
80
+ model.setup()
81
+ model.run()
82
+
83
+ # 5. Analyze results
84
+ results = model.get_results()
85
+ print(results['Sat'].head())
86
+ ```
87
+
88
+ ## Calibration and Optimization
89
+
90
+ ### Monte Carlo Calibration
91
+ Provide `[min, max]` lists for parameters you wish to calibrate.
92
+ ```python
93
+ from aquimodpy import CalibrationRunner
94
+ model.set_runner(CalibrationRunner(model))
95
+ model.set_simulation_mode('m', n_runs=10000, threshold=0.5, variable='g')
96
+
97
+ # Calibrate Z_r and BFI, keep others fixed
98
+ FAO(
99
+ model,
100
+ theta_fc=0.35,
101
+ theta_wp=0.1,
102
+ Z_r=[500, 3000],
103
+ p=0.5,
104
+ BFI=[0.1, 0.99]
105
+ )
106
+ ```
107
+
108
+ ### SCE-UA Optimization
109
+ ```python
110
+ model.set_simulation_mode('s', n_loops=100, n_complexes=50, variable='g')
111
+ ```
112
+
113
+ ## License and Attribution
114
+
115
+ This library is licensed under the **MIT License**.
116
+
117
+ This project provides a wrapper for **AquiMod 2**, which is owned by the British Geological Survey (BGS) and is licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).
118
+
119
+ Please note that this library does not include the AquiMod 2 binary. You can download the AquiMod 2 software from the [official BGS website](https://www.bgs.ac.uk/technologies/software/aquimod/). Users are responsible for obtaining the binary independently and complying with the terms of the Open Government Licence as specified by the BGS.
120
+
@@ -0,0 +1,11 @@
1
+ # API Reference
2
+
3
+ ::: aquimodpy.Model
4
+
5
+ ::: aquimodpy.Components
6
+
7
+ ::: aquimodpy.Runner
8
+
9
+ ::: aquimodpy.CalibrationRunner
10
+
11
+ ::: aquimodpy.EvaluationRunner
@@ -0,0 +1,41 @@
1
+ # Welcome to aquimodpy
2
+
3
+ `aquimodpy` is a Python wrapper for the British Geological Survey's **AquiMod 2**, a lumped parameter groundwater model. It provides a clean, Pythonic interface to define complex hydrogeological models.
4
+
5
+ ## Overview
6
+ This library allows you to:
7
+ - Define soil, unsaturated, and saturated zone components using intuitive named arguments.
8
+ - Seamlessly integrate with Pandas for input data and model observation.
9
+ - Manage simulation runs (evaluation, Monte Carlo calibration, and SCE-UA optimization) through dedicated runner classes.
10
+ - Run the original AquiMod 2 Windows binary on Linux environments using Wine.
11
+
12
+ ## Quick Start
13
+ ```python
14
+ import pandas as pd
15
+ from aquimodpy import Model, FAO, Weibull, Q3K3S1, Observations, EvaluationRunner
16
+
17
+ # Initialize the model
18
+ model = Model("MySim", "~/path/to/AquiMod2.exe", "./results")
19
+
20
+ # Configure components
21
+ FAO(model, theta_fc=0.4, theta_wp=0.1, Z_r=1000, p=0.5, BFI=0.8)
22
+ Weibull(model, k=2.0, lambda_=5.0)
23
+ Q3K3S1(model, dx=1000, K3=10, K2=5, K1=1, S=0.01, z3=50, z2=40, z1=30, alpha=1)
24
+
25
+ # Set observations and run
26
+ df = pd.read_csv("data.csv")
27
+ Observations(model, df, {"DATE": "date", "RAIN": "rain", "PET": "pet", "GWL": "gwl"})
28
+
29
+ model.set_runner(EvaluationRunner(model))
30
+ model.run()
31
+ ```
32
+
33
+ ## API Reference
34
+ Navigate through the core components of the library:
35
+
36
+ - [Model Configuration](api.md#aquimodpy.Model)
37
+ - [Observation Handling](api.md#aquimodpy.Components.Observations)
38
+ - [Soil Components](api.md#aquimodpy.Components.FAO)
39
+ - [Unsaturated Zone](api.md#aquimodpy.Components.Weibull)
40
+ - [Saturated Zone](api.md#aquimodpy.Components.Q3K3S1)
41
+ - [Simulation Runners](api.md#aquimodpy.EvaluationRunner)
@@ -0,0 +1,28 @@
1
+ site_name: aquimodpy
2
+ theme:
3
+ name: material
4
+
5
+ nav:
6
+ - Home: index.md
7
+ - API Reference: api.md
8
+
9
+ plugins:
10
+ - search
11
+ - mkdocstrings:
12
+ default_handler: python
13
+ handlers:
14
+ python:
15
+ paths: [src]
16
+ options:
17
+ show_source: true
18
+ show_root_heading: true
19
+ members_order: source
20
+ show_if_no_docstring: true
21
+ show_bases: true
22
+ show_source: true
23
+
24
+
25
+ markdown_extensions:
26
+ - admonition
27
+ - pymdownx.details
28
+ - pymdownx.superfences
@@ -0,0 +1,50 @@
1
+ [project]
2
+ name = "aquimodpy"
3
+ version = "1.0.0"
4
+ description = "Python wrapper for Aquimod 2"
5
+ authors = [{name = "Arran Clarke"}]
6
+ license = {text = "MIT"}
7
+ readme = "README.md"
8
+ requires-python = ">=3.14"
9
+ dependencies = [
10
+ "pandas>=3.0.3",
11
+ ]
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3",
14
+ "License :: OSI Approved :: MIT License",
15
+ "Operating System :: OS Independent",
16
+ ]
17
+
18
+ [build-system]
19
+ requires = ["hatchling"]
20
+ build-backend = "hatchling.build"
21
+
22
+ [tool.hatch.build.targets.wheel]
23
+ packages = ["src/aquimodpy"]
24
+
25
+ [dependency-groups]
26
+ dev = [
27
+ "black>=26.5.0",
28
+ "build>=1.5.0",
29
+ "mkdocs>=1.6.1",
30
+ "mkdocs-material>=9.7.6",
31
+ "mkdocstrings[python]>=1.0.4",
32
+ "mypy>=2.1.0",
33
+ "pandas-stubs>=3.0.0.260204",
34
+ "pytest>=9.0.3",
35
+ "pytest-cov>=7.1.0",
36
+ "twine>=6.2.0",
37
+ ]
38
+ test = [
39
+ "matplotlib>=3.10.9",
40
+ ]
41
+
42
+ [tool.pytest.ini_options]
43
+ pythonpath = ["src"]
44
+ testpaths = ["tests"]
45
+
46
+ [tool.mypy]
47
+ python_version = "3.14"
48
+ warn_return_any = true
49
+ warn_unused_configs = true
50
+ disallow_untyped_defs = true
@@ -0,0 +1,48 @@
1
+ from typing import TYPE_CHECKING
2
+ from .Runner import Runner
3
+ import os
4
+
5
+ if TYPE_CHECKING:
6
+ from .Model import Model
7
+
8
+
9
+ class CalibrationRunner(Runner):
10
+ """Runner for Monte Carlo and SCE-UA calibration simulations."""
11
+
12
+ def prepare(self) -> None:
13
+ """Prepares calibration simulation."""
14
+ super().prepare()
15
+ # Generate component calibration files
16
+ self.write_component_calib_files()
17
+
18
+ def write_component_calib_files(self) -> None:
19
+ """Writes *_calib.txt files in the Calibration directory."""
20
+ calib_dir = os.path.join(self.model.working_directory, "Calibration")
21
+
22
+ components = [self.model.soil_zone, self.model.unsat_zone, self.model.sat_zone]
23
+
24
+ for comp in components:
25
+ if comp:
26
+ comp_name = comp.__class__.__name__
27
+ file_path = os.path.join(calib_dir, f"{comp_name}_calib.txt")
28
+
29
+ # Ensure parameters are written in the correct order specified in REQUIRED_PARAMETERS
30
+ if isinstance(comp.parameters, dict):
31
+ with open(file_path, "w", newline="") as f:
32
+ for param_name in comp.REQUIRED_PARAMETERS:
33
+ bounds = comp.parameters.get(param_name)
34
+ if bounds is None:
35
+ continue # Should not happen due to validation
36
+
37
+ # Ensure bounds is a list/tuple of two values
38
+ if (
39
+ not isinstance(bounds, (list, tuple))
40
+ or len(bounds) != 2
41
+ ):
42
+ # If it's a single value, treat it as fixed
43
+ b = [bounds, bounds]
44
+ else:
45
+ b = list(bounds)
46
+
47
+ f.write(f"{param_name}\r\n")
48
+ f.write(f"{b[0]} {b[1]}\r\n\r\n")