crop-type-map
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.
- recipe
- Apache-2.0
- outputs
- CC-BY-4.0
The contract
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
| output | kind | layer | what 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
registry/recipes/crop-type-map/folia.yaml