{"id":"climate_anomaly","summary":"Compute an anomaly (observed − climatological normal) and publish it as a new GeoZarr dataset","description":"Loads a published observed collection over a time range and a published climatological normal, computes the anomaly (observed − normal, aligned by day-of-year or month), and publishes the result as a new GeoZarr dataset with the observed `t` axis preserved.\n\nUse it to derive anomalies from datasets already on the instance — e.g. the observed `era5land_temperature_daily` against the normal `era5land_temperature_daily_normal_1991_2020`. The normal must already exist (compute it with the `climate_normal` workflow, or use an EDH-direct normal data source).\n\nKeep an anomaly dataset current by re-running this workflow over the desired range — recomputing observed − normal is a cheap lazy subtract, so no incremental sync cascade is needed.\n\nIf the `output_dataset_id` has no registered data source, managed `save_result` auto-registers one (inheriting units/period_type from the observed dataset). Pre-registering a static data source (a dataset template in `plugins/rasters/` with `sync: {kind: static}` and a `display` block) is recommended for anomalies so you control the diverging colormap centred on zero. No ingestion plugin is required — the data is produced by this workflow.\n\nZarr output cannot be produced synchronously, so run this as a batch job (`POST /jobs`, then `POST /jobs/{id}/results`):\n\n{\n  \"anomaly\": {\n    \"process_id\": \"climate_anomaly\",\n    \"arguments\": {\n      \"observed_dataset_id\": \"era5land_temperature_daily\",\n      \"normal_dataset_id\": \"era5land_temperature_daily_normal_1991_2020\",\n      \"output_dataset_id\": \"era5land_temperature_daily_anomaly_1991_2020\",\n      \"variable\": \"t2m\",\n      \"temporal_extent\": [\"2024-01-01\", \"2024-12-31\"],\n      \"method\": \"absolute\"\n    },\n    \"result\": true\n  }\n}","parameters":[{"name":"observed_dataset_id","description":"ID of the published observed collection (datetime time axis), e.g. era5land_temperature_daily.","schema":{"type":"string"}},{"name":"normal_dataset_id","description":"ID of the published climatological normal (with a dayofyear or month ordinal axis).","schema":{"type":"string"}},{"name":"output_dataset_id","description":"ID of the anomaly dataset to publish. Auto-registered if no static data source exists, taking its units from the computed result (so a relative anomaly registers as '%'); pre-register one to control the diverging display, making sure its units match the method (no ingestion plugin needed).","schema":{"type":"string"}},{"name":"variable","description":"Variable/band name carried through to the published anomaly dataset.","schema":{"type":"string"}},{"name":"temporal_extent","description":"Observed time range as [start, end] ISO-8601 date strings, e.g. [\"2024-01-01\", \"2024-12-31\"].","schema":{"type":"array","subtype":"temporal-interval"}},{"name":"method","description":"'absolute' (observed − normal, default) or 'relative' (percent of normal). A relative anomaly is published with units '%' rather than the observed variable's unit, so a pre-registered output data source must declare '%' to match; publishing into one that declares the observed unit is refused rather than relabelled.","schema":{"type":"string","enum":["absolute","relative"]},"optional":true,"default":"absolute"}],"returns":null,"process_graph":{"observed":{"process_id":"load_collection","arguments":{"id":{"from_parameter":"observed_dataset_id"},"temporal_extent":{"from_parameter":"temporal_extent"}}},"normal":{"process_id":"load_collection","arguments":{"id":{"from_parameter":"normal_dataset_id"}}},"anomaly":{"process_id":"compute_anomaly","arguments":{"observed":{"from_node":"observed"},"normal":{"from_node":"normal"},"method":{"from_parameter":"method"}}},"save":{"process_id":"save_result","arguments":{"data":{"from_node":"anomaly"},"format":"Zarr","options":{"dataset_id":{"from_parameter":"output_dataset_id"},"source_dataset_id":{"from_parameter":"observed_dataset_id"},"variable":{"from_parameter":"variable"},"publish":true}},"result":true}},"links":[]}