Skip to main content

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.


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-simulate and the preprocessed inputs from geoaquacrop-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_PATH and thinned in memory at startup — see boundary.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

  1. Choose a crop and irrigation type, then a season — a single harvest year, or All years.
  2. When All years is selected, an Aggregation toggle appears: Mean or Sum. Each variable has a sensible default (yields average, irrigation and production sum).
  3. Pick a map variable from the accordion, grouped as Yield & Production, Water Balance, and Water Productivity. The map recolours immediately.
  4. 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.
  5. 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.
  6. 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)

Source distribution for geoaquacrop-visualize 0.1.0
File Size Uploaded
geoaquacrop_visualize-0.1.0.tar.gz 83.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for geoaquacrop-visualize 0.1.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page