Application Data Preparation¶
This guide covers how to prepare the data files that Decision Theatre consumes.
nix run .#check-data. Vector Map Tiles (MBTiles)¶
Source Data¶
The map data originates from a GeoPackage file (UoW_layers.gpkg) containing:
| Layer | Description |
|---|---|
ne_african_countries | Country boundaries from Natural Earth |
ne_10m_rivers | Major river networks |
ne_10m_lakes | Lake boundaries |
ecoregions | Ecological region boundaries |
catchments_lev12 | Level-12 catchment boundaries |
ne_10m_populated_places | Cities and towns |
Conversion Pipeline¶
The script resources/mbtiles/gpkg_to_mbtiles.sh automates the full conversion:
The script stages output in resources/mbtiles/ during processing, then moves the final africa.mbtiles to data/mbtiles/ on completion.
Pipeline stages:
- Layer discovery -- queries
gpkg_contentsfor all feature layers - Geometry validation -- checks for NULL geometries; optionally repairs with
ogr2ogr -makevalid - GeoJSONSeq export -- converts each layer to newline-delimited GeoJSON using
ogr2ogr - Per-layer tile generation -- runs
tippecanoefor each layer with configured zoom ranges - Merge -- combines all per-layer MBTiles into a single file using
tile-join
Zoom Configuration¶
Each layer has configured minimum and maximum zoom levels:
| Layer | Min Zoom | Max Zoom |
|---|---|---|
ne_african_countries | 2 | 10 |
ne_10m_rivers | 6 | 15 |
ne_10m_lakes | 6 | 15 |
ecoregions | 2 | 8 |
catchments_lev12 | 8 | 15 |
ne_10m_populated_places | 6 | 15 |
Layers not in this table default to zoom 6--15.
Required Tools¶
ogr2ogr(GDAL)tippecanoesqlite3
All are available in the Nix dev shell (nix develop).
Map Style¶
The MapBox GL Style JSON at data/mbtiles/style.json defines how each layer is rendered (colours, line widths, label placement). Edit this file to change the map's visual appearance.
Fetching Data from Google Drive¶
The script scripts/fetch-data.sh downloads all files from a shared Google Drive folder (including subfolders) directly into the data/ directory, preserving the folder structure. Run this before dt geopackage to pull the latest source files in one step.
Installation: rclone¶
The script requires rclone, a command-line tool for cloud storage. Install it once on your machine:
Download the installer from rclone.org/downloads and add rclone.exe to your PATH.
One-time Google Drive configuration¶
rclone needs a named remote that points to your Google Drive account. Create one called gdrive by running:
Follow the interactive prompts:
- Press
nfor New remote. - Name it
gdrive. - Choose Google Drive 24 as the storage type.
- Leave the client ID and secret blank (uses rclone's defaults).
- Choose scope
drive.readonly2 if you only need to download, ordrivefor full access. - Follow the browser OAuth flow to authorise rclone with your Google account.
- Accept the default for all remaining options and confirm.
Verify the remote works:
Service account authentication
For automated or CI environments, use a Google service account instead of OAuth. Pass --drive-service-account-file /path/to/key.json to rclone, or add it to your remote configuration during rclone config.
Finding the folder ID¶
Open the Google Drive folder in your browser. The folder ID is the last segment of the URL:
https://drive.google.com/drive/folders/1ABCdef_ghiJKLmnopQRSTuvwXYZ
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
this is the folder ID
The folder must be shared with the Google account you authenticated with rclone, or set to Anyone with the link.
Usage¶
# Using Make (recommended)
dt fetch-data FOLDER=<folder-id-or-url>
# Or directly
./scripts/fetch-data.sh <folder-id-or-url> [data-dir]
Both a bare folder ID and a full URL are accepted:
# Bare folder ID
dt fetch-data FOLDER=1ABCdef_ghiJKLmnopQRSTuvwXYZ
# Full shareable URL
dt fetch-data FOLDER="https://drive.google.com/drive/folders/1ABCdef_ghiJKLmnopQRSTuvwXYZ"
# Custom destination directory
./scripts/fetch-data.sh 1ABCdef_ghiJKLmnopQRSTuvwXYZ /path/to/data
What the script does¶
- Extracts the folder ID from the argument (whether a bare ID or URL).
- Checks that rclone is installed and the
gdriveremote exists. - Copies all files from the Drive folder and any subfolders into
data/usingrclone copy, preserving the subfolder structure. - Skips files that are already up-to-date (same size and modification time).
- Retries automatically on transient network errors.
- Prints a summary of all files in
data/with their sizes when complete.
Using a different remote name¶
If your rclone Google Drive remote is not called gdrive, set the RCLONE_REMOTE environment variable:
Full workflow¶
# 1. Download the CSV source files from Google Drive
dt fetch-data FOLDER=1ABCdef_ghiJKLmnopQRSTuvwXYZ
# 2. Build the GeoPackage datapack
dt geopackage
# 3. Launch the application
dt app
Scenario Data (GeoPackage Datapack)¶
The application uses a GeoPackage file (datapack.gpkg) containing catchment geometries and scenario data. This is built from raw input files using the scripts/build-geopackage.sh script.
Input Files¶
Place the following files in the data/ directory:
Geometry¶
| File | Required | Description |
|---|---|---|
catchments.gpkg | Yes | GeoPackage containing catchment polygon geometries in a layer named catchments_lev12. Each feature must have a HYBAS_ID attribute that matches the catchID column in the scenario CSVs. |
Scenario CSVs¶
All scenario CSVs must have a catchID column that cross-references HYBAS_ID in catchments.gpkg. All other columns are per-catchment indicator values stored as REAL in the database (NA becomes NULL).
| File | Required | Description |
|---|---|---|
current.csv | Yes | Per-catchment indicator values for the current scenario. |
reference.csv | Yes | Per-catchment indicator values for the reference (historical baseline) scenario. |
current_lower.csv | Yes | Lower-bound uncertainty values for the current scenario. Displayed as the lower whisker in boxplot charts. |
current_upper.csv | Yes | Upper-bound uncertainty values for the current scenario. Displayed as the upper whisker in boxplot charts. |
reference_lower.csv | Yes | Lower-bound uncertainty values for the reference scenario. |
reference_upper.csv | Yes | Upper-bound uncertainty values for the reference scenario. |
Metadata¶
| File | Required | Description |
|---|---|---|
metadata.csv | Yes | Human-readable labels, units, chart types, map colours, and user-input flags for each indicator column. Without it the app still runs but uses raw column names with no colour coding or chart type detection. See the Datapack Format page for a full column-by-column reference. |
Ecological Lookup Tables¶
These files support the cascading recalculation workflow triggered when a user adjusts a target indicator. All three are optional — if absent the application falls back to proportional scaling.
| File | Required | Description |
|---|---|---|
NPP_by_treecover.csv | Yes | Per-catchment net primary productivity (g/m²) indexed by catchID, with one column per tree-cover class bin (X0_5 through X80_100). Used to recalculate NPP when the user adjusts tree-cover targets. |
deltaSOC_bytcc_Mgha.csv | Yes | Per-catchment change in soil organic carbon (ΔSOCc, Mg/ha) by tree-cover class. Same structure as NPP_by_treecover.csv. Used to recalculate soil carbon when tree-cover proportions change. |
herb_traits_ready.csv | Yes | Per-species herbivore trait table indexed by Common_name. Columns include Body_mass, Diet, HFT_BII, Prop_Grass, DMI_kg_indiv_yr, and CH4_kg_indiv_yr. Species names must match the suffixes used in the herbs_sp_* and herbs_fg_* indicator columns in the scenario CSVs. |
See the Datapack Format page for the full column specifications of each lookup file.
Building the Datapack¶
This script performs the following steps:
- Base setup — Copies
catchments.gpkgas the base for the output file - CSV import — Imports scenario CSVs as raw tables using
ogr2ogr - Type conversion — Converts data columns to REAL type, converting
NAstrings to NULL - Column normalization — Normalizes column names across tables (replaces dashes, spaces with dots)
- Indexing — Creates integer indexes on catchment IDs for fast joins
- GeoJSON precomputation — Converts geometries to GeoJSON for fast API serving
- Domain min/max — Computes global min/max for each attribute across both scenarios
Output GeoPackage Schema¶
The output datapack.gpkg contains these tables:
| Table | Description |
|---|---|
catchments_lev12 | Catchment polygons with HYBAS_ID, geom, and precomputed geojson |
scenario_current | Current scenario data with normalized column names |
scenario_reference | Reference scenario data with normalized column names |
domain_minima | Global minimum values for each attribute across both scenarios |
domain_maxima | Global maximum values for each attribute across both scenarios |
metadata | (If provided) Column descriptions from the metadata CSV |
Scenario Tables Schema¶
Both scenario_current and scenario_reference tables have:
catchment_id(TEXT) — The catchment identifier (normalized fromcatchID)catchment_id_int(INTEGER) — Integer version for indexed joins- All attribute columns as REAL type (NULL for missing/NA values)
Domain Tables Schema¶
The domain_minima and domain_maxima tables each contain one row with:
- All attribute columns from the scenario tables
- Each column contains the global min (or max) value computed across both scenarios
- These are used for consistent color scaling across scenario comparisons
Column Normalization¶
The build script normalizes column names to ensure consistency between tables:
catchID→catchment_id- Dashes (
-), spaces, apostrophes → dots (.) - Multiple consecutive dots → single dot
- Duplicate ID columns (e.g.,
sp_current.catchID) are dropped
Required Tools¶
ogr2ogr(GDAL)sqlite3python3
All are available in the Nix dev shell (nix develop).