Skip to content

Article: dating detected floodplain change with Sentinel-2 and Esri Wayback (#108) - #109

Merged
NewGraphEnvironment merged 36 commits into
mainfrom
108-article-watching-forest-change-with-esri
Oct 17, 2026
Merged

NewGraphEnvironment merged 36 commits into
mainfrom
108-article-watching-forest-change-with-esri

Conversation

@NewGraphEnvironment

@NewGraphEnvironment NewGraphEnvironment commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Summary

New pkgdown article, When Did the Floodplain Change? Dating Detected Change with Sentinel-2 and Esri Wayback (vignettes/articles/floodplain-change-dating.Rmd). It replaces the first version of this PR (wayback-change.Rmd), which covered Wayback mechanics and was built on the superseded bulk_co_ff04 item. The new article follows the use case on the Bulkley watershed group's floodplain, along Maxan and Crow creeks: date the change drift detects in a floodplain, then look at each change with the best imagery available.

  • The data comes from the current STAC item. bulk_all_ff04 on stac-floodplains-bc, read with rstac: the all_ff04 floodplain and the 2017–2023 IO LULC land cover. dft_rast_break_class() and dft_rast_break_category() give each floodplain cell the year of its clean switch. Connected same-year switches of 1 ha or more become the lettered change areas A–J.
  • The first map shows where the box is: the Bulkley watershed group's floodplain, the Bulkley River and the towns on a shaded grey relief basemap (Esri Light Gray Base x World Hillshade), with a BC inset. A second map colours floodplain cells by switch year over the 2023 Sentinel-2 composite.
  • Each change area gets a verdict (change / class error where Wayback brackets it; likely change / unclear where only Sentinel-2 does), shown above its panels with a Google Maps satellite link for an undated look at the ground today. The table groups the areas by verdict, class errors first. The verdicts are keyed to areas.csv and stop the build if the areas change.
  • The article links the stac_floodplains_bc catalogue and the floodplains modelling sites.
  • What the sharp images show (2018–2020). For the five areas Wayback brackets (2016-09-11 before, 2020-09-18 after), only one (C, creekside forest opened up) is a change on the ground. Three are parts of one open meadow relabelled from Crops to Rangeland, and one is the same stand of trees. Sentinel-2 brightening alone would have flagged one of the fields as cleared.
  • After 2020, Sentinel-2 alone. In the last sharp image, four of the five 2021–2023 areas are forest and one is an open wet meadow. In its year, each brightens more than the box as a whole does. One lies partly in a 2023 cutblock.
  • Why the sharp images stop. Over the box, every Wayback release from 2022-05-18 to the latest (2026-09-24) still draws the 2020-09-18 capture.
  • The rest: one table of tools, one table of numbers, and short limits. All code folds under a "Code" toggle. The fetch code shown is read from the data-raw script, so what is shown is what ran.
  • data-raw/floodplain_change_dating.R makes every network call and writes 31 small files (5.9 MB) to vignettes/articles/floodplain-change-dating/, which is outside the tarball. The article reads only those files.

Closes #108

What the data changed

  • The verdicts for A–E came from looking at the Wayback views at full size, not from the land-cover labels. Four of the five dated switches are the map, not the ground. That became the article's main point.
  • Each area's Sentinel-2 brightening is measured against the whole box's. The 2019 composite is pale across the box, and 2023 is brighter, so a raw before/after would date haze.
  • Code folding: pkgdown 2.2.0 ignores code_folding: hide, so a knitr source hook wraps each chunk in <details>. knitr::read_chunk() of a ../../data-raw path breaks the build, so the article reads the script with readLines() and passes the code through code =.

Measurement

  • Data script: 1.4 min on a warm cache. A warm rerun reproduces all 28 files byte for byte (md5). The first cold run took 32.9 min for 25 of 182 Wayback metadata releases, then hit a transient HTTP 502. It was cold only because the box corners had been rounded differently from the old script's, so every cache key missed. With the old full-precision corners, all 182 releases read in 0.5 min.
  • Body prose at the redo: 884 words, Rmd 348 lines (previous article: 1,477 words, 414 lines). The verdicts, links and context map since then bring the Rmd to 445 lines.
  • No R/ changes. devtools::test(): FAIL 0 | PASS 1709 | SKIP 19. pkgdown::check_pkgdown(): no problems. No footnotes or \@ref() in the built HTML.

Checks

  • pkgdown::build_article() renders from the committed files; every dft_ call is in an eval = FALSE chunk
  • The code folds (8 <details> blocks), including the chunk that reads the saved files, so the figure code on the page runs as shown
  • Every date and count in the prose is computed from the CSVs; the per-area verdicts are keyed to areas.csv and stop the build if it changes

Relates to NewGraphEnvironment/sred-2025-2026#16

🤖 Generated with Claude Code

https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN

NewGraphEnvironment and others added 25 commits October 15, 2026 14:48
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
…ge article (#108)

data-raw/wayback_change.R picks each sub-metre capture over the box from the
releases where it covers the most ground, fetches them on one 0.5 m grid,
composites Sentinel-2 for 2018/2020/2022/2023 on one shared stretch, and writes
3.6 MB of 8-bit display rasters and CSVs to vignettes/articles/wayback-change/.
A warm-cache rerun reproduces every file byte for byte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Shows a release is not a capture, picks the capture nearest each year,
fetches the three sub-metre captures on one grid, and fills 2022-2023 with
Sentinel-2 composites, over the new_graphiti stac-ortho-mosaics box with the
published Bulkley co_ff04 floodplain outlined. Every number in the prose is
read from the CSVs the data-raw script writes; the article makes no network
call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
JPEG window chips no longer carry a nodata value (lossy 1 -> 0 read as
nodata specks); captions name the tile zoom behind each panel; composite
dating stated as start of one window to end of the next; drop an authors'
aside; brightness wording matches the 2023 haze caveat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Display chunks no longer echo (their code called hidden helpers and
contradicted the workflow code shown); the floodplain is drawn from its own
edge, which stops at the box frame instead of running along it, with the
clipped polygon kept for the area.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
)

The zoom window moves south to take in both the clearing between the
floodplain arms and the valley floor where the published Bulkley change
layer has harvest starting in 2020. The Sentinel-2 panels now outline the
tree loss in that layer that falls inside a dated harvest, labelled with
its start year, and the post-2020 paragraph reads the 2022-2023 change
against those dates rather than against overall brightness.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
)

Review found the change layer's in_harvest tag means a patch touches a
cutblock, not that it lies inside one: 13.9 of the 55.6 tagged ha are
inside a 2017-2023 cutblock. The Sentinel-2 panels now outline the BC
consolidated cutblocks themselves (2017-2023 start, read with bcdata),
which date the window's clearing (2020) and the bare strips east of the
floodplain (2023). A new section explains how the published change layer
is built with drift and tagged by floodplains, maps its tree-loss
patches against the cutblocks, and tabulates the tags beside the area
actually inside a cutblock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
- in_harvest is touching a cutblock started 2017-2023, so say so where
  the tag is defined, used and limited.
- Drop "all of it on the floodplain": 2.5 of 71.3 ha of the change
  patches lie outside the drawn floodplain polygon, along its edge.
- Cutblock year labels get a halo and are drawn after the window square;
  one near the right frame ends at its point instead of being pushed off
  its block.
- data-raw: keep only blocks and patches with area in the box before the
  per-row results are joined back by position, and assert the lengths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
…#108)

The window caption and prose called the 2014/2016 valley floor open ground
with scattered trees. Its south-west end and the riverside were stands of
forest, darker than the forest reference, and the 2020 cutblock is that
south-west stand being cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
data-raw/floodplain_change_dating.R reads the current Bulkley floodplain
item (bulk_all_ff04) from STAC, dates each floodplain cell's clean switch
with dft_rast_break_class(), groups same-year switches into change areas of
1 ha or more, and writes Sentinel-2 composites for 2017-2023 and Wayback
before/after views of each area. A warm rerun reproduces all 28 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
vignettes/articles/floodplain-change-dating.Rmd replaces wayback-change.Rmd.
It maps the floodplain's clean land-cover switches by year, then looks at
each change area: Wayback before and after for 2018-2020, where only one of
five is a change on the ground, and Sentinel-2 alone for 2021-2023, since
Esri has released no sharp capture here after 2020-09-18. All code folds;
the fetch code is read from the data-raw script. The old article, its data
and data-raw/wayback_change.R are removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
G was an open wet meadow in 2020, not forest; A, D and E are one meadow;
the change lies along Maxan and Crow creeks, not the Bulkley River; the
lead map says what uncoloured floodplain cells are; the composites are not
cloud-free (2019 carries haze); I's cutblock share is asserted; the
script's one-grid comment is corrected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
The Sentinel-2 check now asks whether an area's largest rise against the
box falls in its mapped year, since a positive rise holds in most years and
dated nothing; the page shows the Wayback pick and cover filter, with the
retrying fetch moved ahead of the shown block so the shown code is what
ran; and "sharper", "new trails", "few clear scenes" and A's "same"
verdict are corrected. The script header now matches change.tif.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Round 3 enumerated every claim on the page. Fixed what it found wrong or
unbacked: E's southern lobe also crosses the 2016 mown strip; the code that
reads the saved files is now shown, so the figure code runs from what the
page shows; guards for the one-summer and two-summer claims, the S2-only
areas' last capture, and the two sections covering every area; and the
tools table, the composite's cloud filter, Wayback's archive, "bare
ground" and the Sentinel-2 limit are worded to what was measured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Scope the Sentinel-2 date claim to F, H, I and J; say the 2020 Wayback
image falls late in the change year for D and E; name what the meadow's
brightening shows rather than a cause; tighten the G guard; Wayback's
archive starts in 2014 and the capture count is at zooms 16-18.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
@NewGraphEnvironment NewGraphEnvironment changed the title Article: watching forest change with Esri Wayback and Sentinel-2 (#108) Article: dating detected floodplain change with Sentinel-2 and Esri Wayback (#108) Oct 16, 2026
NewGraphEnvironment and others added 4 commits October 16, 2026 11:38
A clean first figure (the 2020 Wayback image over the box, floodplain edge,
change-area outlines), a sentence and a table column saying which change
areas are change on the ground and which are class errors, and a Google Maps
satellite link per area. Draft; review deferred until the drafts settle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
)

The first figure is now the study area in the Bulkley watershed group over
Esri's World Topographic Map, with the group's floodplain and a BC inset.
Each change area's row of image panels is headed by a line carrying its
Google Maps link, so the two can be compared side by side; the table's
link column is dropped. Draft; review deferred until the drafts settle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
The verdict sentence claimed most mapped change was not change on the
ground; by count and by area that holds only for the five areas the sharp
images reach, so it now says that. The table caption names the Unclear
verdict, guards tie each verdict group to the images that reach it, and
the data script's header names every live source a rerun can pick up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
The areas dated after 2020 have a sharp image before their change, so they
are not "seen only in Sentinel-2"; Google does not date its imagery, so the
link no longer calls it current; and the box figure's caption says the ground
outside the floodplain is dimmed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
NewGraphEnvironment and others added 7 commits October 16, 2026 13:47
Round 3 enumerated all 41 claims the drafts add; five failed. The code
comment no longer calls Google's image a look at the ground now, the context
map's caption says the ground outside the watershed group is dimmed, the box
caption says an area is cells that switched in the same year, and the data
script's header names the BC outline that bcmaps caches. D stays a class
error, the author's call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
The context map now introduces the study area, so the 2020 Wayback image of
the whole box, its data-script block and its saved file go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
The context map's basemap is now Esri's World Light Gray Base shaded with
its World Hillshade through gq_basemap_blend(), at zoom 10, with the
Bulkley River (FWA) and the towns (bcmaps) drawn and labelled by us, so no
baked-in tile text is upscaled. Each service's own attribution goes in the
caption. Draft; review deferred until the drafts settle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
bcmaps::bc_cities() put Houston 7 km south-east of the town; the towns now
come from BC Geographical Names, incorporated places only. The river's
segments are ordered before the union, so a warm rerun no longer rewrites
context.csv (checked: two runs, identical bytes), and the header names the
Esri attribution as a live read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
Round 3 enumerated the 20 claims the relief-basemap commits add; two failed.
The script's comments call the towns those in the map frame (Granisle and
Hazelton lie outside the watershed group), and the verdict paragraph now
defines a change area and its letters, which the removed box figure had
done before it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRhUJsuKABLfpBGktPoiBN
@NewGraphEnvironment
NewGraphEnvironment merged commit cd79d1c into main Oct 17, 2026
1 check passed
@NewGraphEnvironment
NewGraphEnvironment deleted the 108-article-watching-forest-change-with-esri branch October 17, 2026 00:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Article: dating detected floodplain change with Sentinel-2 and Esri Wayback

1 participant