crop-type-map

unverified
v0.1 AOI: San Joaquin Valley cropland block · bbox -120.05, 36.55, -119.85, 36.72

Label-free (unsupervised) per-field crop-type mapping from a multi-index Sentinel-2 phenology SIGNATURE. For an AOI covered by a Fields of the World boundary set, compute an NDVI + EVI + NDRE time series, fit harmonic curves to each index to extract its amplitude (how much the crop greens/matures) and phase (WHEN it peaks — the crop calendar), stack those (index × harmonic) features into a per-pixel signature, and cluster the signature with k-means into crop GROUPS. Per-field majority vote over the cluster raster gives one crop-group label per field. The per-field group table is the primary product; the multi-index stack and harmonic amplitude/phase rasters are the inspectable "show your work" layers. This is the honest FIRST version: it needs NO training labels — it discovers crop groups from the phenology structure itself. The clusters are anonymous ("group 0/1/2…") until named; where USDA CDL (boryan-2011) covers the AOI, the optional validation step names each cluster by its majority CDL class and reports cluster↔CDL agreement. The SUPERVISED path (a CDL-trained classifier that emits named crop classes directly, no post-hoc naming) is the v2 — see the NOTE on compute/crop_cluster. This extends crop-monitoring (single-index NDVI vigor/phenology) with two additions: a multi-index signature (NDRE separates canopy N / structure that NDVI alone misses) and an unsupervised clustering head that turns the signature into a discrete crop-group layer.

Primary outputs
compute/field_group
Show your work
compute/indices compute/phenology compute/crop_cluster
Provenance
source_scene_ids
License
recipe
Apache-2.0
outputs
CC-BY-4.0
Map preview and live runs are available in the workbench.

The contract

legacy dialectcandidate

Read from this recipe's own declarations — parameters:, outputs:, requires:, and the ops its layers name. Not from its style blocks and not from any benchmark: a colour ramp is not a contract, and a measured run is evidence about one AOI rather than a domain.

Parameters

The legacy dialect has no typed parameter schema. Read the folia.yaml for what this recipe takes; nothing here can type-check it.

Outputs

outputkindlayerwhat it is
primary not declared ['compute/field_group']
show_your_work not declared ['compute/indices', 'compute/phenology', 'compute/crop_cluster']
provenance not declared ['source_scene_ids']

Capabilities it requires

The legacy dialect has no requires: block.

Where it runs

  • Browser preview does not run here compute/crop_cluster: carries an unsubstituted ${...} template; compute/field_group: carries an unsubstituted ${...} template; compute/indices: layer type "raster_timeseries" is not one folia-view parses; and 2 more
  • Local CLI (folia run) runs here runs locally through the legacy (no spec_version) parser
  • Operated fleet (POST /plan, /run) runs here legacy dialect: a lock binds by the cut's layer names, not by digest
open in Workbench from registry/recipes/crop-type-map/folia.yaml