Change detection tool
The ChangeDetectionTool, which an agent sees as FindChanges, compares two time windows over indexed regions. The answer reports, per class, what appeared, disappeared, grew, and shrank.
Set time_field to the capture-time field on each region. The vectorize processor writes captured_at when you set that ingest parameter. Dates are ISO-8601 (2024-07-12 or a comma-separated pair 2024-07-01,2024-07-07). Call WhenWasThisImaged to choose windows that contain documents.
Region documents
FindChanges searches top-level fields on each document: time_field (a date range), label_field (a terms aggregation), and measure_field (a sum). Those aggregations run on document-root fields.
Index one document per region, with captured_at, label, and area at the document root — the same names you pass as time_field, label_field, and measure_field.
PUT /land_cover
{
"mappings": {
"properties": {
"label": { "type": "keyword" },
"area": { "type": "double" },
"area_units": { "type": "keyword" },
"captured_at": {
"type": "date",
"format": "strict_date_optional_time||yyyy-MM-dd",
"doc_values": true
},
"mask": { "type": "geo_shape" },
"source_uri": { "type": "keyword" }
}
}
}
vectorize writes nested segments[] on the scene document. After foreach reproject adds mask on each segment, explode that array into land_cover: one bulk action per region, copying label, area, area_units, captured_at, mask, and source_uri to the top level. Use one area_units value per land_cover index. When an index holds more than one, set query to that value so the measure_field sum is in one unit.
POST /land_cover/_bulk
{"index":{}}
{"label":"Almonds","area":1843200.0,"area_units":"EPSG:5070 squared","captured_at":"2024-07-12","mask":{"type":"polygon","coordinates":[[[-119.8,36.7],[-119.7,36.7],[-119.7,36.8],[-119.8,36.8],[-119.8,36.7]]]},"source_uri":"s3://bucket/cdl-2024-07-12.tif"}
{"index":{}}
{"label":"Almonds","area":2100000.0,"area_units":"EPSG:5070 squared","captured_at":"2024-07-19","mask":{"type":"polygon","coordinates":[[[-119.8,36.7],[-119.65,36.7],[-119.65,36.82],[-119.8,36.82],[-119.8,36.7]]]},"source_uri":"s3://bucket/cdl-2024-07-19.tif"}
Windows
baseline and compare are dates. A single date means that whole day; a comma-separated pair is an inclusive range. The answer repeats the windows it used.
When the baseline window has no documents, the answer states that the baseline is empty and names WhenWasThisImaged.
Totals and regions
By default the tool compares class totals — how many regions of each label, and how much of measure_field they carry — in one search.
Set detail to regions to name the individual polygons that appeared and left. The answer says which pass ran.
Parameters
| Parameter | Required | Description |
|---|---|---|
index | Yes | The index holding the regions. |
time_field | Yes | The date field holding when each document was captured. |
baseline | Yes | The earlier window: a date, or a comma-separated pair. |
compare | Yes | The later window: a date, or a comma-separated pair. |
label_field | No | The field holding each region's class or label. |
measure_field | No | A numeric field summed per class (typically area). |
query | No | A query_string phrase that restricts which regions count (for example label:Almonds AND area_units:"EPSG:5070 squared"). |
area | No | An area of interest, as WKT. |
field | No | The geometry field area is tested against. |
detail | No | Set to regions to name individual polygons. |
Register a flow agent that runs the ChangeDetectionTool
POST /_plugins/_agent/agents/_register
{
"name": "Change_Agent",
"type": "flow",
"description": "compares two dates over indexed regions",
"tools": [
{
"type": "ChangeDetectionTool",
"name": "DemoFindChanges",
"parameters": {
"index": "land_cover",
"time_field": "captured_at",
"label_field": "label",
"measure_field": "area"
}
}
]
}
POST /_plugins/_agent/agents/<agent_id>/_execute
{
"parameters": {
"baseline": "2024-07-12",
"compare": "2024-07-19",
"query": "label:Almonds AND area_units:\"EPSG:5070 squared\""
}
}
Related tools
- Coverage and gaps before you compare:
WhenWasThisImaged - What is in a single raster:
FindImageRegions - Nested
segments[]from ingest:vectorize