Environmental data (via the lab stores)¶
Climate, terrain, and soil context for the same bounding box and date range as the Sentinel-2 pipeline. Each source lives in its own machine-wide, self-filling store — nothing is ever downloaded twice, and overlapping queries share every byte already fetched. PaddockTS calls the stores directly; the packages are equally usable standalone.
| Source | Package | What it provides | Auth required |
|---|---|---|---|
| Copernicus DEM 30 m | pycopdem |
elevation + on-read slope / aspect / flow accumulation / TWI / HLI | none |
| OzWALD | pyozwald |
daily meteorology (~5 km) + 8-day biophysical series (~500 m) at AOI centre | none |
| SILO | pysilo |
daily climate (T, rain, radiation, ET, vapour pressure) at AOI centre | |
| SLGA | pyslga |
~90 m soil properties (16 attributes × 6 depths), clipped to AOI | TERN API key |
The Sentinel-2 → PaddockTS chain itself doesn't depend on any of these — they're independent context layers, useful for downstream analyses that combine remote sensing with weather, soil, or topography.
Every store follows the same design: a troi-agnostic core
(get_ds(bbox, ...) / get_df(lat, lon, ...)), a *_troi adapter
for pipelines that speak the shared Troi, and a fill(...) that
returns how much was actually downloaded (0 = fully cached).
Terrain — Copernicus DEM 30 m (pycopdem)¶
One sparse global Zarr on the DEM's native 1-arc-second grid; a chunk is fetched with a single windowed COG read and never re-downloaded. Slope, aspect, flow accumulation (pysheds), TWI and Heat Load Index are computed on read, never stored.
from datetime import date
from troi.troi import Troi
from pycopdem.store import Store
q = Troi(
bbox=[148.36265, -33.52606, 148.38265, -33.50606],
start=date(2024, 1, 1),
end=date(2024, 12, 31),
stub="env_demo",
)
ds = Store(config=q.config).get_ds_troi(q, derivatives=('slope', 'twi'))
ds['elevation'] # (lat, lon), metres
ds['slope'] # degrees, computed on read
Dates on the troi are ignored — elevation is time-invariant. Use with
terrain_tiles_plot to render elevation /
slope / aspect / flow accumulation.
OzWALD — daily meteorology + 8-day biophysical (pyozwald)¶
Point series sampled at the AOI centre from NCI THREDDS (OPeNDAP), stored per (grid point, variable, year) so an in-progress year keeps re-fetching until complete, then never again.
from pyozwald.store import Store
store = Store(config=q.config)
met = store.get_df_troi(q, cadence='daily') # Pg, Tmax, Tmin, Uavg, ...
veg = store.get_df_troi(q, cadence='8day',
variables=['NDVI', 'LAI', 'GPP', 'Ssoil'])
Daily meteorology snaps to OzWALD's ~5 km grid, the 8-day biophysical variables to its ~500 m grid — nearby farms in the same cell share one stored series.
SILO — daily climate (pysilo)¶
Point series from the DataDrill endpoint at the AOI centre, snapped to
SILO's native 0.05° (~5 km) grid, with a coverage-span ledger so only
missing date ranges are ever requested. Requires a registration email
(email in ~/.config/Troi.json, or TROI_EMAIL).
from pysilo.store import Store
df = Store(config=q.config).get_df_troi(q)
df.columns # date, daily_rain, max_temp, min_temp, radiation, vp, et_short_crop, ... (18 vars)
SLGA — soil properties (pyslga)¶
National ~90 m COGs, one per attribute × depth, windowed-read per chunk
into a sparse store. Layer filenames are resolved from the TERN
datastore listing at first contact (release dates differ per
attribute). Pixel reads require a TERN API key (tern_api_key in
~/.config/Troi.json, or TROI_TERN_KEY — free from
https://account.tern.org.au/); cached reads need no key.
from pyslga.store import Store
ds = Store(config=q.config).get_ds_troi(
q, attributes=('Clay', 'Sand', 'Silt', 'pH_Water'),
depths=('0-5cm', '5-15cm'))
ds['Clay_5-15cm'] # (lat, lon), percent
DAESIM forcing¶
PaddockTS.daesim_forcing assembles the DAESIM
climate-forcing table (SILO radiation + OzWALD daily meteorology +
8-day biophysical series forward-filled to daily, renamed to DAESIM's
vocabulary) from the stores, cached per stub as
{out_dir}/{stub}_DAESim_forcing.csv:
from PaddockTS.daesim_forcing import daesim_forcing
df = daesim_forcing(q) # date + 10 DAESIM columns, one row per day
Reference¶
Full API reference for each store lives in its own repository — see the READMEs (each has a live-measured Performance section) and module docstrings.
daesim_forcing¶
PaddockTS.daesim_forcing.daesim_forcing ¶
DAESIM forcing for the centre of troi.bbox, cached as
{troi.out_dir}/{troi.stub}_DAESim_forcing.csv.
The CSV cache makes the assembled product reproducible per stub; the underlying observations are cached machine-wide by the stores regardless, so even a cache miss here re-downloads nothing already held locally.