GeoAquaCrop Visualize
An interactive Dash/Plotly application for exploring gridded AquaCrop-OSPy simulations. Point it at a completed model run and it gives you a map of the region, a variable picker, and a click-through to per-cell daily time series — plus the inputs those runs were driven by, and a gridded export of anything you select.
- Requirements
- Installation
- Connecting your data
- Running the app
- Using the app
- Exporting data
- Configuration
- Project structure
- Running the tests
- Documentation
- Troubleshooting
What you get
| Choropleth maps | 11 seasonal output variables (yield, production, irrigation, ET, water productivity) over the simulation grid, on an OpenFreeMap Positron basemap with the region outline traced on top. |
| Daily time series | 13 daily variables (water fluxes, soil water, crop development) for any cell, read straight from the simulation's daily tables. |
| Model inputs | The climate forcing (4 variables), the crop calendar, and SPAM physical crop areas, on the same grid as the outputs. |
| Spatial selection | Click a cell for its time series; lasso or box-select many cells to highlight them and scope an export to just that area. |
| Season handling | One season at a time, or All years aggregated by mean or sum — each variable carries a sensible default. |
| Gridded export | Any set of cells, variables, and dates to NetCDF, GeoTIFF, or CSV. |
Everything loads once at startup, so interaction is instant afterwards.
Requirements
- Python 3.11 or newer
- A completed AquaCrop run. The app is a viewer, not a model — it reads the
outputs of
geoaquacrop-simulateand the preprocessed inputs fromgeoaquacrop-preprocess. See Connecting your data.
Runtime dependencies (pandas, numpy, xarray, netCDF4, scipy,
plotly, dash, dash-bootstrap-components) install automatically.
Installation
pip install "geoaquacrop_visualize[geotiff]"
From a checkout, use pip install -e ".[geotiff]" instead. The project uses a
src layout, so the package is importable only once it is installed.
| Extra | Adds | For |
|---|---|---|
geotiff |
rasterio |
GeoTIFF export. Without it, that one format is skipped and the other two still work. |
test |
pytest |
The test suite. |
docs |
Sphinx, sphinx-rtd-theme |
Building the documentation. |
dev |
all of the above | Contributing. |
Dependencies are declared without version constraints, so pip resolves whatever
is current. If you need a reproducible environment, capture one with
pip freeze > requirements.txt after a working install.
Connecting your data
By default the app looks for its data in the folder you launch it from, or in
the workspace root given by --root / $GEOAQUACROP_ROOT:
<working directory>/ # or $GEOAQUACROP_ROOT
├── outputs/ # $GEOAQUACROP_OUTPUTS
│ ├── summary_results_<timestamp>.pkl # seasonal results per cell
│ └── daily_results_<timestamp>.pkl # daily tables per cell
├── processed/ # $GEOAQUACROP_PROCESSED
│ ├── MaxTemp*.nc MinTemp*.nc Precipitation*.nc ReferenceET*.nc
│ ├── cropcalendar.nc
│ └── spam*_physical_area.nc
└── region.geojson # $GEOAQUACROP_REGION — region outline
Data somewhere else. Pass the locations as options (--root, --outputs,
--processed, --region, --exports), as the matching keyword arguments of
run(), or set the environment variables:
export GEOAQUACROP_OUTPUTS=/path/to/geoaquacrop-simulate/outputs
export GEOAQUACROP_PROCESSED=/path/to/geoaquacrop-preprocess/processed
export GEOAQUACROP_REGION=/path/to/geoaquacrop-preprocess/inputdata/region.geojson
Choosing a run. If outputs/ holds several runs, the newest
summary_results_*.pkl and daily_results_*.pkl (by filename) are loaded.
To view a different run, point GEOAQUACROP_OUTPUTS at a folder that holds it.
No data is bundled with this repository, and none needs to be copied into it. The region outline, for instance, is read from
GEOJSON_PATHand thinned in memory at startup — seeboundary.py.
Running the app
From the command line:
geoaquacrop_visualize --root /path/to/workspace # console script
Run geoaquacrop_visualize --help for every option, including --port and
--debug.
From Python:
import geoaquacrop_visualize as visualize
visualize.run(outputs="/path/to/outputs", port=8050)
Then open http://localhost:8050.
Startup loads every dataset, pre-computes the aggregations, and prints a couple of diagnostic lines (the auto-derived map zoom, and the region boundary statistics). Expect a few seconds, depending on the size of your run.
Deploying behind a WSGI server. build_app() assembles the app without
starting a server:
from geoaquacrop_visualize import build_app
server = build_app().server # WSGI entry point for gunicorn etc.
Using the app
The window is a control sidebar on the left and a map canvas on the right. Two tabs at the top of the sidebar switch what you are looking at.
Simulation Outputs tab
- Choose a crop and irrigation type, then a season — a single harvest year, or All years.
- When All years is selected, an Aggregation toggle appears: Mean or Sum. Each variable has a sensible default (yields average, irrigation and production sum).
- Pick a map variable from the accordion, grouped as Yield & Production, Water Balance, and Water Productivity. The map recolours immediately.
- Click any cell to open its daily time series below the map. Choose the daily variable from the Water Fluxes, Soil Water, and Crop Development groups.
- Click two points on the time series to mark a window: the app shades it, draws the mean as a dashed line, and reports the mean ± standard deviation over that period. A third click clears it.
- Lasso or box-select a group of cells (the tools are in the Plotly toolbar at the top-right of the map) to highlight them in orange. The count appears in the ribbon above the map, and the export dialog can then be scoped to just that selection.
Inputs tab
Shows the data that drove the simulation, on the same grid: the climate variable of your choice (max/min temperature, precipitation, reference ET), the crop calendar for the selected cell, and SPAM physical crop areas for the selected crop. Clicking a cell here opens the climate time series for that cell.
Map controls
Pan and zoom are preserved as you change variables, so you can stay zoomed into one area while cycling through the outputs. Hovering a cell shows its coordinates and the current variable's value.
Exporting data
⬇ Export Data… at the bottom of the sidebar opens a dialog with four choices:
| Choice | Options |
|---|---|
| Variables | Any of the 13 daily variables, grouped as in the sidebar. |
| Period | The whole simulation, or an explicit start and end date. |
| Cells | The whole area, or just your current map selection. |
| Format | NetCDF (.nc), GeoTIFF (.tif), CSV (.csv) — any combination. |
Output is assembled as a time × y × x grid per variable and written to
<root>/outputs/exports/ (override with --exports or $GEOAQUACROP_EXPORTS). The dialog reports the filenames it wrote.
GeoTIFF needs rasterio. If it is missing, that format is skipped with a note
in the status message and the others are still written.
Configuration
All user-facing settings live in
src/geoaquacrop_visualize/config.py.
| Setting | Default | What it does |
|---|---|---|
ROOT |
$GEOAQUACROP_ROOT or the working directory |
Workspace root; the locations below default to paths under it. |
OUTPUTS_DIR |
$GEOAQUACROP_OUTPUTS or outputs |
Folder holding the simulation result pickles. |
PROCESSED_DIR |
$GEOAQUACROP_PROCESSED or processed |
Climate, crop calendar, and SPAM grids. |
GEOJSON_PATH |
$GEOAQUACROP_REGION or region.geojson |
The region outline. |
CELL_RES |
$GEOAQUACROP_CELL_RES or 0.05 |
Grid cell size in degrees. Must match the preprocessing grid. |
SUMMARY_PKL, DAILY_PKL |
newest match in OUTPUTS_DIR |
Which simulation run to display. |
EXPORT_DIR |
$GEOAQUACROP_EXPORTS or outputs/exports |
Where exports are written. |
PORT |
$GEOAQUACROP_PORT or 8050 |
Port the app serves on. |
MAP_HEIGHT, TS_HEIGHT |
550, 400 |
Canvas heights in pixels. |
BOUNDARY_SIMPLIFY_EPS |
0.004 |
Outline simplification tolerance in degrees (~400 m). Raise for a lighter outline, lower for a crisper one. |
MAP_VARIABLES |
11 entries | Map variable catalogue: label, colourscale, default aggregation. |
DAILY_VARIABLES |
13 entries | Daily variable catalogue: label, source table, line colour. |
CLIMATE_VARIABLES |
4 entries | Climate variable catalogue. |
Adding a variable is a matter of adding an entry to the relevant catalogue — the sidebar, the maps, and the export dialog all read from these dictionaries.
Project structure
geoaquacrop_visualize/
├── pyproject.toml # Packaging + pytest configuration
├── src/
│ └── geoaquacrop_visualize/ # Application package, 22 modules
│ ├── __init__.py # ← run() / build_app(), console script entry
│ ├── config.py # ← paths, sizes, variable catalogues
│ ├── utils.py data.py grid.py aggregates.py queries.py
│ ├── boundary.py # ← region outline, thinned and served by URL
│ ├── export.py figures_maps.py figures_timeseries.py
│ ├── styles.py app_shell.py
│ ├── layout*.py # ← sidebar, panels, export modal, assembly
│ └── callbacks_*.py # ← controls, selection, maps, ts, export
├── tests/ # One test module per application module
└── docs/ # Sphinx sources (Read the Docs)
Importing the package loads no data; the datasets are read and the app is
assembled only when run() or build_app() is called.
The package is split by concern, and the split is enforced: the test suite
checks that no module exceeds 500 lines, that the import graph stays acyclic,
that callbacks never import each other, and that only data.py opens the
pickles — so the datasets can only ever be loaded once.
Running the tests
pip install -e ".[test]"
pytest # whole suite
pytest tests/test_utils.py -v # a single module
pytest -k colorscale # by keyword
No data files are required to run the tests.
Documentation
Full documentation — architecture, API reference, and configuration — is built
with Sphinx from docs/ and hosted on Read the Docs. To build it locally:
pip install -e ".[docs]"
sphinx-build -b html docs docs/_build/html
Troubleshooting
FileNotFoundError at startup
A data file was not found where config.py expects it. The error names the
missing path. Either launch the app from the folder holding outputs/,
processed/, and region.geojson, pass --root, or point at each location
with --outputs, --processed, and --region (or the matching
GEOAQUACROP_* variables).
The wrong run is displayed
The newest summary_results_*.pkl and daily_results_*.pkl in
GEOAQUACROP_OUTPUTS are loaded. Make sure both come from the same run, or
point GEOAQUACROP_OUTPUTS at a folder holding only the run you want.
No region outline on the map
The outline is served from /region-boundary.geojson, derived at startup from
GEOJSON_PATH. Startup prints a Region boundary: … line reporting how many
polygons and vertices it produced — if that line is missing or reports zero, the
source GeoJSON is the place to look.
(rasterio not installed — GeoTIFF skipped) in the export status
Install the optional extra: pip install "geoaquacrop_visualize[geotiff]".
The map is blank but the sidebar works The basemap tiles come from OpenFreeMap's public tile server, so the app needs network access to draw them. The data layers render regardless.
Acknowledgements
The basemap uses the Positron style from OpenFreeMap. Map data: © OpenMapTiles, data from OpenStreetMap.
Metadata
Release files for geoaquacrop-visualize 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| geoaquacrop_visualize-0.1.0.tar.gz | 83.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| geoaquacrop_visualize-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 143.9 kB
Release files / geoaquacrop_visualize-0.1.0.tar.gz
| Download URL | geoaquacrop_visualize-0.1.0.tar.gz |
|---|---|
| Size | 83.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
26df406df340d9f4a77d2cc6f3bb0144e7378b9e2185d4beb0be5ee76cf6b333
|
|
BLAKE2b-256 checksum How to use checksums |
a75e50c13cb742a9c7d77d75fc83e529e130162b462f017c6049526858fe9f33
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logRelease files / geoaquacrop_visualize-0.1.0-py3-none-any.whl
| Download URL | geoaquacrop_visualize-0.1.0-py3-none-any.whl |
|---|---|
| Size | 60.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7529241befa9012d08001592a7f165d53464366dc9dc3707c4e766975c2f4c93
|
|
BLAKE2b-256 checksum How to use checksums |
1e764ad7919cb6df92f1b339e1de7e6a71dbbca6d99458c8f24b6fe9b6546be4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency log