Repository navigation
Temporal QA across five watershed groups from the published annual series: does the BULK split generalise? #62
Description
Context
dft_rast_break_class() (#9, v0.14.0) was measured on one watershed group. On BULK, of the 4,620 ha the 2017 -> 2023 comparison reports as change, 19.7% is a switch sustained two years each side, 36.4% is a clean switch with 2017 or 2023 the odd year out (922 ha broke in 2018 — 2017 alone differs; 757 ha in 2023), and 44.0% flickers; 3,187 ha flickers while reading stable on the endpoints. Patches carrying the #44 artifact signature had an area-weighted clean-break share of 0.50 against 0.58 for the rest. Evidence in data-raw/logs/benchmark_break_class/.
floodplains re-ran bulk, necr, lnth, kotl with all seven IO LULC years (NewGraphEnvironment/floodplains#79) and stac_floodplains_bc published them (NewGraphEnvironment/stac_floodplains_bc#59), both closed 2026-09-05. This issue runs the temporal leg across all four from the published assets and answers the questions one group cannot.
Four groups, not five (corrected 2026-09-05; the body first said five). PINE was dropped upstream on purpose: data/pine/ has no provenance.json and its floodplain rasters predate flooded 0.5.0, the bankfull-units vintage floodplains calls dead. NewGraphEnvironment/floodplains#76 tracks PINE and MCGR; their annual series arrive with that rebuild. The published items that carry seven classified_* years are exactly bulk_co_ff04, necr_ch_ff04, lnth_ch_ff04, kotl_bt_ff04.
Questions
- Does the split generalise? Sustained / endpoint-only / flicker share of the endpoint-changed area per group, against BULK's 19.7 / 36.4 / 44.0. If the sustained share sits near 20% everywhere, the published
transition_2017_2023layers overstate real change by a factor the reports need to carry; if it varies widely, the variation is the result. - Is 2017 the odd year product-wide? Area with
n_flips == 1 & n_before == 1(2018 break) per group, and the same forn_after == 1(2023). If 2017 is the outlier in every group, the first year of IO LULC v02 is the noisy one and the honest baseline is 2018 — which changes what "2017 to 2023 change" means in every report. Clouds (code 10) count as a flip, so the per-year class frequencies are reported beside this: a cloudy 2017 would produce the same signature for a different reason. - Landscape or classifier? Flicker share against floodplain shape. Confinement is not a field in the data, so two proxies derived from each item's published floodplain polygons: how much the floodplain widens as the flood factor rises (
ff06 / ff02area ratio — a confined valley barely does) and the ff04 effective width2A/P; within each group, the Detect geometric edge/misregistration artifacts in transitions (sliver width, boundary-hugging, reciprocal pairs) #44 sliver-vs-wider patch split. A share that barely moves across groups and shape classes is the classifier's. (The per-stream_by_blue_line_keylayer was considered and rejected: its polygons overlap 1.7-2.2x because tributary floodplains nest inside the mainstem's, andkotl_bt_ff04has no such layer.) With four groups there is no test; the answer is the four rows. - Are the geometric and temporal legs independent everywhere?
break_fracby artifact signature per group, as the BULK patch-group table (summary_patch_groups.csv). - What to build next. Two decisions this run informs, to be filed as their own issues with the numbers behind them: (a) the corrected series the Categorical breakpoint detection: sustained switch vs flicker across the annual class series (the temporal leg of change QA) #9 body named — a per-pixel mode filter that keeps a sustained break and overwrites the flicker years — is worth building only if flicker is large everywhere; (b) whether the catalogue's items should carry the temporal evidence (
break_year,n_flipsCOGs, or a corrected transition) beside the two-epoch transition.
Filed 2026-09-05 with the measurements: (a) Corrected annual series: per-pixel run-length filter that keeps a sustained switch and overwrites flicker years #64, (b) Carry temporal evidence (break_n_flips, break_year) beside transition_2017_2023 for full-series items stac_floodplains_bc#67. Results:inst/notes/temporal-qa-groups.md.
How
- Download the seven
classified_<year>COGs per item from the published hrefs once (~1 MB each; the pipeline reads each stack many times, so a local copy beats/vsicurl/on every pass), verify each against the asset'sfile:checksum, classify withsource = "io-lulc", rundft_rast_break_class(), thendft_transition_vectors(changes_only = TRUE)+dft_transition_artifact()+ per-patch zonal — the BULK script (data-raw/benchmark_break_class_bulk.R) minus the fetch. The COGs are already clipped to the floodplain, so there is no AOI mask either, and file-backed inputs remove the 8.5-20 GB in-memory input floor the BULK run carried.dft_stac_fetch()assumes one asset name across items, so this is adata-raw/script, not a new source; if it turns out worth keeping, astac-floodplains-bcsource is a separate issue. - BULK is re-measured on the published grid (14651 x 11552) rather than the 16000 x 12000 grid the Categorical breakpoint detection: sustained switch vs flicker across the annual class series (the temporal leg of change QA) #9 run tiled from Planetary Computer; the script emits the reconciliation row against the Categorical breakpoint detection: sustained switch vs flicker across the annual class series (the temporal leg of change QA) #9 CSV.
- One directory of CSVs per group in
data-raw/logs/break_class_groups/plussummary_groups.csv/.mdthe note includes verbatim; RSS sampled per group. - Results as a short note (
inst/notes/temporal-qa-groups.md), every number derived from the committed CSVs by the committed script (the round-8 lesson on Categorical breakpoint detection: sustained switch vs flicker across the annual class series (the temporal leg of change QA) #9).
Acceptance
- Four groups measured with the same script; the four questions above each answered with a number per group.
- The two follow-up decisions filed as issues (drift and/or stac_floodplains_bc) with the measurements in their bodies, or explicitly closed as "not worth it" with the number that says so.
- Nothing in
R/changes here unless the run finds a defect; this is analysis.
Activity
Merge pull request #65 from NewGraphEnvironment/62-temporal-qa-across…
Patch-size sieve, two worked sliver examples, and split the floodplai…