t.crop.stage estimates the current crop growth stage, per pixel,
from an NDVI space time raster dataset (STRDS) using a crop-agnostic,
curve-relative model. Most row crops and vegetables follow a similar NDVI
trajectory over a growing season — a rise to peak vegetative vigor
followed by senescence — so a single curve-relative model can locate
"where on the curve" a given pixel currently sits, without crop-specific
calibration.
The output is a single classified raster map with five generic stages:
Category
Stage
Description
1
A
Bare soil / planting / emergence
2
B
Greenup / rapid growth
3
C
Peak maturity
4
D
Senescence
5
E
Post-harvest / residue / bare soil
Pixels whose NDVI series is too short or too sparse (fewer than
min_observations days once resampled to a daily grid) are left NULL
in the output.
For each pixel, the maps registered in the input STRDS (optionally
filtered with where) are read in the current computational region,
resampled to a daily grid, gap-filled with PCHIP interpolation, and smoothed
with a Whittaker filter. The stage of the last observation is then
decided from three signals:
Signal
Description
NDVI level
Position relative to the adaptive lower_threshold / upper (peak) threshold
Trend
Rising or falling, estimated with a Kalman filter
Peak history
Whether a genuine seasonal peak has already been confirmed
Stage
NDVI level
Trend
Peak confirmed
A
below lower threshold
any
no
B
between thresholds
rising
no
C
at/above upper threshold
any
—
D
between thresholds
falling
yes
E
below lower threshold
any
yes
The upper (peak) threshold is derived per pixel as
max(percentile(NDVI, upper_percentile), min_peak_ndvi); a peak
only counts as "confirmed" once the pixel stays above it for at least
min_peak_width consecutive days (guards against noise spikes).
With the -e flag, four additional DCELL maps are written alongside
output:
output_velocity — Kalman-estimated NDVI rate of change (NDVI/day)
output_value — last NDVI value used in the estimate
output_days_since_peak — days elapsed since the detected seasonal peak
output_upper_threshold — the adaptive upper threshold used per pixel
The module operates on the current computational region —
set g.region to the input STRDS extent/resolution beforehand
(e.g. t.info -g input=ndvi_strds followed by
g.region).
Per-pixel estimation (PCHIP interpolation, Whittaker smoothing, Kalman
filtering) is done in Python and is the dominant cost; keep the region to
the field/site extent you actually need. Use nprocs to parallelize
across pixels.
NDVI values are expected in the conventional [-1, 1] (or [0, 1]) range;
no rescaling is performed.
The underlying algorithm is adapted from the
crop-stage-detection
project (NASA Harvest / Agmatix); see NOTICE in the addon
source for attribution.