aquagrid 0.2.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.
- aquagrid-0.2.0/CHANGELOG.md +33 -0
- aquagrid-0.2.0/LICENSE +25 -0
- aquagrid-0.2.0/MANIFEST.in +4 -0
- aquagrid-0.2.0/PKG-INFO +337 -0
- aquagrid-0.2.0/README.md +304 -0
- aquagrid-0.2.0/docs/zarr-schema.md +88 -0
- aquagrid-0.2.0/examples/config.example.yaml +18 -0
- aquagrid-0.2.0/pyproject.toml +55 -0
- aquagrid-0.2.0/setup.cfg +4 -0
- aquagrid-0.2.0/src/aquagrid/__init__.py +12 -0
- aquagrid-0.2.0/src/aquagrid/bench.py +75 -0
- aquagrid-0.2.0/src/aquagrid/cli.py +52 -0
- aquagrid-0.2.0/src/aquagrid/engine/__init__.py +1 -0
- aquagrid-0.2.0/src/aquagrid/engine/cpu.py +45 -0
- aquagrid-0.2.0/src/aquagrid/engine/gpu.py +87 -0
- aquagrid-0.2.0/src/aquagrid/engine/run.py +119 -0
- aquagrid-0.2.0/src/aquagrid/io/__init__.py +36 -0
- aquagrid-0.2.0/src/aquagrid/io/schema.py +76 -0
- aquagrid-0.2.0/src/aquagrid/io/soil.py +264 -0
- aquagrid-0.2.0/src/aquagrid/io/synthetic.py +164 -0
- aquagrid-0.2.0/src/aquagrid/kernels/__init__.py +5 -0
- aquagrid-0.2.0/src/aquagrid/kernels/constants.py +196 -0
- aquagrid-0.2.0/src/aquagrid/kernels/impl.py +2413 -0
- aquagrid-0.2.0/src/aquagrid/kernels/loader.py +45 -0
- aquagrid-0.2.0/src/aquagrid/params.py +321 -0
- aquagrid-0.2.0/src/aquagrid/pipeline.py +251 -0
- aquagrid-0.2.0/src/aquagrid/soil_grid.py +295 -0
- aquagrid-0.2.0/src/aquagrid.egg-info/PKG-INFO +337 -0
- aquagrid-0.2.0/src/aquagrid.egg-info/SOURCES.txt +37 -0
- aquagrid-0.2.0/src/aquagrid.egg-info/dependency_links.txt +1 -0
- aquagrid-0.2.0/src/aquagrid.egg-info/entry_points.txt +2 -0
- aquagrid-0.2.0/src/aquagrid.egg-info/requires.txt +12 -0
- aquagrid-0.2.0/src/aquagrid.egg-info/top_level.txt +1 -0
- aquagrid-0.2.0/tests/conftest.py +32 -0
- aquagrid-0.2.0/tests/test_gpu.py +84 -0
- aquagrid-0.2.0/tests/test_grid.py +108 -0
- aquagrid-0.2.0/tests/test_io.py +75 -0
- aquagrid-0.2.0/tests/test_parity.py +105 -0
- aquagrid-0.2.0/tests/test_soil.py +289 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2026-09-22
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Rename the project to AquaGrid. The distribution, import, and command are `aquagrid`.
|
|
15
|
+
|
|
16
|
+
## [0.1.1] - 2026-09-16
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- PyPI-friendly README hero (HTML only inside the centered block; version badge from PyPI).
|
|
21
|
+
- CI matrix again covers Ubuntu and Windows on Python 3.11 and 3.12.
|
|
22
|
+
|
|
23
|
+
## [0.1.0] - 2026-09-16
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Initial AquaGrid package: zarr climate/sowing in, Numba CPU and GPU
|
|
28
|
+
kernels, YAML CLI, and pytest suite with bit-exact AquaCrop-OSPy parity.
|
|
29
|
+
|
|
30
|
+
[Unreleased]: https://github.com/Paloschi/aquagrid/compare/v0.2.0...HEAD
|
|
31
|
+
[0.2.0]: https://github.com/Paloschi/aquagrid/compare/v0.1.1...v0.2.0
|
|
32
|
+
[0.1.1]: https://github.com/Paloschi/aquagrid/releases/tag/v0.1.1
|
|
33
|
+
[0.1.0]: https://github.com/Paloschi/aquagrid/releases/tag/v0.1.0
|
aquagrid-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rennan Andres Paloschi
|
|
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.
|
|
22
|
+
|
|
23
|
+
The daily-step kernels in src/aquacrop_grid/kernels/impl.py are derived from
|
|
24
|
+
AquaCrop-OSPy (https://github.com/aquacropos/aquacrop), licensed under the
|
|
25
|
+
Apache License 2.0.
|
aquagrid-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aquagrid
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: AquaCrop on rasters: zarr in/out, Numba-compiled kernels (CPU/GPU)
|
|
5
|
+
Author: Rennan Andres Paloschi
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Paloschi/aquagrid
|
|
8
|
+
Project-URL: Issues, https://github.com/Paloschi/aquagrid/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/Paloschi/aquagrid/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Source, https://github.com/Paloschi/aquagrid
|
|
11
|
+
Keywords: aquacrop,raster,zarr,numba,crop,hydrology
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: numpy>=1.26
|
|
22
|
+
Requires-Dist: numba>=0.59
|
|
23
|
+
Requires-Dist: pandas>=2.0
|
|
24
|
+
Requires-Dist: xarray>=2024.1
|
|
25
|
+
Requires-Dist: zarr<3,>=2.16
|
|
26
|
+
Requires-Dist: dask>=2024.1
|
|
27
|
+
Requires-Dist: typer>=0.12
|
|
28
|
+
Requires-Dist: pyyaml>=6.0
|
|
29
|
+
Requires-Dist: aquacrop>=3.0.11
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
<div align="center">
|
|
35
|
+
<a href="https://github.com/Paloschi/aquagrid"><img alt="AquaGrid" src="https://img.shields.io/badge/AquaGrid-raster%20AquaCrop-0F766E?style=for-the-badge&labelColor=134E4A"></a>
|
|
36
|
+
<h1>AquaGrid</h1>
|
|
37
|
+
<p><strong>Pixel-wise AquaCrop on rasters: zarr in, Numba kernels out — CPU or GPU.</strong></p>
|
|
38
|
+
<p>
|
|
39
|
+
<a href="https://pypi.org/project/aquagrid/"><img alt="PyPI" src="https://img.shields.io/pypi/v/aquagrid.svg?style=flat-square&color=0F766E"></a>
|
|
40
|
+
<a href="https://github.com/Paloschi/aquagrid/actions/workflows/test.yml"><img alt="Tests" src="https://github.com/Paloschi/aquagrid/actions/workflows/test.yml/badge.svg?branch=main"></a>
|
|
41
|
+
<img alt="Python" src="https://img.shields.io/badge/python-3.11%2B-3776AB?style=flat-square&logo=python&logoColor=white">
|
|
42
|
+
<a href="#license-and-attribution"><img alt="License" src="https://img.shields.io/badge/license-MIT-0F766E?style=flat-square"></a>
|
|
43
|
+
<img alt="Visitors" src="https://api.visitorbadge.io/api/visitors?path=github.com%2FPaloschi%2Faquagrid&label=Visitors&countColor=%230F766E&style=flat">
|
|
44
|
+
</p>
|
|
45
|
+
<p>
|
|
46
|
+
<img alt="Numba" src="https://img.shields.io/badge/Numba-CPU%20%7C%20CUDA-00A3E0?style=flat-square">
|
|
47
|
+
<img alt="NumPy" src="https://img.shields.io/badge/NumPy-1.26%2B-013243?style=flat-square&logo=numpy&logoColor=white">
|
|
48
|
+
<img alt="xarray" src="https://img.shields.io/badge/xarray-2024%2B-4D8BBD?style=flat-square">
|
|
49
|
+
<img alt="zarr" src="https://img.shields.io/badge/zarr-2.16%2B-F9C642?style=flat-square&labelColor=1A1A1A">
|
|
50
|
+
<img alt="Dask" src="https://img.shields.io/badge/Dask-2024%2B-FFC107?style=flat-square&logo=dask&logoColor=black">
|
|
51
|
+
<img alt="pytest" src="https://img.shields.io/badge/pytest-8-0A9EDC?style=flat-square&logo=pytest&logoColor=white">
|
|
52
|
+
<img alt="AquaCrop-OSPy" src="https://img.shields.io/badge/AquaCrop--OSPy-3.x-0F766E?style=flat-square">
|
|
53
|
+
</p>
|
|
54
|
+
<p>
|
|
55
|
+
<img alt="Scope" src="https://img.shields.io/badge/scope-rainfed%20%7C%20one%20season-134E4A?style=flat-square">
|
|
56
|
+
<img alt="Parity" src="https://img.shields.io/badge/parity-1e--12%20vs%20OSPy-0F766E?style=flat-square">
|
|
57
|
+
<a href="https://www.conventionalcommits.org/"><img alt="Conventional Commits" src="https://img.shields.io/badge/commits-conventional-FE5196?style=flat-square&logo=conventionalcommits&logoColor=white"></a>
|
|
58
|
+
</p>
|
|
59
|
+
<p>
|
|
60
|
+
<a href="#quick-start">Quick start</a> ·
|
|
61
|
+
<a href="#yaml-config">Config</a> ·
|
|
62
|
+
<a href="#architecture">Architecture</a> ·
|
|
63
|
+
<a href="#io-schema">Schema</a> ·
|
|
64
|
+
<a href="#testing">Testing</a> ·
|
|
65
|
+
<a href="#citing-this-project">Citing</a> ·
|
|
66
|
+
<a href="#license-and-attribution">License</a>
|
|
67
|
+
</p>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<p align="center">
|
|
71
|
+
<img src="docs/images/example-field.png" alt="Soybean field at 30 m: MapBiomas Solo collection 3 clay on the left, AquaCrop dry yield on the right" width="920">
|
|
72
|
+
</p>
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
Climate as zarr cubes `(time, y, x)`, per-pixel sowing dates `(y, x)`, zarr
|
|
77
|
+
outputs. Daily-step kernels from
|
|
78
|
+
[AquaCrop-OSPy](https://github.com/aquacropos/aquacrop) 3.x are vendored and
|
|
79
|
+
recompiled with Numba — `njit` + `prange` on CPU (one thread per pixel) and
|
|
80
|
+
`numba.cuda` on GPU — with **bit-exact parity** against AquaCrop-OSPy
|
|
81
|
+
(`tests/test_parity.py`).
|
|
82
|
+
|
|
83
|
+
This is **not** official FAO AquaCrop and not an aquacropos extension. It
|
|
84
|
+
started in [CyMP](https://github.com/Paloschi/CyMP) (Unioeste-LEA).
|
|
85
|
+
|
|
86
|
+
| Layer | Stack |
|
|
87
|
+
| ---------- | -------------------------------------------------------------------------- |
|
|
88
|
+
| Language | **Python 3.11+** |
|
|
89
|
+
| Kernels | **Numba** (`njit` + `prange` / `numba.cuda`) |
|
|
90
|
+
| Arrays | **NumPy**, **xarray**, **zarr**, **Dask** |
|
|
91
|
+
| Reference | **AquaCrop-OSPy** ≥ 3.0.11 (crop/soil params + parity tests) |
|
|
92
|
+
| CLI | **Typer** (`aquagrid`) |
|
|
93
|
+
| Tests | **pytest** 8 — Ubuntu & Windows, Python 3.11 / 3.12 |
|
|
94
|
+
|
|
95
|
+
**Current scope:** rainfed (no irrigation, no groundwater), one season per
|
|
96
|
+
pixel. Soil: a single AquaCrop preset **or** a per-pixel zarr raster
|
|
97
|
+
(HiHydroSoil hydraulics or sand/silt/clay texture).
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Prerequisites
|
|
102
|
+
|
|
103
|
+
- **Python 3.11+**
|
|
104
|
+
- GPU (optional): NVIDIA GPU with a CUDA **driver** — Numba talks to the
|
|
105
|
+
driver; the full CUDA toolkit is not required
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Quick start
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pip install aquagrid
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
From Git (no clone, before or besides PyPI):
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install "git+https://github.com/Paloschi/aquagrid.git"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For development, clone and install editable:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git clone https://github.com/Paloschi/aquagrid.git
|
|
125
|
+
cd aquagrid
|
|
126
|
+
pip install -e ".[dev]"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# 1. synthetic 10×10 pixels / 540 days
|
|
131
|
+
aquagrid synth --out ./data
|
|
132
|
+
|
|
133
|
+
# 2. config
|
|
134
|
+
cp examples/config.example.yaml ./data/config.yaml
|
|
135
|
+
# (adjust paths if needed)
|
|
136
|
+
|
|
137
|
+
# 3. run
|
|
138
|
+
aquagrid run --config ./data/config.yaml # CPU
|
|
139
|
+
aquagrid run --config ./data/config.yaml -b gpu # GPU
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Output: `output.zarr` with final yield/biomass `(y, x)` and, with
|
|
143
|
+
`save_daily: true`, daily series `(time, y, x)` in group `daily`.
|
|
144
|
+
Full schema: [`docs/zarr-schema.md`](docs/zarr-schema.md).
|
|
145
|
+
|
|
146
|
+
### Programmatic
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from aquagrid.pipeline import run_grid
|
|
150
|
+
|
|
151
|
+
run_grid("climate.zarr", "sowing.zarr", "output.zarr",
|
|
152
|
+
crop_name="Maize", soil_name="SandyLoam",
|
|
153
|
+
backend="cpu", save_daily=False)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## CLI
|
|
159
|
+
|
|
160
|
+
| Command | Purpose |
|
|
161
|
+
| ------- | ------- |
|
|
162
|
+
| `aquagrid synth -o ./data` | Synthetic climate + sowing zarr for tests |
|
|
163
|
+
| `aquagrid run -c config.yaml` | Gridded simulation from YAML (`-b cpu\|gpu`) |
|
|
164
|
+
| `aquagrid bench` | Throughput (pixels/s), excluding JIT compile |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## YAML config
|
|
169
|
+
|
|
170
|
+
```yaml
|
|
171
|
+
climate: data/climate.zarr # cube (time, y, x): tmin, tmax, precip, eto
|
|
172
|
+
sowing: data/sowing.zarr # grid (y, x) int32 YYYYDDD; <=0 = masked
|
|
173
|
+
output: data/output.zarr
|
|
174
|
+
crop:
|
|
175
|
+
name: Maize # any AquaCrop-OSPy crop
|
|
176
|
+
soil:
|
|
177
|
+
name: SandyLoam # AquaCrop preset (xor with zarr below)
|
|
178
|
+
# zarr: data/soil.zarr # ksat/wcsat/wcpf2/wcpf3 or sand/silt/clay
|
|
179
|
+
# ksat_unit: cm/d
|
|
180
|
+
backend: cpu # cpu | gpu
|
|
181
|
+
options:
|
|
182
|
+
save_daily: false
|
|
183
|
+
tile: 128 # spatial tile size (pixels)
|
|
184
|
+
max_season_days: 400
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Copy from [`examples/config.example.yaml`](examples/config.example.yaml).
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Project structure
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
aquagrid/
|
|
195
|
+
├── docs/ # zarr I/O schema
|
|
196
|
+
├── examples/ # sample YAML config
|
|
197
|
+
├── src/aquagrid/
|
|
198
|
+
│ ├── cli.py # Typer: synth / run / bench
|
|
199
|
+
│ ├── pipeline.py # zarr in → tiles → zarr out
|
|
200
|
+
│ ├── params.py # Crop / Soil → kernel arrays
|
|
201
|
+
│ ├── soil_grid.py # PTF + HiHydro layers → compartments
|
|
202
|
+
│ ├── bench.py
|
|
203
|
+
│ ├── engine/
|
|
204
|
+
│ │ ├── cpu.py # njit + prange
|
|
205
|
+
│ │ ├── gpu.py # numba.cuda
|
|
206
|
+
│ │ └── run.py # shared runner over flat arrays
|
|
207
|
+
│ ├── kernels/
|
|
208
|
+
│ │ ├── impl.py # daily step (njit / cuda.jit subset)
|
|
209
|
+
│ │ └── loader.py # compile one source for both backends
|
|
210
|
+
│ └── io/ # schema, validation, synthetic data
|
|
211
|
+
└── tests/ # pytest: parity, grid, soil, io, gpu
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Where to look first
|
|
215
|
+
|
|
216
|
+
| Concern | Location |
|
|
217
|
+
| ------------------ | --------------------------------------------- |
|
|
218
|
+
| Daily AquaCrop step | `src/aquagrid/kernels/impl.py` |
|
|
219
|
+
| CPU / GPU backends | `src/aquagrid/engine/` |
|
|
220
|
+
| Raster pipeline | `src/aquagrid/pipeline.py` |
|
|
221
|
+
| Crop / soil params | `src/aquagrid/params.py` |
|
|
222
|
+
| Soil rasters / PTF | `src/aquagrid/soil_grid.py` |
|
|
223
|
+
| Zarr schema | [`docs/zarr-schema.md`](docs/zarr-schema.md) |
|
|
224
|
+
| Bit-exact parity | `tests/test_parity.py` |
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Architecture
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
climate.zarr (time, y, x) + sowing.zarr (y, x) [+ soil.zarr]
|
|
232
|
+
↓
|
|
233
|
+
pipeline.py (spatial tiles)
|
|
234
|
+
↓
|
|
235
|
+
params.py → kernel arrays
|
|
236
|
+
↓
|
|
237
|
+
engine/run.py → cpu (prange) | gpu (cuda)
|
|
238
|
+
↓
|
|
239
|
+
kernels/impl.py one source, Numba njit / cuda.jit
|
|
240
|
+
↓
|
|
241
|
+
output.zarr
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
- `kernels/impl.py` — AquaCrop daily step ported to a common `njit` /
|
|
245
|
+
`cuda.jit` subset (no allocation in kernels, scalar state per pixel +
|
|
246
|
+
1-D compartment views). One source compiled for both backends by
|
|
247
|
+
`kernels/loader.py`.
|
|
248
|
+
- `params.py` — flattens aquacrop `Crop` / `Soil` into kernel arrays
|
|
249
|
+
(weather-independent init, including deepening the profile to
|
|
250
|
+
`Zmax + 0.1`).
|
|
251
|
+
- GDD phenology is computed **inside the kernel per pixel** (sowing date
|
|
252
|
+
changes each pixel's thermal accumulation), mirroring aquacrop
|
|
253
|
+
`compute_crop_calendar`.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## I/O schema
|
|
258
|
+
|
|
259
|
+
| Store | Shape | Role |
|
|
260
|
+
| -------- | ------------ | ---- |
|
|
261
|
+
| Climate | `(time, y, x)` | `tmin`, `tmax`, `precip`, `eto` (daily, gap-free) |
|
|
262
|
+
| Sowing | `(y, x)` | `int32` YYYYDDD; `<= 0` = mask |
|
|
263
|
+
| Soil | name **or** zarr | AquaCrop preset, or hydraulic / texture raster |
|
|
264
|
+
| Output | `(y, x)` | yield, biomass, status; optional `daily/` group |
|
|
265
|
+
|
|
266
|
+
Grids must already be aligned — AquaGrid does not reproject.
|
|
267
|
+
Details, units, and soil bands: [`docs/zarr-schema.md`](docs/zarr-schema.md).
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Benchmark
|
|
272
|
+
|
|
273
|
+
`aquagrid bench --pixels 65536 --days 540` (excluding JIT compile):
|
|
274
|
+
|
|
275
|
+
| Backend | Reference hardware | Throughput |
|
|
276
|
+
| ------- | ------------------ | ---------- |
|
|
277
|
+
| CPU (`njit` + `prange`) | Ryzen (all threads) | ~58k pixels/s |
|
|
278
|
+
| GPU (`numba.cuda`) | RTX 3060 | ~61k pixels/s |
|
|
279
|
+
|
|
280
|
+
One full season (540 days) per pixel. On larger grids the GPU scales better
|
|
281
|
+
(climate transfer dominates on small grids).
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Testing
|
|
286
|
+
|
|
287
|
+
[](https://github.com/Paloschi/aquagrid/actions/workflows/test.yml)
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
pytest # parity vs AquaCrop-OSPy, io, grid driver, gpu (if present)
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
| File | What it covers |
|
|
294
|
+
| ---- | -------------- |
|
|
295
|
+
| `test_parity.py` | Single pixel vs AquaCrop-OSPy, 1e-12 (maize/soybean, calendar and GDD, 3 soils) |
|
|
296
|
+
| `test_grid.py` | Mask, per-pixel sowing, tiles, grid vs single-pixel equality |
|
|
297
|
+
| `test_soil.py` | Hydraulic/texture zarr, Saxton–Rawls PTF, per-pixel soil |
|
|
298
|
+
| `test_io.py` | Synthetic I/O, sowing → plant index |
|
|
299
|
+
| `test_gpu.py` | CPU vs GPU parity (skipped without CUDA) |
|
|
300
|
+
|
|
301
|
+
CI (GitHub Actions) runs on every **pull request** against `main`, and again
|
|
302
|
+
on push to `main`: Ubuntu and Windows × Python 3.11 / 3.12. Hosted runners
|
|
303
|
+
are CPU-only; `test_gpu.py` is skipped.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Contributing
|
|
308
|
+
|
|
309
|
+
1. Use **conventional commits** (`feat:`, `fix:`, `chore:`, `ci:`, `docs:`).
|
|
310
|
+
2. Put tests in the same change as the behaviour they cover.
|
|
311
|
+
3. Open a pull request against `main` — CI must pass before merge.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Citing this project
|
|
316
|
+
|
|
317
|
+
If you use AquaGrid in research or operational work, please cite this repository:
|
|
318
|
+
|
|
319
|
+
```bibtex
|
|
320
|
+
@software{paloschi_aquagrid,
|
|
321
|
+
author = {Paloschi, Rennan Andres},
|
|
322
|
+
title = {AquaGrid: pixel-wise AquaCrop on rasters (Numba CPU/GPU)},
|
|
323
|
+
year = {2026},
|
|
324
|
+
url = {https://github.com/Paloschi/aquagrid},
|
|
325
|
+
version = {0.1.0}
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Also acknowledge [AquaCrop-OSPy](https://github.com/aquacropos/aquacrop) (and FAO AquaCrop) for the underlying crop water-productivity model that the kernels follow.
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## License and attribution
|
|
335
|
+
|
|
336
|
+
**MIT.** Kernels in `src/aquagrid/kernels/impl.py` are derived from
|
|
337
|
+
[AquaCrop-OSPy](https://github.com/aquacropos/aquacrop) (**Apache-2.0**).
|