From 7ed345063b05abef7637d712983c65b19e117ede Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:26:02 -0700 Subject: [PATCH 01/13] Initialize PWF baseline for #142 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- planning/active/findings.md | 41 +++++++++++++++++++++++++++++++ planning/active/progress.md | 8 ++++++ planning/active/task_plan.md | 47 ++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 planning/active/findings.md create mode 100644 planning/active/progress.md create mode 100644 planning/active/task_plan.md diff --git a/planning/active/findings.md b/planning/active/findings.md new file mode 100644 index 0000000..0cf05e4 --- /dev/null +++ b/planning/active/findings.md @@ -0,0 +1,41 @@ +# Findings — README: add daily point temperatures and any-series consumers; drop internal function (#142) + +## Issue context + +## Problem + +The architecture and data sections are accurate (v0.6.7), but recent consumer capabilities are missing, and one function listed as part of the API is internal. + +## Findings + +**Shipped but not in the README (underselling)** +- Daily point temperatures, `cd_extract_daily()` (v0.6.0), for stream-temperature and degree-day work +- Consumer functions accept any annual series, such as streamflow and stream temperature (v0.5.0) +- Per-file checksums and run provenance (v0.6.3 to v0.6.5) + +**Stale** +- README.md:105 lists `cd_stac_item()` as a producer function; it is internal and not exported +- The quick start uses a toy `1951:1955` baseline (README.md:31); the vignettes use `1951:1980` +- The VPD unit fix (Pa to hPa, v0.6.7) is not mentioned + +## Tasks + +- [ ] Add the shipped capabilities above +- [ ] Remove `cd_stac_item()` from the function list +- [ ] Use a realistic baseline in the quick start +- [ ] Group the `_pkgdown.yml` reference index by purpose. It has no `reference:` sections today, so the docs site shows a flat alphabetical list. + +## Context + +Audited 2026-10-14 against `origin/main` @ `5611c59`, from README, DESCRIPTION, NEWS, NAMESPACE and vignettes. Verify each item against the code before acting. Versions cited are where a capability landed. + +The New Graph website will describe this package from its README (NewGraphEnvironment/newgraphenvironment.github.io#53), so the README is the source of truth for the public one-liner. Plain language in the opening paragraph: what it does today, and what restoration planning, implementation or monitoring decision it informs. + +## Plan-gate notes (2026-10-17) + +- README on main: 962 words (`wc -w`), sections Overview, Installation, Quick start, Caching, Data, Architecture, Roadmap, Links, Acknowledgements. +- `cd_stac_item()` is not in NAMESPACE (confirmed); it appears only in the Architecture table, which the rewrite removes. +- `_pkgdown.yml` has `url` and `template` only, no `reference:`. +- DESCRIPTION `Description` says producer functions "download ERA5-Land monthly means": true of the legacy `cd_fetch()` (CDS), not of the EDH pipeline CI runs. +- `update-citation-cff.yaml` calls `cffr::cff_create()` with default roles, so New Graph Environment Ltd. (`cph`, `fnd`) is not a citation author. +- `example_aoi_kotl.gpkg` is the KOTL watershed group, ~9,339 km². diff --git a/planning/active/progress.md b/planning/active/progress.md new file mode 100644 index 0000000..a56700a --- /dev/null +++ b/planning/active/progress.md @@ -0,0 +1,8 @@ +# Progress — README: add daily point temperatures and any-series consumers; drop internal function (#142) + +## Session 2026-10-17 + +- Plan-mode exploration — phases approved by user (scope widened to a full `readme.md`-convention rewrite at the user's direction) +- Created branch `142-readme-add-daily-point-temperatures-and` off main +- Scaffolded PWF baseline from issue #142 with approved phases +- Next: start Phase 1 diff --git a/planning/active/task_plan.md b/planning/active/task_plan.md new file mode 100644 index 0000000..10936ec --- /dev/null +++ b/planning/active/task_plan.md @@ -0,0 +1,47 @@ +# Task: README: add daily point temperatures and any-series consumers; drop internal function (#142) + +The architecture and data sections are accurate (v0.6.7), but recent consumer capabilities are missing, and one function listed as part of the API is internal. + +Scope set at the plan gate (2026-10-17): rewrite the README to soul's `readme.md` convention — simple, plain language, a figure from committed code, not too much detail. Function tables, roadmap, caching section and the data inventory come out; the VPD unit fix stays in NEWS. + +## Phase 1: Figure from committed code + +- [ ] `data-raw/readme_figure.R` (local only, `pkgload::load_all()`): live catalog, `example_aoi_kotl.gpkg` (Kootenay Lake watershed group, ~9,300 km²), annual tmean, `cd_baseline(1951:1980)` -> `cd_anomaly()` -> `cd_trend(trend_start = 1951)` -> `cd_plot_timeseries()`; writes `man/figures/readme-kotl-tmean.png` (opaque white background) and prints the `cd_summary()` table for the README example +- [ ] Check the PNG at its published width (~700 px column): type legible, no transparency + +## Phase 2: README rewrite, in the convention's order + +- [ ] Title line with hex sticker (`alt` text added), lifecycle-experimental badge, one-line tagline +- [ ] Opening: what cd is (how far BC's climate has moved from a chosen baseline, for any area), the data (ERA5-Land reanalysis since 1950, served as a public self-updating catalog, no credentials), what it informs (which watersheds are warming or losing snow, for restoration planning and monitoring); one clause each for daily point temperatures (stream-temperature and degree-day work), any annual series (streamflow, stream temperature), and each value naming the file build it came from +- [ ] Figure + alt text + one-line caption +- [ ] Installation, then the "under active development / see NEWS / pin `@vX.Y.Z`" line +- [ ] Example: the Phase 1 code with a `1951:1980` baseline, shown with its real pasted `cd_summary()` output; one sentence that files are cached after first read +- [ ] Learn more: one line per vignette (peace-fwcp, kootenay-lake, northern-bc), then the function reference +- [ ] Ecosystem: cd, wet (and gq only if a vignette uses it), roles worded as in link's README +- [ ] Data and methods it builds on: ERA5-Land (Copernicus/ECMWF) via DestinE Earth Data Hub with the Copernicus attribution sentence, Mann-Kendall / Theil-Sen, and the `bcgov/bc_climate_anomaly` inspiration (replaces Acknowledgements) +- [ ] Citation (points to `CITATION.cff` / `citation("cd")`) and License +- [ ] Record word count before/after in findings.md + +## Phase 3: Texts that travel with the README + +- [ ] DESCRIPTION `Title` in step with the tagline; `Description` in step with the opening (drops the stale "download ERA5-Land monthly means"), ends "Under active development."; `devtools::document()` +- [ ] `update-citation-cff.yaml`: `cff_create(authors_roles = c("aut", "cre", "cph"))` so New Graph Environment Ltd. is a citation author +- [ ] GitHub About via `gh repo edit NewGraphEnvironment/cd --description "…"`, same words as the tagline + +## Phase 4: Grouped reference index + +- [ ] `_pkgdown.yml` `reference:` sections: Read the data (`cd_catalog`, `cd_catalog_default`, `cd_crop`, `cd_extract`, `cd_extract_daily`, `cd_variables`, `cd_periods`, `cd_seasons`); Departures and trends (`cd_baseline`, `cd_anomaly`, `cd_compare`, `cd_trend`, `cd_summary`); Plots (`cd_plot_*`); Cache (`cd_cache_*`); Publishing the data, for maintainers (`cd_fetch`, `cd_derive`, `cd_aggregate`, `cd_cog_write`, `cd_stac_catalog`, `cd_s3_push`) +- [ ] `pkgdown::check_pkgdown()` clean; `pkgdown::build_home()` locally and look at the rendered page and figure + +## Phase 5: Close out + +- [ ] Edit #142's body: scope is the convention rewrite; VPD fix left to NEWS +- [ ] Mechanical checks: every function the README names is exported; every link resolves +- [ ] `/code-check branch` with every README/DESCRIPTION claim enumerated against code + +## Validation + +- [ ] Tests pass +- [ ] `/code-check` clean (each commit, or once over the branch with `/code-check branch`) +- [ ] PWF checkboxes match landed work +- [ ] `/planning-archive` on completion From 981eaf1606ab8daf7a9c41614b4e1317c8e7804d Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:26:57 -0700 Subject: [PATCH 02/13] README figure from committed code: Kootenay Lake temperature departure (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- data-raw/readme_figure.R | 50 ++++++++++++++++++++++++++++++ man/figures/readme-kotl-tmean.png | Bin 0 -> 39827 bytes planning/active/progress.md | 1 + planning/active/task_plan.md | 4 +-- 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 data-raw/readme_figure.R create mode 100644 man/figures/readme-kotl-tmean.png diff --git a/data-raw/readme_figure.R b/data-raw/readme_figure.R new file mode 100644 index 0000000..c27adac --- /dev/null +++ b/data-raw/readme_figure.R @@ -0,0 +1,50 @@ +# Build the README figure and the output its example shows (#142) +# +# Generates: +# man/figures/readme-kotl-tmean.png (annual mean air temperature departure +# for the Kootenay Lake watershed group, +# with its trend) +# and prints the cd_summary() table pasted under the README example. +# +# The code between the two `README example` markers is the README's example, +# so the figure and the pasted output come from the same run. Run from the +# package root when the catalog gains a year. +# +# Prerequisites: network access to the live catalog. + +Sys.setenv( + GDAL_HTTP_MAX_RETRY = "3", + GDAL_HTTP_RETRY_DELAY = "2" +) + +# The checkout's cd, not an installed one (#135). +pkgload::load_all(export_all = FALSE, quiet = TRUE) + +# --- README example --------------------------------------------------------- +catalog <- cd_catalog() +aoi <- sf::st_read( + system.file("extdata", "example_aoi_kotl.gpkg", package = "cd"), + quiet = TRUE +) + +ts <- cd_extract(catalog, aoi, variables = "tmean", periods = "annual") +bl <- cd_baseline(ts, baseline_years = 1951:1980) +ano <- cd_anomaly(ts, bl) +trn <- cd_trend(ano, trend_start = 1951) + +cd_summary(trn) +# --- end README example ----------------------------------------------------- + +print(cd_summary(trn)) + +p <- cd_plot_timeseries(ano, trend = trn) + + ggplot2::theme_minimal(base_size = 15) + + ggplot2::theme(legend.position = "none") + +out <- "man/figures/readme-kotl-tmean.png" +# png() gives an opaque white background, which survives a dark web page. +grDevices::png(out, width = 7, height = 3.5, units = "in", res = 150, + bg = "white") +print(p) +grDevices::dev.off() +message("Wrote ", out) diff --git a/man/figures/readme-kotl-tmean.png b/man/figures/readme-kotl-tmean.png new file mode 100644 index 0000000000000000000000000000000000000000..8e8fde65b228c23722420afdd9da4ebc12ae06d2 GIT binary patch literal 39827 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 `cd_anomaly()` -> `cd_trend(trend_start = 1951)` -> `cd_plot_timeseries()`; writes `man/figures/readme-kotl-tmean.png` (opaque white background) and prints the `cd_summary()` table for the README example -- [ ] Check the PNG at its published width (~700 px column): type legible, no transparency +- [x] `data-raw/readme_figure.R` (local only, `pkgload::load_all()`): live catalog, `example_aoi_kotl.gpkg` (Kootenay Lake watershed group, ~9,300 km²), annual tmean, `cd_baseline(1951:1980)` -> `cd_anomaly()` -> `cd_trend(trend_start = 1951)` -> `cd_plot_timeseries()`; writes `man/figures/readme-kotl-tmean.png` (opaque white background) and prints the `cd_summary()` table for the README example +- [x] Check the PNG at its published width (~700 px column): type legible, no transparency ## Phase 2: README rewrite, in the convention's order From 59fcc8a4390b0f3f8cacd7d28f7b5c42a1a613a4 Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:28:38 -0700 Subject: [PATCH 03/13] README: rewrite to the readme convention in plain language (#142) Opening says what cd measures and what it informs, adds daily point temperatures and any-series baselines, a figure from committed code, an example with a 1951-1980 baseline and its real output. Drops the function table (and internal cd_stac_item()), roadmap and inventories. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- README.md | 129 +++++++++++------------------------ planning/active/findings.md | 9 +++ planning/active/progress.md | 1 + planning/active/task_plan.md | 20 +++--- 4 files changed, 59 insertions(+), 100 deletions(-) diff --git a/README.md b/README.md index f1aeffb..219be74 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,16 @@ -# cd +# cd cd hex sticker -Climate Departure Analysis from ERA5-Land Reanalysis + +[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) + -## Overview +> How far British Columbia's climate has moved from any baseline, for any area, from ERA5-Land reanalysis -cd fetches [ERA5-Land](https://www.ecmwf.int/en/era5-land) hourly reanalysis (1950–present, ~9 km native grid) from the [DestinE Earth Data Hub](https://earthdatahub.destine.eu/), subsets to British Columbia, aggregates to monthly, seasonal, and annual periods, derives additional climate variables (vapour pressure deficit and relative humidity from temperature + dewpoint via the Tetens equation; soil moisture as a 4-depth mean) and snow-pack variables (snow water equivalent, snowfall, snowmelt, snow cover, plus annual derived scalars: peak SWE, snowfall fraction, snowmelt 50% day-of-year, peak weekly melt rate), and writes Cloud-Optimized GeoTIFFs alongside a static SpatioTemporal Asset Catalog (STAC) in a public S3 bucket. A monthly GitHub Action keeps the catalog current. On the consumer side, R functions (`cd_catalog`, `cd_extract`, `cd_baseline`, `cd_anomaly`, `cd_trend`, `cd_compare`, `cd_summary`, `cd_plot_timeseries`, `cd_plot_comparison`) read the COGs directly via GDAL's `/vsicurl/` — no credentials, no tile server — crop to a user-supplied area of interest, compute baselines and anomalies for arbitrary reference periods, and run Mann-Kendall and Theil-Sen trend statistics. All baseline and comparison logic stays on the consumer side, so reference periods are not baked into the served data. +cd measures how much the climate of a watershed or any other area in British Columbia has changed: air temperature, precipitation, humidity, soil moisture and snow, by season and year since 1950, compared with whatever reference period you choose, with the trend and how much it has moved. It reads ERA5-Land reanalysis from a public catalog that needs no account, so restoration can be planned and monitored against the climate a site has now rather than the one it had. It also gives daily air temperature at any point in the province, for stream-temperature models and degree-day work, and its baseline and trend steps take any annual series, such as streamflow or stream temperature. + +Bar chart of annual mean air temperature in the Kootenay Lake watershed group from 1950 to 2025, as the difference from the 1951 to 1980 average, with a dashed trend line rising about 1.9 degrees + +*Annual mean air temperature in the Kootenay Lake watershed group, compared with its 1951–1980 average. Red years were warmer, blue years cooler; the dashed line is the trend since 1951.* ## Installation @@ -12,115 +18,58 @@ cd fetches [ERA5-Land](https://www.ecmwf.int/en/era5-land) hourly reanalysis (19 pak::pak("NewGraphEnvironment/cd") ``` -## Quick start +cd is under active development and its functions change between releases (see [NEWS](https://newgraphenvironment.github.io/cd/news/index.html)). Pin a release for reproducible work: `pak::pak("NewGraphEnvironment/cd@vX.Y.Z")`. + +## Example + +Extract a series for an area, compare it with a baseline, and test the trend. This is the run behind the figure above: ```r library(cd) -# Load the live STAC catalog and an example area of interest catalog <- cd_catalog() aoi <- sf::st_read( system.file("extdata", "example_aoi_kotl.gpkg", package = "cd"), quiet = TRUE ) -# Extract zonal mean time series -ts <- cd_extract(catalog, aoi) - -# Compute baseline and anomalies -bl <- cd_baseline(ts, baseline_years = 1951:1955) +ts <- cd_extract(catalog, aoi, variables = "tmean", periods = "annual") +bl <- cd_baseline(ts, baseline_years = 1951:1980) ano <- cd_anomaly(ts, bl) - -# Trend analysis trn <- cd_trend(ano, trend_start = 1951) -# Reporting table cd_summary(trn) - -# Compare time windows directly -cd_compare(ts, window_a = 1956:1960, window_b = 1951:1955) -``` - -## Caching - -`cd_extract()` and `cd_crop()` cache each COG on first read, so repeated -extractions, report renders, and vignette rebuilds pull each file from S3 -**once** and read locally thereafter — turning recurring S3 egress into a -one-time cost. Caching is on by default (`cache = TRUE`). - -```r -# First call downloads; later calls read the local cache. -ts <- cd_extract(catalog, aoi) # cache = TRUE by default - -cd_cache_info() # where the cache lives + size -cd_cache_clear() # wipe it -cd_extract(catalog, aoi, cache = FALSE) # bypass the cache for one call +#> # A tibble: 1 × 7 +#> Parameter Period Slope Years `Total Change` Unit `p-value` +#> +#> 1 Mean temperature Annual 0.025 75 1.9 °C 0 ``` -Freshness is checked with a cheap HTTP HEAD (S3 ETag), so the monthly -catalog republish is picked up automatically; `cd_cache_fetch(href, -refresh = TRUE)` forces a re-download. For a fully-offline session set -`options(cd.cache_revalidate = FALSE)` to serve cached copies without any -network call. +Each file is downloaded once and read from a local cache after that. Every value extracted records the commit of cd's code that built the file it came from. -**Stopgap without the cache.** If you read COGs through GDAL directly -(e.g. raw `terra::rast("/vsicurl/...")` outside `cd_crop()`), you can cut -repeat egress within a session by enabling GDAL's `/vsicurl/` cache: +## Learn more -```r -Sys.setenv(VSI_CACHE = "TRUE", VSI_CACHE_SIZE = "100000000") # 100 MB -Sys.setenv(GDAL_HTTP_MAX_RETRY = "3", GDAL_HTTP_RETRY_DELAY = "1") -``` - -This only persists within one R session; the `cd_*` cache above persists -across sessions, which is what kills recurring report-dev egress. - -## Data - -The producer pipeline fetches ERA5-Land hourly reanalysis from -[DestinE Earth Data Hub](https://earthdatahub.destine.eu/), derives -additional variables (VPD, RH, soil moisture), aggregates to monthly, -seasonal, and annual periods on a single EPSG:4326 BC grid, and writes -Cloud-Optimized GeoTIFFs alongside a static SpatioTemporal Asset -Catalog (STAC) in a public S3 bucket. - -- Catalog (JSON): -- Region: BC (~48–60° N, 114–140° W), 1950–2025, ~9 km native grid -- Variables (15): - - **Core climate** (7): tmean, tmax, tmin, prcp, vpd, rh, soil_moisture - - **Snow monthly natives** (4): swe, snowfall, snowmelt, snow_cover - - **Snow annual derived** (4): swe_max, snowfall_fraction, snowmelt_doy_50, snowmelt_rate_peak -- Periods: seasonal (DJF/MAM/JJA/SON) and annual for monthly-native vars; annual only for snow_max / snowfall_fraction / snowmelt_doy_50 / snowmelt_rate_peak - -The catalog is consumable directly outside R — for example, in QGIS via -the STAC plugin, in `gdalcubes`, or with any STAC-aware client. The -`cd_catalog()` consumer function reads the catalog URL by default. - -## Architecture - -cd has a strict producer / consumer split, kept separate so reference periods, baselines, and statistical choices are not baked into the published data: - -| Side | Functions | Where it runs | -|---|---|---| -| **Producer** | `cd_fetch()`, `cd_derive()`, `cd_aggregate()`, `cd_cog_write()`, `cd_stac_catalog()`, `cd_stac_item()`, `cd_s3_push()`, plus `scripts/backfill_edh_*.py` and `scripts/pipeline_*_edh.R` | A monthly GitHub Action pulls fresh ERA5-Land data from DestinE EDH, derives variables, writes COGs, rebuilds the STAC catalog, and pushes to `s3://stac-era5-land`. Run by maintainers; users do not need to run it. | -| **Consumer** | `cd_catalog()`, `cd_extract()`, `cd_crop()`, `cd_baseline()`, `cd_anomaly()`, `cd_trend()`, `cd_compare()`, `cd_summary()`, `cd_plot_timeseries()`, `cd_plot_comparison()`, `cd_periods()`, `cd_seasons()`, `cd_cache_*()` | Reads COGs directly via `/vsicurl/` — no credentials, no tile server. All baseline selection and statistical work (Mann-Kendall, Theil-Sen, Welch's t, Mann-Whitney U) happen client-side on the cropped time series. | +- [Climate Departure for the FWCP Peace Region](https://newgraphenvironment.github.io/cd/articles/peace-fwcp.html): trends, snowpack and the spatial pattern across a large northern region, by ecoregion and watershed group. +- [Climate Departure for the Kootenay Lake Region](https://newgraphenvironment.github.io/cd/articles/kootenay-lake.html): the same report for the southern Kootenays, where precipitation changes sharply from east to west. +- [How the Weather Has Changed in Three Northern BC Watersheds](https://newgraphenvironment.github.io/cd/articles/northern-bc.html): a short, plain-language story for readers with no climate background. +- [Function reference](https://newgraphenvironment.github.io/cd/reference/) -Anyone can compute climate departure against any baseline period, in any AOI, with whatever statistical test they prefer — without re-publishing the underlying data. +## Ecosystem -## Roadmap +| Package | Role | +|---|---| +| **cd** | Climate departure: baselines, anomalies and trends, and ERA5-Land climate (this package) | +| [wet](https://github.com/NewGraphEnvironment/wet) | Stream flow and water temperature for BC's Freshwater Atlas | +| [gq](https://github.com/NewGraphEnvironment/gq) | Shared map symbology | -- **BEC zone shift analysis** ([#59](https://github.com/NewGraphEnvironment/cd/issues/59)) — methodology lit review for biogeoclimatic ecosystem classification (BEC) shifts under climate change, alongside the existing temperature / precipitation+drying / interpretation-framing methodology stacks. -- **Vignette templates** — `peace-fwcp` and `kootenay-lake` are reference implementations of the regional reporting pattern. Future regional vignettes follow the same structure (trends → recent vs pre-warming → spatial → per-ecoregion → snowpack) so cross-region findings are directly comparable. +## Data and methods it builds on +The climate data are [ERA5-Land](https://www.ecmwf.int/en/era5-land) ([Muñoz-Sabater et al. 2021](https://doi.org/10.5194/essd-13-4349-2021)), produced by ECMWF for the Copernicus Climate Change Service and read from the [DestinE Earth Data Hub](https://earthdatahub.destine.eu/). The published layers contain modified Copernicus Climate Change Service information. Trends are Mann-Kendall tests with Theil-Sen slopes, from the [Kendall](https://cran.r-project.org/package=Kendall) and [zyp](https://cran.r-project.org/package=zyp) packages. cd's variables and its ecoregion and watershed framing follow [`bcgov/bc_climate_anomaly`](https://github.com/bcgov/bc_climate_anomaly), a Shiny app by the Province of British Columbia (Aseem Sharma and contributors). -## Links +## Citation -- [Function reference](https://newgraphenvironment.github.io/cd/reference/) -- Vignettes: - - [Climate Departure for the FWCP Peace Region](https://newgraphenvironment.github.io/cd/articles/peace-fwcp.html) - - [Climate Departure for the Kootenay Lake Region](https://newgraphenvironment.github.io/cd/articles/kootenay-lake.html) - - [How the Weather Has Changed in Three Northern BC Watersheds](https://newgraphenvironment.github.io/cd/articles/northern-bc.html) — a short, plain-language story for readers with no climate background +Cite cd with `citation("cd")`, or from [`CITATION.cff`](CITATION.cff). -## Acknowledgements +## License -This package is inspired by [`bcgov/bc_climate_anomaly`](https://github.com/bcgov/bc_climate_anomaly), a Shiny app developed by the Province of British Columbia (Aseem Sharma and contributors) that visualizes monthly, seasonal, and annual climate anomalies for temperature, precipitation, humidity, vapor pressure, and soil moisture across BC. The variable set and the eco-region / watershed framing in `cd` follow directly from that work. `bc_climate_anomaly` is licensed under the Apache License 2.0. +MIT © New Graph Environment Ltd. See [LICENSE](LICENSE.md). diff --git a/planning/active/findings.md b/planning/active/findings.md index 0cf05e4..4d9aad3 100644 --- a/planning/active/findings.md +++ b/planning/active/findings.md @@ -39,3 +39,12 @@ The New Graph website will describe this package from its README (NewGraphEnviro - DESCRIPTION `Description` says producer functions "download ERA5-Land monthly means": true of the legacy `cd_fetch()` (CDS), not of the EDH pipeline CI runs. - `update-citation-cff.yaml` calls `cffr::cff_create()` with default roles, so New Graph Environment Ltd. (`cph`, `fnd`) is not a citation author. - `example_aoi_kotl.gpkg` is the KOTL watershed group, ~9,339 km². + +## README rewrite (Phase 2) + +- Words: 962 on main -> 593 (`wc -w`, includes the code block and pasted output). No forecast was set; the floor is the convention's fixed sections: opening, figure, install + pin line, example with output, three vignette lines, ecosystem table, data and methods, citation, license. +- Removed: Overview inventory, Caching section (now one sentence), Data inventory (15 variables, extent, years), Architecture function table (with `cd_stac_item()`), Roadmap, Acknowledgements (folded into "Data and methods it builds on"). +- Claims checked against code: catalog periods are annual + four seasons (59 items; no monthly layers), so the opening says "by season and year"; `cd_sha` is "Git commit of the cd code that built the file read" (`R/cd_extract.R:30`, `R/cd_extract_daily.R:90`), hence "commit", not "version"; trends are `Kendall::MannKendall` + `zyp::zyp.sen` (`R/cd_trend.R:74-75`). +- No ERA5-Land / Copernicus attribution existed anywhere in the repo or `catalog.json`; added the C3S "contains modified Copernicus Climate Change Service information" sentence and Muñoz-Sabater et al. 2021 (doi:10.5194/essd-13-4349-2021, resolves to ESSD 13/4349). +- Ecosystem roles copied from wet's README (cd's own row) and link's (wet, gq). +- Mechanical: all 6 functions named are exported; all 15 links return 200. diff --git a/planning/active/progress.md b/planning/active/progress.md index 1053d92..170e7a4 100644 --- a/planning/active/progress.md +++ b/planning/active/progress.md @@ -7,3 +7,4 @@ - Scaffolded PWF baseline from issue #142 with approved phases - Next: start Phase 1 - Phase 1: `data-raw/readme_figure.R` run against the live catalog (07:26 UTC, 4 s with the cache warm). KOTL annual tmean, 1951:1980 baseline: slope 0.025 °C/yr over 75 years, total change 1.9 °C. PNG 1050 x 525, min alpha 1 (opaque); text legible at a ~700 px column. +- Phase 2: README rewritten to the convention, 962 -> 593 words; exports and links checked. diff --git a/planning/active/task_plan.md b/planning/active/task_plan.md index ac8f2d3..0e15a61 100644 --- a/planning/active/task_plan.md +++ b/planning/active/task_plan.md @@ -11,16 +11,16 @@ Scope set at the plan gate (2026-10-17): rewrite the README to soul's `readme.md ## Phase 2: README rewrite, in the convention's order -- [ ] Title line with hex sticker (`alt` text added), lifecycle-experimental badge, one-line tagline -- [ ] Opening: what cd is (how far BC's climate has moved from a chosen baseline, for any area), the data (ERA5-Land reanalysis since 1950, served as a public self-updating catalog, no credentials), what it informs (which watersheds are warming or losing snow, for restoration planning and monitoring); one clause each for daily point temperatures (stream-temperature and degree-day work), any annual series (streamflow, stream temperature), and each value naming the file build it came from -- [ ] Figure + alt text + one-line caption -- [ ] Installation, then the "under active development / see NEWS / pin `@vX.Y.Z`" line -- [ ] Example: the Phase 1 code with a `1951:1980` baseline, shown with its real pasted `cd_summary()` output; one sentence that files are cached after first read -- [ ] Learn more: one line per vignette (peace-fwcp, kootenay-lake, northern-bc), then the function reference -- [ ] Ecosystem: cd, wet (and gq only if a vignette uses it), roles worded as in link's README -- [ ] Data and methods it builds on: ERA5-Land (Copernicus/ECMWF) via DestinE Earth Data Hub with the Copernicus attribution sentence, Mann-Kendall / Theil-Sen, and the `bcgov/bc_climate_anomaly` inspiration (replaces Acknowledgements) -- [ ] Citation (points to `CITATION.cff` / `citation("cd")`) and License -- [ ] Record word count before/after in findings.md +- [x] Title line with hex sticker (`alt` text added), lifecycle-experimental badge, one-line tagline +- [x] Opening: what cd is (how far BC's climate has moved from a chosen baseline, for any area), the data (ERA5-Land reanalysis since 1950, served as a public self-updating catalog, no credentials), what it informs (which watersheds are warming or losing snow, for restoration planning and monitoring); one clause each for daily point temperatures (stream-temperature and degree-day work), any annual series (streamflow, stream temperature), and each value naming the file build it came from +- [x] Figure + alt text + one-line caption +- [x] Installation, then the "under active development / see NEWS / pin `@vX.Y.Z`" line +- [x] Example: the Phase 1 code with a `1951:1980` baseline, shown with its real pasted `cd_summary()` output; one sentence that files are cached after first read +- [x] Learn more: one line per vignette (peace-fwcp, kootenay-lake, northern-bc), then the function reference +- [x] Ecosystem: cd, wet (and gq only if a vignette uses it), roles worded as in link's README +- [x] Data and methods it builds on: ERA5-Land (Copernicus/ECMWF) via DestinE Earth Data Hub with the Copernicus attribution sentence, Mann-Kendall / Theil-Sen, and the `bcgov/bc_climate_anomaly` inspiration (replaces Acknowledgements) +- [x] Citation (points to `CITATION.cff` / `citation("cd")`) and License +- [x] Record word count before/after in findings.md ## Phase 3: Texts that travel with the README From cfe77452039ef0c4c38ee1d232c0871ea677261d Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:29:14 -0700 Subject: [PATCH 04/13] DESCRIPTION, tagline and About say the same thing; NGE as a citation author (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- .github/workflows/update-citation-cff.yaml | 2 +- DESCRIPTION | 18 ++++++++++-------- README.md | 2 +- man/cd-package.Rd | 8 ++++---- planning/active/progress.md | 1 + planning/active/task_plan.md | 6 +++--- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/.github/workflows/update-citation-cff.yaml b/.github/workflows/update-citation-cff.yaml index bd3552e..7512d85 100644 --- a/.github/workflows/update-citation-cff.yaml +++ b/.github/workflows/update-citation-cff.yaml @@ -27,7 +27,7 @@ jobs: - name: Update CITATION.cff run: | Rscript -e ' - x <- cffr::cff_create() + x <- cffr::cff_create(authors_roles = c("aut", "cre", "cph")) x$references <- NULL; x$doi <- NULL; x$repository <- NULL x$identifiers <- Filter(function(i) !grepl("CRAN.package", i$value, fixed = TRUE), unclass(x$identifiers)) if (!length(x$identifiers)) x$identifiers <- NULL diff --git a/DESCRIPTION b/DESCRIPTION index abe90d5..5c03ea6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: cd -Title: Climate Departure Analysis from ERA5-Land Reanalysis +Title: Climate Departure for British Columbia from ERA5-Land Reanalysis Version: 0.6.12 Date: 2026-10-17 Authors@R: c( @@ -8,13 +8,15 @@ Authors@R: c( affiliation = "New Graph Environment Ltd.")), person("New Graph Environment Ltd.", role = c("cph", "fnd")) ) -Description: Compute climate anomalies from ERA5-Land reanalysis data for - custom areas of interest. Producer functions download ERA5-Land - monthly means, derive variables (VPD, RH, soil moisture), and publish - Cloud-Optimized GeoTIFFs with a static STAC catalog. Consumer - functions query the catalog, crop to AOI, compute baselines and - anomalies for arbitrary reference periods, and run trend analysis - (Mann-Kendall and Theil-Sen). +Description: Measures how far the climate of any area in British Columbia + has moved from a chosen reference period: air temperature, + precipitation, humidity, soil moisture and snow, by season and year + since 1950, with trends (Mann-Kendall and Theil-Sen). Reads ERA5-Land + reanalysis from a public STAC catalog of Cloud-Optimized GeoTIFFs, and + daily air temperature at points. The baseline, anomaly and trend + functions take any annual series, such as streamflow. Includes the + functions that build and publish the catalog. Under active + development. License: MIT + file LICENSE URL: https://github.com/NewGraphEnvironment/cd, https://newgraphenvironment.github.io/cd/ diff --git a/README.md b/README.md index 219be74..d673d9d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) -> How far British Columbia's climate has moved from any baseline, for any area, from ERA5-Land reanalysis +> Climate departure for British Columbia: how far the climate of any area has moved from any baseline, from ERA5-Land reanalysis cd measures how much the climate of a watershed or any other area in British Columbia has changed: air temperature, precipitation, humidity, soil moisture and snow, by season and year since 1950, compared with whatever reference period you choose, with the trend and how much it has moved. It reads ERA5-Land reanalysis from a public catalog that needs no account, so restoration can be planned and monitored against the climate a site has now rather than the one it had. It also gives daily air temperature at any point in the province, for stream-temperature models and degree-day work, and its baseline and trend steps take any annual series, such as streamflow or stream temperature. diff --git a/man/cd-package.Rd b/man/cd-package.Rd index e0fb49b..c8e67a1 100644 --- a/man/cd-package.Rd +++ b/man/cd-package.Rd @@ -4,11 +4,11 @@ \name{cd-package} \alias{cd} \alias{cd-package} -\title{cd: Climate Departure Analysis from ERA5-Land Reanalysis} +\title{cd: Climate Departure for British Columbia from ERA5-Land Reanalysis} \description{ \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} -Compute climate anomalies from ERA5-Land reanalysis data for custom areas of interest. Producer functions download ERA5-Land monthly means, derive variables (VPD, RH, soil moisture), and publish Cloud-Optimized GeoTIFFs with a static STAC catalog. Consumer functions query the catalog, crop to AOI, compute baselines and anomalies for arbitrary reference periods, and run trend analysis (Mann-Kendall and Theil-Sen). +Measures how far the climate of any area in British Columbia has moved from a chosen reference period: air temperature, precipitation, humidity, soil moisture and snow, by season and year since 1950, with trends (Mann-Kendall and Theil-Sen). Reads ERA5-Land reanalysis from a public STAC catalog of Cloud-Optimized GeoTIFFs, and daily air temperature at points. The baseline, anomaly and trend functions take any annual series, such as streamflow. Includes the functions that build and publish the catalog. Under active development. } \seealso{ Useful links: @@ -20,11 +20,11 @@ Useful links: } \author{ -\strong{Maintainer}: Allan Irvine \email{al@newgraphenvironment.com} (\href{https://orcid.org/0000-0002-3495-2128}{ORCID}) +\strong{Maintainer}: Allan Irvine \email{al@newgraphenvironment.com} (\href{https://orcid.org/0000-0002-3495-2128}{ORCID}) (New Graph Environment Ltd.) Other contributors: \itemize{ - \item New Graph Environment Ltd. [copyright holder] + \item New Graph Environment Ltd. [copyright holder, funder] } } diff --git a/planning/active/progress.md b/planning/active/progress.md index 170e7a4..09742e8 100644 --- a/planning/active/progress.md +++ b/planning/active/progress.md @@ -8,3 +8,4 @@ - Next: start Phase 1 - Phase 1: `data-raw/readme_figure.R` run against the live catalog (07:26 UTC, 4 s with the cache warm). KOTL annual tmean, 1951:1980 baseline: slope 0.025 °C/yr over 75 years, total change 1.9 °C. PNG 1050 x 525, min alpha 1 (opaque); text legible at a ~700 px column. - Phase 2: README rewritten to the convention, 962 -> 593 words; exports and links checked. +- Phase 3: DESCRIPTION Title/Description and README tagline in step; cffr call passes authors_roles (local cff_create shows New Graph Environment Ltd. as second author); GitHub About set to the tagline (was: "Climate departure analysis from ERA5-Land reanalysis. Producer pipeline publishes monthly-refreshed COGs + STAC catalog for BC; ..."). diff --git a/planning/active/task_plan.md b/planning/active/task_plan.md index 0e15a61..4d2f954 100644 --- a/planning/active/task_plan.md +++ b/planning/active/task_plan.md @@ -24,9 +24,9 @@ Scope set at the plan gate (2026-10-17): rewrite the README to soul's `readme.md ## Phase 3: Texts that travel with the README -- [ ] DESCRIPTION `Title` in step with the tagline; `Description` in step with the opening (drops the stale "download ERA5-Land monthly means"), ends "Under active development."; `devtools::document()` -- [ ] `update-citation-cff.yaml`: `cff_create(authors_roles = c("aut", "cre", "cph"))` so New Graph Environment Ltd. is a citation author -- [ ] GitHub About via `gh repo edit NewGraphEnvironment/cd --description "…"`, same words as the tagline +- [x] DESCRIPTION `Title` in step with the tagline; `Description` in step with the opening (drops the stale "download ERA5-Land monthly means"), ends "Under active development."; `devtools::document()` +- [x] `update-citation-cff.yaml`: `cff_create(authors_roles = c("aut", "cre", "cph"))` so New Graph Environment Ltd. is a citation author +- [x] GitHub About via `gh repo edit NewGraphEnvironment/cd --description "…"`, same words as the tagline ## Phase 4: Grouped reference index From 0362f706db2f7412dd0179dd86b240148509f730 Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:33:21 -0700 Subject: [PATCH 05/13] pkgdown: group the reference index by purpose (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- _pkgdown.yml | 39 ++++++++++++++++++++++++++++++++++++ planning/active/progress.md | 1 + planning/active/task_plan.md | 4 ++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/_pkgdown.yml b/_pkgdown.yml index 8d5472f..4ebe1e7 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -2,3 +2,42 @@ url: https://newgraphenvironment.github.io/cd/ template: bootstrap: 5 +reference: +- title: Read the data + desc: Climate series for an area, or daily air temperature at points. + contents: + - cd_catalog + - cd_catalog_default + - cd_extract + - cd_extract_daily + - cd_crop +- title: Departures and trends + desc: Compare a series with a baseline or between two windows, test its trend, and tabulate the result. These take any annual series in cd's long format. + contents: + - cd_baseline + - cd_anomaly + - cd_compare + - cd_trend + - cd_summary +- title: Plots + contents: + - cd_plot_timeseries + - cd_plot_comparison +- title: Variables, periods and seasons + contents: + - cd_variables + - cd_periods + - cd_seasons +- title: Cache + desc: Each file is downloaded once and read locally after that. + contents: + - starts_with("cd_cache_") +- title: Building the published data + desc: For maintainers. The catalog is built and published by a scheduled workflow; users do not need these. + contents: + - cd_fetch + - cd_derive + - cd_aggregate + - cd_cog_write + - cd_stac_catalog + - cd_s3_push diff --git a/planning/active/progress.md b/planning/active/progress.md index 09742e8..3183c6f 100644 --- a/planning/active/progress.md +++ b/planning/active/progress.md @@ -9,3 +9,4 @@ - Phase 1: `data-raw/readme_figure.R` run against the live catalog (07:26 UTC, 4 s with the cache warm). KOTL annual tmean, 1951:1980 baseline: slope 0.025 °C/yr over 75 years, total change 1.9 °C. PNG 1050 x 525, min alpha 1 (opaque); text legible at a ~700 px column. - Phase 2: README rewritten to the convention, 962 -> 593 words; exports and links checked. - Phase 3: DESCRIPTION Title/Description and README tagline in step; cffr call passes authors_roles (local cff_create shows New Graph Environment Ltd. as second author); GitHub About set to the tagline (was: "Climate departure analysis from ERA5-Land reanalysis. Producer pipeline publishes monthly-refreshed COGs + STAC catalog for BC; ..."). +- Phase 4: `_pkgdown.yml` reference grouped in six sections (variables/periods/seasons split out of "Read the data" for clarity; `starts_with("cd_cache_")`); `check_pkgdown()` clean; home and reference index built to scratch, figure copied to `reference/figures/`, page screenshot reviewed. diff --git a/planning/active/task_plan.md b/planning/active/task_plan.md index 4d2f954..07ede5f 100644 --- a/planning/active/task_plan.md +++ b/planning/active/task_plan.md @@ -30,8 +30,8 @@ Scope set at the plan gate (2026-10-17): rewrite the README to soul's `readme.md ## Phase 4: Grouped reference index -- [ ] `_pkgdown.yml` `reference:` sections: Read the data (`cd_catalog`, `cd_catalog_default`, `cd_crop`, `cd_extract`, `cd_extract_daily`, `cd_variables`, `cd_periods`, `cd_seasons`); Departures and trends (`cd_baseline`, `cd_anomaly`, `cd_compare`, `cd_trend`, `cd_summary`); Plots (`cd_plot_*`); Cache (`cd_cache_*`); Publishing the data, for maintainers (`cd_fetch`, `cd_derive`, `cd_aggregate`, `cd_cog_write`, `cd_stac_catalog`, `cd_s3_push`) -- [ ] `pkgdown::check_pkgdown()` clean; `pkgdown::build_home()` locally and look at the rendered page and figure +- [x] `_pkgdown.yml` `reference:` sections: Read the data (`cd_catalog`, `cd_catalog_default`, `cd_crop`, `cd_extract`, `cd_extract_daily`, `cd_variables`, `cd_periods`, `cd_seasons`); Departures and trends (`cd_baseline`, `cd_anomaly`, `cd_compare`, `cd_trend`, `cd_summary`); Plots (`cd_plot_*`); Cache (`cd_cache_*`); Publishing the data, for maintainers (`cd_fetch`, `cd_derive`, `cd_aggregate`, `cd_cog_write`, `cd_stac_catalog`, `cd_s3_push`) +- [x] `pkgdown::check_pkgdown()` clean; `pkgdown::build_home()` locally and look at the rendered page and figure ## Phase 5: Close out From 94eef3a99e04e956571d080a05be7faccd97e015 Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:33:36 -0700 Subject: [PATCH 06/13] README: NOTICE for ERA5-Land data, plain axis label, fixes from plan review (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- .github/workflows/pkgdown.yaml | 2 +- NOTICE.md | 17 +++++++++++++++++ README.md | 13 ++++++++----- data-raw/readme_figure.R | 3 ++- man/figures/readme-kotl-tmean.png | Bin 39827 -> 45886 bytes planning/active/review-1.md | 25 +++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 NOTICE.md create mode 100644 planning/active/review-1.md diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index a6cf9d3..76dac5b 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -59,7 +59,7 @@ jobs: - name: Fail if an unexpected page reached the site run: | set -eu - allowed="404 authors index LICENSE LICENSE-text" + allowed="404 authors index LICENSE LICENSE-text NOTICE" # An empty result set is not a pass. A loop over nothing exits 0, so a build # that produced no pages at all would report "all declared" — the guard diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 0000000..fe27bc2 --- /dev/null +++ b/NOTICE.md @@ -0,0 +1,17 @@ +# NOTICE + +cd's climate data are derived from ERA5-Land, produced by ECMWF for the Copernicus Climate Change Service and distributed under the [Creative Commons Attribution 4.0 International licence](https://creativecommons.org/licenses/by/4.0/) (CC BY 4.0). + +> Contains modified Copernicus Climate Change Service information. + +ERA5-Land: Muñoz-Sabater, J., et al. (2021). ERA5-Land: a state-of-the-art global reanalysis dataset for land applications. *Earth System Science Data*, 13, 4349–4383. + +cd reads ERA5-Land from the [DestinE Earth Data Hub](https://earthdatahub.destine.eu/), aggregates and derives variables from it (seasonal and annual means and totals, vapour pressure deficit, relative humidity, soil moisture, snow metrics, and daily local-day air temperature), and publishes the results to `s3://stac-era5-land`. + +## Redistributed data + +This repository redistributes modified ERA5-Land data, under CC BY 4.0, in: + +- `inst/extdata/example_climate.tif` +- `inst/extdata/example_daily/` (daily air temperature, 2002) +- `inst/vignette-data/` (the precomputed series and rasters the vignettes read) diff --git a/README.md b/README.md index d673d9d..4c0393f 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ pak::pak("NewGraphEnvironment/cd") cd is under active development and its functions change between releases (see [NEWS](https://newgraphenvironment.github.io/cd/news/index.html)). Pin a release for reproducible work: `pak::pak("NewGraphEnvironment/cd@vX.Y.Z")`. +The example below also needs sf, Kendall and zyp: `pak::pak(c("sf", "Kendall", "zyp"))`. + ## Example Extract a series for an area, compare it with a baseline, and test the trend. This is the run behind the figure above: @@ -45,7 +47,7 @@ cd_summary(trn) #> 1 Mean temperature Annual 0.025 75 1.9 °C 0 ``` -Each file is downloaded once and read from a local cache after that. Every value extracted records the commit of cd's code that built the file it came from. +Files are cached after the first read and downloaded again only when they are republished. Extracted rows record which commit of cd built each file they came from. ## Learn more @@ -60,16 +62,17 @@ Each file is downloaded once and read from a local cache after that. Every value |---|---| | **cd** | Climate departure: baselines, anomalies and trends, and ERA5-Land climate (this package) | | [wet](https://github.com/NewGraphEnvironment/wet) | Stream flow and water temperature for BC's Freshwater Atlas | -| [gq](https://github.com/NewGraphEnvironment/gq) | Shared map symbology | + +cd computes the departures from wet's yearly station values. ## Data and methods it builds on -The climate data are [ERA5-Land](https://www.ecmwf.int/en/era5-land) ([Muñoz-Sabater et al. 2021](https://doi.org/10.5194/essd-13-4349-2021)), produced by ECMWF for the Copernicus Climate Change Service and read from the [DestinE Earth Data Hub](https://earthdatahub.destine.eu/). The published layers contain modified Copernicus Climate Change Service information. Trends are Mann-Kendall tests with Theil-Sen slopes, from the [Kendall](https://cran.r-project.org/package=Kendall) and [zyp](https://cran.r-project.org/package=zyp) packages. cd's variables and its ecoregion and watershed framing follow [`bcgov/bc_climate_anomaly`](https://github.com/bcgov/bc_climate_anomaly), a Shiny app by the Province of British Columbia (Aseem Sharma and contributors). +The climate data are [ERA5-Land](https://www.ecmwf.int/en/era5-land) ([Muñoz-Sabater et al. 2021](https://doi.org/10.5194/essd-13-4349-2021)), produced by ECMWF for the Copernicus Climate Change Service and read from the [DestinE Earth Data Hub](https://earthdatahub.destine.eu/). The published layers contain modified Copernicus Climate Change Service information, under CC BY 4.0. Trends are Mann-Kendall tests with Theil-Sen slopes, from the [Kendall](https://cran.r-project.org/package=Kendall) and [zyp](https://cran.r-project.org/package=zyp) packages. cd's variables and its ecoregion and watershed framing follow [`bcgov/bc_climate_anomaly`](https://github.com/bcgov/bc_climate_anomaly), a Shiny app by the Province of British Columbia (Aseem Sharma and contributors). ## Citation -Cite cd with `citation("cd")`, or from [`CITATION.cff`](CITATION.cff). +Cite cd with `citation("cd")`. ## License -MIT © New Graph Environment Ltd. See [LICENSE](LICENSE.md). +MIT © New Graph Environment Ltd. See [LICENSE](LICENSE.md). The ERA5-Land data it ships and publishes are CC BY 4.0; see [NOTICE](NOTICE.md). diff --git a/data-raw/readme_figure.R b/data-raw/readme_figure.R index c27adac..70be56e 100644 --- a/data-raw/readme_figure.R +++ b/data-raw/readme_figure.R @@ -39,7 +39,8 @@ print(cd_summary(trn)) p <- cd_plot_timeseries(ano, trend = trn) + ggplot2::theme_minimal(base_size = 15) + - ggplot2::theme(legend.position = "none") + ggplot2::theme(legend.position = "none") + + ggplot2::labs(y = "Difference from 1951–1980\naverage (°C)") out <- "man/figures/readme-kotl-tmean.png" # png() gives an opaque white background, which survives a dark web page. diff --git a/man/figures/readme-kotl-tmean.png b/man/figures/readme-kotl-tmean.png index 8e8fde65b228c23722420afdd9da4ebc12ae06d2..8b4c54f32f3b96c4f03bc5288a965018ff698d77 100644 GIT binary patch literal 45886 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 X~VR{v9Ri>aY$W-;vg zYycQ@(!S(w_%NBuBD|an=rbK8EP(Z}g2e-!ihSW7b8mK^H@IBj$;b<~Kziu_!vrjo z)sFW^1TBZ}9)tER0{|iwz$5G9{4O|CNf`hh2Cmtc612cuMM7P2iM)jfS+;wDUG~hU z#}NAn`DCHV-Z51;`9q^Y^&JUY<`Piu(qR-2(*eVi`tE7>Vjhd(duFwcyA32&?6?pA zCupOWL$tKwND81VkmWZhb&B%x`>t9AzcdrzAtCY!07EZa7qDdfoVo!dheQ~<#{Wnh zJbXmPl2T(`lK?X35VMChs^;S!0GO2lhz8l4A}xTX8O?qF-nBFiIA;Lqb#S*#+q>Qm zuFsBnz%>PY2Dtkg4)!r_x$Upe*EnzT#0Z)9r+b%dRo6tZX!M+$`-Fv&@jdnAGrKw6 z%%;*GRZ6-tVoBC<4Y@^Uhl^eGv(Ki4p)GYgPf;UDQ=Uw_6m6 zDeU3FhkWe{g~$!`LyH~8CwY+NItGJ1RVS0g_r98%Dt+7pK0jAT zX%F$Ef

0Omf;x@D2;zu~9X}aFFzUr*3>r8 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 Date: Sat, 17 Oct 2026 00:44:24 -0700 Subject: [PATCH 07/13] code-check round 1: cache wording, CDS route split out, NOTICE scope (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- NOTICE.md | 5 +- README.md | 2 +- _pkgdown.yml | 13 ++++-- planning/active/progress.md | 1 + planning/active/review-round1.md | 78 ++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 planning/active/review-round1.md diff --git a/NOTICE.md b/NOTICE.md index fe27bc2..d5f19ac 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -12,6 +12,9 @@ cd reads ERA5-Land from the [DestinE Earth Data Hub](https://earthdatahub.destin This repository redistributes modified ERA5-Land data, under CC BY 4.0, in: -- `inst/extdata/example_climate.tif` - `inst/extdata/example_daily/` (daily air temperature, 2002) - `inst/vignette-data/` (the precomputed series and rasters the vignettes read) + +It also redistributes, in `inst/extdata/example_aoi_*.gpkg` and `inst/extdata/context_*.gpkg`, watershed groups, lakes, rivers and streams from the BC Freshwater Atlas and ecoregions from the Ecoregion Ecosystem Classification of British Columbia, under the [Open Government Licence – British Columbia](https://www2.gov.bc.ca/gov/content/data/policy-standards/open-data/open-government-licence-bc). + +> Contains information licensed under the Open Government Licence – British Columbia. diff --git a/README.md b/README.md index 4c0393f..5f7c136 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ cd computes the departures from wet's yearly station values. ## Data and methods it builds on -The climate data are [ERA5-Land](https://www.ecmwf.int/en/era5-land) ([Muñoz-Sabater et al. 2021](https://doi.org/10.5194/essd-13-4349-2021)), produced by ECMWF for the Copernicus Climate Change Service and read from the [DestinE Earth Data Hub](https://earthdatahub.destine.eu/). The published layers contain modified Copernicus Climate Change Service information, under CC BY 4.0. Trends are Mann-Kendall tests with Theil-Sen slopes, from the [Kendall](https://cran.r-project.org/package=Kendall) and [zyp](https://cran.r-project.org/package=zyp) packages. cd's variables and its ecoregion and watershed framing follow [`bcgov/bc_climate_anomaly`](https://github.com/bcgov/bc_climate_anomaly), a Shiny app by the Province of British Columbia (Aseem Sharma and contributors). +The climate data are [ERA5-Land](https://www.ecmwf.int/en/era5-land) ([Muñoz-Sabater et al. 2021](https://doi.org/10.5194/essd-13-4349-2021)), produced by ECMWF for the Copernicus Climate Change Service and read from the [DestinE Earth Data Hub](https://earthdatahub.destine.eu/). The published layers contain modified Copernicus Climate Change Service information, under CC BY 4.0. Trends are Mann-Kendall tests with Theil-Sen slopes, from the [Kendall](https://cran.r-project.org/package=Kendall) and [zyp](https://cran.r-project.org/package=zyp) packages. cd's core climate variables and its ecoregion and watershed framing follow [`bcgov/bc_climate_anomaly`](https://github.com/bcgov/bc_climate_anomaly), a Shiny app by the Province of British Columbia (Aseem Sharma and contributors). ## Citation diff --git a/_pkgdown.yml b/_pkgdown.yml index 4ebe1e7..3cbd06f 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -29,15 +29,18 @@ reference: - cd_periods - cd_seasons - title: Cache - desc: Each file is downloaded once and read locally after that. + desc: Files are cached after the first read and downloaded again only when they are republished. contents: - starts_with("cd_cache_") -- title: Building the published data - desc: For maintainers. The catalog is built and published by a scheduled workflow; users do not need these. +- title: Publishing the catalog + desc: For maintainers. A scheduled workflow uses these to write the published files and catalog; users do not need them. contents: - - cd_fetch - - cd_derive - cd_aggregate - cd_cog_write - cd_stac_catalog - cd_s3_push +- title: Downloading from the Copernicus Climate Data Store + desc: An alternative route to monthly ERA5-Land through the Copernicus Climate Data Store. The published catalog is not built this way. + contents: + - cd_fetch + - cd_derive diff --git a/planning/active/progress.md b/planning/active/progress.md index 3183c6f..d9a664e 100644 --- a/planning/active/progress.md +++ b/planning/active/progress.md @@ -10,3 +10,4 @@ - Phase 2: README rewritten to the convention, 962 -> 593 words; exports and links checked. - Phase 3: DESCRIPTION Title/Description and README tagline in step; cffr call passes authors_roles (local cff_create shows New Graph Environment Ltd. as second author); GitHub About set to the tagline (was: "Climate departure analysis from ERA5-Land reanalysis. Producer pipeline publishes monthly-refreshed COGs + STAC catalog for BC; ..."). - Phase 4: `_pkgdown.yml` reference grouped in six sections (variables/periods/seasons split out of "Read the data" for clarity; `starts_with("cd_cache_")`); `check_pkgdown()` clean; home and reference index built to scratch, figure copied to `reference/figures/`, page screenshot reviewed. +- code-check round 1 (spawned 07:34 UTC): 5 findings, 4 fixed, 1 accepted; filed #150 (anomaly axis label) and #151 (bundled data licences). Tests: FAIL 0 | PASS 768 (6 pre-existing warnings in cd_plot_comparison). diff --git a/planning/active/review-round1.md b/planning/active/review-round1.md new file mode 100644 index 0000000..7207be2 --- /dev/null +++ b/planning/active/review-round1.md @@ -0,0 +1,78 @@ +# Code-check round 1: branch 142-readme-add-daily-point-temperatures-and (vs main @ 59a5122) + +Reviewer read every changed file in full, the readme.md and writing.md conventions, the R sources behind each claim, the live catalog and daily manifest, live COG tags, wet's origin/main, bcgov/bc_climate_anomaly. Built the pkgdown home and ran `pkgdown::check_pkgdown()` on a `git archive HEAD` copy in the scratchpad (no problems found; NOTICE.html built; README links rewritten to LICENSE.html / NOTICE.html; no unexpected root pages). Every external link in README.md and NOTICE.md answers 200. + +Disclosure: one `gdalinfo -stats` on `inst/extdata/example_climate.tif` wrote an `.aux.xml` sidecar into the repo. It was deleted right away, and `git status` showed the tree clean afterwards. Nothing else in the repo was touched. + +## Findings + +- **[false-claim, low]** `_pkgdown.yml:46-47` (Cache section): "Each file is downloaded once and read locally after that." `cd_cache_fetch()` revalidates with a HEAD on every call and downloads again when the ETag changes, so a republished file is downloaded again. The README says the opposite, correctly: "downloaded again only when they are republished". Two published texts disagree, and the pkgdown one is wrong. Fix: e.g. "Each file is downloaded once, and again only when it is republished." + +- **[false-claim, low]** `_pkgdown.yml:48-56` ("Building the published data": "The catalog is built and published by a scheduled workflow; users do not need these"). The section lists `cd_fetch()` and `cd_derive()`, and neither is called anywhere in `scripts/`. They are the CDS-based fallback: `cd_fetch` downloads from the Copernicus CDS, and `cd_derive` builds tmax/tmin by its own route, not the local-day route the published layers use. CLAUDE.md says they ship "for users who want a CDS-based fallback, but are not what runs in CI". Under this heading they read as part of what builds the published data, which they are not. Fix: either give them their own line ("an alternative CDS route; not used for the published catalog"), or move them out of the section. `cd_aggregate`, `cd_cog_write`, `cd_stac_catalog` and `cd_s3_push` are used by `pipeline_*_edh.R`, so the claim holds for those. + +- **[false-claim, low]** `README.md:84` "cd's variables and its ecoregion and watershed framing follow bcgov/bc_climate_anomaly". cd has 15 variables, and 8 of them are snow (swe, snowfall, snowmelt, snow_cover, swe_max, snowfall_fraction, snowmelt_doy_50, snowmelt_rate_peak). bc_climate_anomaly's `app.R` has no snow variable: "snow"/"swe" match 0 times, while tmean, tmax, tmin, prcp, vpd, rh and soil all appear. The quantifier covers the whole set, and only the 7 core variables follow it. Fix: "cd's core climate variables …" (or "its temperature, precipitation, humidity and soil-moisture variables"). + +- **[fragile / convention gap, low]** `README.md:88` "Cite cd with `citation("cd")`", together with the `update-citation-cff.yaml` change (commit cfe7745, "NGE as a citation author"). `citation("cd")` reads `inst/CITATION`, whose `author =` keeps only `"aut"` roles. Rendered from this branch's DESCRIPTION it gives "Irvine A (2026). _cd: …_. New Graph Environment Ltd." with NGE only as `organization`, not as an author. After the workflow runs, CITATION.cff will list NGE as an author. The README points readers to the citation that leaves NGE out, which readme.md §9 requires ("Citation from CITATION.cff, with New Graph Environment Ltd. as an author"). link's inst/CITATION is identical, so this is a fleet pattern, not something this branch introduced. Either add `"cph"` to the inst/CITATION filter, or accept it and say so. + +- **[licence gap, low; pre-existing, partly outside #142's NOTICE task]** `NOTICE.md`. The README's License line ("see NOTICE") makes NOTICE the place for third-party data terms, but NOTICE covers only ERA5-Land. Two other gaps: + (a) The package also ships BC government data: FWA watershed groups in `inst/extdata/example_aoi_*.gpkg`, and ecoregions, lakes, rivers, highways, towns and the BC outline in `inst/extdata/context_*.gpkg` (from fwapg and the BC WFS via bcdata, per `data-raw/example_aoi_*.R` and `example_context_*.R`). That data is under the Open Government Licence – British Columbia, which requires an attribution statement, and none is given anywhere. + (b) `inst/extdata/example_climate.tif` is not output of cd's EDH pipeline, which is what NOTICE's paragraph implies. `data-raw/example_climate_tmean.R` crops it from bc_climate_anomaly's `tmean_ano_annual_1950_+_res25.nc`, the Province's processing of CDS ERA5-Land at 0.25° (the file's pixel size is 0.25). bc_climate_anomaly has no licence file (GitHub reports `license: null`). Calling it "modified ERA5-Land data, under CC BY 4.0" is defensible as to the ultimate source, but the Province's intermediate product is not credited. The old README's acknowledgement credited it; the new one credits only the variable framing. + Neither gap makes a sentence in the diff false. Both are real attribution gaps in the file this branch introduces for that purpose. + +## Claims checked (verdict) + +README.md +1. Tagline "Climate departure for BC: how far the climate of any area has moved from any baseline, from ERA5-Land": true. It matches the GitHub About exactly (`gh repo view`), and the DESCRIPTION Title is consistent with it. +2. "air temperature, precipitation, humidity, soil moisture and snow, by season and year since 1950": true. The live catalog has 59 items: 11 variables × {annual, winter, spring, summer, fall} plus 4 annual-only, and every item starts 1950-01-01. +3. "compared with whatever reference period you choose, with the trend and how much it has moved": true (`cd_baseline(baseline_years=)`, `cd_trend`, `cd_summary` Total Change). +4. "public catalog that needs no account": true. `cd_catalog_default()` is the public https S3 URL, and the catalog fetched anonymously. +5. "daily air temperature at any point in the province": true. The cube covers 47.95–60.05 N, 140.05–113.95 W, and the manifest lists 228 files, 1950–2025. Coastal no-data cells move to a neighbour, as documented. +6. "baseline and trend steps take any annual series, such as streamflow or stream temperature": true (`?cd_anomaly` input contract; wet's `wet_window_stats`/`wet_temp_gsdd` feed them). +7. Figure alt "1950 to 2025 … dashed trend line rising about 1.9 degrees": true. The image shows 1950–2025 bars and a dashed line from about −0.35 to about 1.53. The first trend line is dashed (`cd_plot_timeseries`). +8. Caption "Red years were warmer, blue cooler; dashed line is the trend since 1951": true. The fill is `>= 0` → `#d73027`, else `#4575b4`, and `trend_start = 1951`. +9. "The example below also needs sf, Kendall and zyp": true. Only `cd_trend` calls `check_installed(c("Kendall","zyp"))`, sf is needed for `st_read`, and the example does not plot. +10. Pin `@vX.Y.Z`: tags of that form exist (v0.6.12 latest). +11. "This is the run behind the figure above": true. Same code as `data-raw/readme_figure.R` (accepted). +12. Pasted output (Mean temperature, Annual, 0.025, 75, 1.9, °C, 0): consistent with `cd_summary()` (75 = 1951–2025; Total Change = round(slope × n, 1); long_name). Output accepted as a real run. +13. "Files are cached after the first read and downloaded again only when they are republished": true for `cd_extract` (default `cache = TRUE`, ETag revalidation). +14. "Extracted rows record which commit of cd built each file": true. `cd_sha` is read from the file's `CD_SHA` tag, and the live `tmean_annual.tif` and `daily/tmean_daily_1950.tif` both carry `CD_SHA`. All 59 catalog items carry `processing:software.cd`. +15. Learn-more titles and URLs: they match the three `vignettes/*.Rmd` titles and all answer 200. The one-line descriptions are consistent with CLAUDE.md. +16. Ecosystem: wet's role matches wet's About verbatim. "cd computes the departures from wet's yearly station values": true (wet docs and vignette call `cd::cd_baseline/anomaly/trend`). +17. ERA5-Land, ECMWF for C3S, read from EDH: true (producer). The CC BY 4.0 licence is confirmed on the CDS catalogue API (`license: CC-BY-4.0`). The Muñoz-Sabater 2021 DOI resolves. +18. "Mann-Kendall tests with Theil-Sen slopes, from Kendall and zyp": true (`Kendall::MannKendall`, `zyp::zyp.sen`). +19. "cd's variables … follow bc_climate_anomaly": partly false (finding 3). "Shiny app by the Province … (Aseem Sharma and contributors)": consistent (its sole contributor is aseemsharma1, and the app's watermark names the BC Ministry of Forests). +20. Citation via `citation("cd")`: works, but leaves NGE out as an author (finding 4). +21. License "MIT © NGE … ERA5-Land data it ships and publishes are CC BY 4.0": true as far as it goes (finding 5 covers the non-ERA5 data). + +NOTICE.md +22. CC BY 4.0 and the "Contains modified Copernicus Climate Change Service information" wording: true. +23. ERA5-Land reference (ESSD 13, 4349–4383): correct. +24. "reads from EDH, aggregates and derives (seasonal and annual means and totals, VPD, RH, soil moisture, snow metrics, daily local-day air temperature), publishes to s3://stac-era5-land": true for the published data. Not how `example_climate.tif` was made (finding 5b). +25. Redistributed-file list: all three paths exist and are ERA5-Land-derived. No other ERA5-derived data file is tracked (git ls-files). The README figure is derived output, not data. + +DESCRIPTION / man/cd-package.Rd +26. Title and Description: each clause is true (STAC of COGs, daily at points, any annual series, "Includes the functions that build and publish the catalog" = `cd_cog_write`/`cd_stac_catalog`/`cd_s3_push`/`cd_aggregate`, used by the pipelines). The Rd matches DESCRIPTION. + +_pkgdown.yml +27. All 25 exports are indexed, and `check_pkgdown()` finds no problems. +28. "Climate series for an area, or daily air temperature at points": true. +29. Departures desc: true. +30. Cache desc: false (finding 1). +31. Building desc: misleading for cd_fetch/cd_derive (finding 2). + +Workflows +32. `pkgdown.yaml` allowlist + NOTICE: correct. pkgdown renders NOTICE.html, and the guard strips both extensions. +33. `update-citation-cff.yaml` `authors_roles = c("aut","cre","cph")`: cffr 1.4.2 accepts it. Tested on a copy of DESCRIPTION, it yields Irvine plus `name: New Graph Environment Ltd.`, and the title updates. + +data-raw/readme_figure.R +34. Runs from the checkout (`load_all`), opaque white png, and the example block is identical to the README. No defects. The top-level `cd_summary(trn)` autoprints and the table is then printed again, which is harmless. + +## Triage (session) + +| Finding | Disposition | +|---|---| +| pkgdown Cache desc "downloaded once" | Fixed: same wording as README | +| `cd_fetch`/`cd_derive` under "Building the published data" | Confirmed (only a comment in `backfill_edh_all.py:207` names `cd_derive`); split into "Publishing the catalog" and "Downloading from the Copernicus Climate Data Store" | +| "cd's variables follow bc_climate_anomaly" | Fixed: "core climate variables" | +| `citation("cd")` lists NGE as organization, CFF as author | Accepted: `inst/CITATION` pattern shared with link; cross-repo rule in soul#426 territory | +| NOTICE: example_climate.tif not cd's ERA5-Land; BC data unattributed | Fixed: example_climate.tif removed from the ERA5-Land list; FWA + ecoregions attributed under OGL-BC (licences read from the BC Data Catalogue API). GNS towns and DRA highways are "Access Only", and bc_climate_anomaly has no licence: filed #151 | From 14af396d6b10a0533d0545d2595972dc38f2d4ba Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:50:25 -0700 Subject: [PATCH 08/13] code-check round 2: NOTICE names each OGL file; FWCP boundary to #151 (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- NOTICE.md | 5 +- planning/active/progress.md | 1 + planning/active/review-round2.md | 79 ++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 planning/active/review-round2.md diff --git a/NOTICE.md b/NOTICE.md index d5f19ac..277ac79 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -15,6 +15,9 @@ This repository redistributes modified ERA5-Land data, under CC BY 4.0, in: - `inst/extdata/example_daily/` (daily air temperature, 2002) - `inst/vignette-data/` (the precomputed series and rasters the vignettes read) -It also redistributes, in `inst/extdata/example_aoi_*.gpkg` and `inst/extdata/context_*.gpkg`, watershed groups, lakes, rivers and streams from the BC Freshwater Atlas and ecoregions from the Ecoregion Ecosystem Classification of British Columbia, under the [Open Government Licence – British Columbia](https://www2.gov.bc.ca/gov/content/data/policy-standards/open-data/open-government-licence-bc). +It also redistributes data from the BC Freshwater Atlas and the Ecoregion Ecosystem Classification of British Columbia, under the [Open Government Licence – British Columbia](https://www2.gov.bc.ca/gov/content/data/policy-standards/open-data/open-government-licence-bc), in: + +- `inst/extdata/example_aoi_kootenay_lake.gpkg`, `example_aoi_kotl.gpkg` and `example_aoi_northern_bc.gpkg` (watershed groups and watersheds) +- `inst/extdata/context_fwcp_peace.gpkg`, `context_kootenay_lake.gpkg` and `context_northern_bc.gpkg` (every layer except `towns` and `highways`) > Contains information licensed under the Open Government Licence – British Columbia. diff --git a/planning/active/progress.md b/planning/active/progress.md index d9a664e..0e90a9b 100644 --- a/planning/active/progress.md +++ b/planning/active/progress.md @@ -11,3 +11,4 @@ - Phase 3: DESCRIPTION Title/Description and README tagline in step; cffr call passes authors_roles (local cff_create shows New Graph Environment Ltd. as second author); GitHub About set to the tagline (was: "Climate departure analysis from ERA5-Land reanalysis. Producer pipeline publishes monthly-refreshed COGs + STAC catalog for BC; ..."). - Phase 4: `_pkgdown.yml` reference grouped in six sections (variables/periods/seasons split out of "Read the data" for clarity; `starts_with("cd_cache_")`); `check_pkgdown()` clean; home and reference index built to scratch, figure copied to `reference/figures/`, page screenshot reviewed. - code-check round 1 (spawned 07:34 UTC): 5 findings, 4 fixed, 1 accepted; filed #150 (anomaly axis label) and #151 (bundled data licences). Tests: FAIL 0 | PASS 768 (6 pre-existing warnings in cd_plot_comparison). +- code-check round 2 (spawned 07:44 UTC): 1 finding, inside round 1's NOTICE fix; fixed by naming files; #151 extended. Enumerated all 18 bundled data files against NOTICE (table in review-round2.md). diff --git a/planning/active/review-round2.md b/planning/active/review-round2.md new file mode 100644 index 0000000..86d2351 --- /dev/null +++ b/planning/active/review-round2.md @@ -0,0 +1,79 @@ +# Code-check round 2: branch 142-readme-add-daily-point-temperatures-and (vs main @ 59a5122) + +Reviewer read every changed file in full (README.md, NOTICE.md, DESCRIPTION, man/cd-package.Rd, _pkgdown.yml, data-raw/readme_figure.R, both workflow diffs), viewed the figure, and read soul's readme.md. It checked round 1's four fixes against the code and data. The bundled gpkgs were inspected from copies in the scratchpad: layers and row counts read with sqlite3, provenance traced through data-raw/. The vignette rds files were read with readRDS and hold no sf geometry. BC Data Catalogue licences were read from the CKAN API. All 14 external links in README.md and NOTICE.md answer 200. Nothing in the repo was written except this file. + +## Findings + +- **[false-claim / licence gap, low]** `NOTICE.md:18`: "It also redistributes, in `inst/extdata/example_aoi_*.gpkg` and `inst/extdata/context_*.gpkg`, watershed groups, lakes, rivers and streams from the BC Freshwater Atlas and ecoregions …, under the Open Government Licence – British Columbia." The glob `example_aoi_*.gpkg` matches `example_aoi_fwcp_peace.gpkg`. That file holds neither Freshwater Atlas nor ecoregion data. It is the Fish & Wildlife Compensation Program's Peace Region boundary, read from a local file (`data-raw/example_aoi_fwcp_peace.R`: `~/Projects/gis/sern_peace_fwcp_2023/fwcp_peace_region.geojson`), with no recorded origin or licence. Round 1's fix 4 brought this file under the OGL-BC sentence by glob, so it now reads as OGL-BC data. The other three `example_aoi_*` files are derived from FWA (watershed groups via bcdata/fwapg), which checks out. Suggested fix: add `example_aoi_fwcp_peace.gpkg` to cd#151 beside example_climate.tif, towns and highways. Optionally name the three FWA AOI files in NOTICE rather than globbing. (`example_aoi.gpkg` falls outside the glob, which is correct: it is a plain bbox.) + +No other defects. Round 1's fixes 1–3 are correct as written (verdicts below). + +## Round 1 fixes reviewed + +1. `_pkgdown.yml` Cache desc, "Files are cached after the first read and downloaded again only when they are republished": true. `cd_cache_fetch()` downloads again only on a refresh, or when the ETag differs (size when there is no ETag). With revalidation off, or when the HEAD fails, it serves the local copy. "Only when" is a necessary condition, and the code honours it. The wording matches README.md:52. One edge, pre-existing and outside the diff: the cache key is `rlang::hash(href)`, so an rlang release that changed the hash would re-download unchanged files. Not flagged. +2. "Publishing the catalog" (cd_aggregate, cd_cog_write, cd_stac_catalog, cd_s3_push): each is called by `scripts/pipeline_stage3_edh.R` / `pipeline_update_edh.R`, the scheduled workflow's entry points. True. "Downloading from the Copernicus Climate Data Store" (cd_fetch: CDS monthly means plus daily stats; cd_derive: from cd_fetch's GRIBs): true. "The published catalog is not built this way": true, since neither is called in scripts/ (only a comment in backfill_edh_all.py names cd_derive). +3. README "cd's core climate variables and its ecoregion and watershed framing follow bcgov/bc_climate_anomaly": true. Its app.R names tmean, tmax, tmin, prcp, vpd, rh and soil_moisture, has no snow variable, and mentions watershed 19 times and ecoregion/ecoprovince 25 times. +4. NOTICE redistribution lists: `inst/extdata/example_daily/` comes from cd's own daily cube (`data-raw/example_daily.R`), 2002, so true. `inst/vignette-data/` holds 3 rds files of series and tables (no geometry) and 3 tifs of departures and normals from cd's catalog, so true. The OGL-BC paragraph: FWA Watershed Groups, Lakes, Rivers and Stream Network and the Ecoregion Ecosystem Classification are all "Open Government Licence - British Columbia" in the BC Data Catalogue API, so true for those layers. The `bc` outline in context_northern_bc.gpkg is a union of FWA watershed groups, so it is covered. The attribution sentence is the OGL-BC wording. The one exception is the finding above. Towns and highways are cd#151 (accepted). + +## Claims enumerated (verdict) + +README.md +- Tagline: same text as the GitHub About (`gh repo view`) and consistent with the DESCRIPTION Title. True. +- Opening, "air temperature, precipitation, humidity, soil moisture and snow, by season and year since 1950 … whatever reference period … the trend and how much it has moved": true (variables registry, `cd_baseline(baseline_years=)`, `cd_trend`, Total Change). +- "public catalog that needs no account": true (anonymous https S3). +- "daily air temperature at any point in the province": true (`cd_extract_daily`, cube on the 121 × 261 BC grid). +- "baseline and trend steps take any annual series, such as streamflow or stream temperature": true (`?cd_anomaly` contract; wet feeds them). +- Figure: alt text and caption match the image (1950–2025 bars; red `>= 0`, blue below; dashed trend from about −0.35 to about 1.53 ≈ 1.9; trend since 1951 = `trend_start = 1951`). The opaque white background comes from `png(bg = "white")`. Made by the committed `data-raw/readme_figure.R`. True. +- Install: pak line, a pin placeholder, and a NEWS link (200). "Also needs sf, Kendall and zyp": true. `cd_trend` calls `check_installed(c("Kendall","zyp"))` and the example calls `sf::st_read`. Nothing else in the example needs a Suggests package. +- Example: signatures match (`cd_extract(catalog, aoi, variables, periods)`, `cd_baseline(x, baseline_years)`, `cd_anomaly(x, baseline)`, `cd_trend(x, trend_start)`, `cd_summary(trend)`). The code is identical to the script block. The output was accepted. +- "Files are cached … downloaded again only when they are republished": true (see fix 1). +- "Extracted rows record which commit of cd built each file": true (`cd_sha` from the file's `CD_SHA` tag). +- Learn more: the three titles match `vignettes/*.Rmd` titles, the URLs answer 200, and the descriptions are consistent with the vignettes. True. +- Ecosystem: wet's role is word-for-word as in wet's README and About. cd's row matches wet's README row for cd. "cd computes the departures from wet's yearly station values" is the same sentence wet's README uses. True. +- Data and methods: ERA5-Land by ECMWF for C3S, read from EDH, is true of the producer. CC BY 4.0 and "modified Copernicus … information" are true. Mann-Kendall / Theil-Sen via Kendall and zyp is true. The bc_climate_anomaly sentence is true (fix 3). +- Citation `citation("cd")`: works. The NGE role gap was accepted. +- License: MIT © NGE, and the LICENSE.md and NOTICE.md links exist. The ERA5-Land CC BY 4.0 line is true. example_climate.tif is cd#151, accepted. + +NOTICE.md +- ERA5-Land licence, attribution wording and Muñoz-Sabater 2021 reference (ESSD 13, 4349–4383; the DOI resolves): true. +- "reads from EDH, aggregates and derives (…), publishes to s3://stac-era5-land": true of the published data. +- Redistributed data: see fix 4 and the finding. + +DESCRIPTION / man/cd-package.Rd +- Title and Description: each clause is true. The Rd matches DESCRIPTION. + +_pkgdown.yml +- All 25 NAMESPACE exports are indexed, each exactly once (the `starts_with("cd_cache_")` selector covers 4). +- "Read the data", "Departures and trends", Cache, Publishing and CDS descriptions: true (above). + +Workflows +- `pkgdown.yaml`: "NOTICE" added to the allowlist. Correct, since NOTICE.md renders to NOTICE.html. +- `update-citation-cff.yaml`: `authors_roles = c("aut","cre","cph")` is what readme.md §9 prescribes. + +data-raw/readme_figure.R +- Loads the checkout (`load_all`). `system.file()` resolves to the source inst/ under pkgload, and the PNG is opaque. No defects. + +## Triage (session) + +Finding confirmed (`data-raw/example_aoi_fwcp_peace.R:3,12` reads a local geojson); it sits inside round 1's fix 4, so the loop now ends only on an enumeration. Fix: NOTICE names each OGL file instead of a glob; `example_aoi_fwcp_peace.gpkg` added to #151. + +### Enumeration: every bundled data file (18) against NOTICE + +| File | Source (data-raw) | Licence | In NOTICE | +|---|---|---|---| +| extdata/context_fwcp_peace.gpkg | FWA lakes/rivers/streams/wsgs, ecoregions (OGL); towns GNS, highways DRA (Access Only) | OGL + #151 | yes, minus towns/highways | +| extdata/context_kootenay_lake.gpkg | same layers | OGL + #151 | yes, minus towns/highways | +| extdata/context_northern_bc.gpkg | FWA rivers/lakes, `bc` = union of FWA wsgs; towns GNS | OGL + #151 | yes, minus towns | +| extdata/example_aoi_fwcp_peace.gpkg | local FWCP boundary geojson | unknown | no — #151 | +| extdata/example_aoi_kootenay_lake.gpkg | bcdata FWA watershed groups | OGL | yes | +| extdata/example_aoi_kotl.gpkg | bcdata 51f20b1a (FWA watershed groups) | OGL | yes | +| extdata/example_aoi_northern_bc.gpkg | FWA watershed groups + stream network (fwapg) | OGL | yes | +| extdata/example_aoi.gpkg | hand-made bbox | none (own) | n/a | +| extdata/example_catalog.json | STAC metadata for example_climate.tif | none (own) | n/a | +| extdata/example_climate.tif | bc_climate_anomaly NetCDF | unknown | no — #151 | +| extdata/example_daily/{tmean,tmax,tmin}_daily_2002.tif (3) | cd daily cube (ERA5-Land) | CC BY 4.0 | yes | +| extdata/peace_wsg_ecoregion_commentary.csv | overlap % computed from bundled wsgs × ecoregions, plus authored text | own, derived from OGL | covered by OGL statement | +| vignette-data/*.tif (3) | cd catalog (ERA5-Land) | CC BY 4.0 | yes | +| vignette-data/*.rds (3) | cd extracts (ERA5-Land) + AOI names/areas from FWA/ecoregions | CC BY 4.0 + OGL | yes | + +Every file is either named in NOTICE under a verified licence, own work, or in #151. Nothing listed in NOTICE carries data outside its stated licence. From ac98da0076afd43aad90c0749c6a105d727151ff Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:56:33 -0700 Subject: [PATCH 09/13] code-check round 3: NOTICE by source, not by file (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- NOTICE.md | 20 ++++---- planning/active/progress.md | 1 + planning/active/review-round3.md | 79 ++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 planning/active/review-round3.md diff --git a/NOTICE.md b/NOTICE.md index 277ac79..e4a2067 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -10,14 +10,16 @@ cd reads ERA5-Land from the [DestinE Earth Data Hub](https://earthdatahub.destin ## Redistributed data -This repository redistributes modified ERA5-Land data, under CC BY 4.0, in: - -- `inst/extdata/example_daily/` (daily air temperature, 2002) -- `inst/vignette-data/` (the precomputed series and rasters the vignettes read) - -It also redistributes data from the BC Freshwater Atlas and the Ecoregion Ecosystem Classification of British Columbia, under the [Open Government Licence – British Columbia](https://www2.gov.bc.ca/gov/content/data/policy-standards/open-data/open-government-licence-bc), in: - -- `inst/extdata/example_aoi_kootenay_lake.gpkg`, `example_aoi_kotl.gpkg` and `example_aoi_northern_bc.gpkg` (watershed groups and watersheds) -- `inst/extdata/context_fwcp_peace.gpkg`, `context_kootenay_lake.gpkg` and `context_northern_bc.gpkg` (every layer except `towns` and `highways`) +The example and vignette data in `inst/` are built from these sources (scripts in `data-raw/`): + +| Source | Licence | +|---|---| +| ERA5-Land, as processed by cd | CC BY 4.0 (above) | +| BC Freshwater Atlas: watershed groups, lakes, rivers, streams | [Open Government Licence – British Columbia](https://www2.gov.bc.ca/gov/content/data/policy-standards/open-data/open-government-licence-bc) | +| Ecoregion Ecosystem Classification of British Columbia | Open Government Licence – British Columbia | +| BC Geographical Names (town points) | Not yet confirmed ([#151](https://github.com/NewGraphEnvironment/cd/issues/151)) | +| Digital Road Atlas (highways) | Not yet confirmed ([#151](https://github.com/NewGraphEnvironment/cd/issues/151)) | +| Fish & Wildlife Compensation Program Peace Region boundary, and the Peace layers clipped or masked to it | Not yet confirmed ([#151](https://github.com/NewGraphEnvironment/cd/issues/151)) | +| `bcgov/bc_climate_anomaly` (`inst/extdata/example_climate.tif`) | Not yet confirmed ([#151](https://github.com/NewGraphEnvironment/cd/issues/151)) | > Contains information licensed under the Open Government Licence – British Columbia. diff --git a/planning/active/progress.md b/planning/active/progress.md index 0e90a9b..9d38cb9 100644 --- a/planning/active/progress.md +++ b/planning/active/progress.md @@ -12,3 +12,4 @@ - Phase 4: `_pkgdown.yml` reference grouped in six sections (variables/periods/seasons split out of "Read the data" for clarity; `starts_with("cd_cache_")`); `check_pkgdown()` clean; home and reference index built to scratch, figure copied to `reference/figures/`, page screenshot reviewed. - code-check round 1 (spawned 07:34 UTC): 5 findings, 4 fixed, 1 accepted; filed #150 (anomaly axis label) and #151 (bundled data licences). Tests: FAIL 0 | PASS 768 (6 pre-existing warnings in cd_plot_comparison). - code-check round 2 (spawned 07:44 UTC): 1 finding, inside round 1's NOTICE fix; fixed by naming files; #151 extended. Enumerated all 18 bundled data files against NOTICE (table in review-round2.md). +- code-check round 3 (spawned 07:50 UTC): mechanism named (a label standing for its members); 2 findings, both from the per-file NOTICE; NOTICE rewritten by source; terminal enumeration of 7 external sources in review-round3.md. diff --git a/planning/active/review-round3.md b/planning/active/review-round3.md new file mode 100644 index 0000000..8060638 --- /dev/null +++ b/planning/active/review-round3.md @@ -0,0 +1,79 @@ +# Code-check round 3: branch 142-readme-add-daily-point-temperatures-and (vs main @ 59a5122) + +The reviewer read README.md, NOTICE.md, DESCRIPTION, _pkgdown.yml, data-raw/readme_figure.R, the diffs to man/cd-package.Rd and both workflows, and viewed the figure. Every gpkg was inspected from a copy in the scratchpad (layers, columns and row counts via sqlite3). Each bundled file was traced to its `data-raw/` script. The vignette rds files were read with readRDS. The live daily cube was read over /vsicurl/ into a scratch R session. Nothing in the repo was written except this file. + +## Mechanism + +All five earlier findings share one assumption: **a label or a category (a glob, a group heading, a familiar member) was taken to stand for its members, and nothing checked the members.** "downloaded once" described the usual cache path. A "Building the published data" heading took in a function the pipeline never calls. "cd's variables" was written from the core seven. A NOTICE line about "cd's ERA5-Land product" took in a file from another source. `example_aoi_*.gpkg` matched by name and not by content. + +Round 2's fix applied the same assumption one level down. It treated **the FWCP boundary as one file**, `example_aoi_fwcp_peace.gpkg`, and moved that file to #151. But the boundary is also geometry, and geometry flows into whatever is clipped or masked by it. The enumeration table follows each file's *source tables*, not the *geometry operations* applied to them. So any file whose content was cut by a boundary of a different licence is labelled with its source tables' licence alone. + +## Findings + +- **[false-claim, low] `NOTICE.md:21`**: "`inst/extdata/context_fwcp_peace.gpkg` … (every layer except `towns` and `highways`)" under OGL-BC. In that file, `rivers`, `streams` and `ecoregions` are **clipped to the FWCP Peace boundary**, the very boundary round 2 moved to #151 as of unknown licence: + - `data-raw/example_context_fwcp_peace.R:19` reads `example_aoi_fwcp_peace.gpkg`. + - `:62-70` builds rivers as `ST_Intersection(geom, )`. + - `:76-82` builds streams the same way. + - `:130-131` builds ecoregions as `st_intersection(ecoregions_bc, aoi_3005)`, and `area_km2` is the clipped area. + + The outer edges of those three layers *are* the FWCP boundary, so the file redistributes it inside layers NOTICE labels OGL-BC. `lakes` (bbox `ST_Intersects`, not clipped) and `wsgs` (selected by a code list, not clipped) are pure FWA. Downstream of the clipped ecoregions are `inst/extdata/peace_wsg_ecoregion_commentary.csv` (`data-raw/peace_wsg_ecoregion_commentary.R:23,32` intersects with that layer) and `inst/vignette-data/peace_fwcp.rds`. The boundary also reaches `inst/vignette-data/peace_fwcp_departure_tmean.tif`, which NOTICE lists only as modified ERA5-Land: it is `terra::mask(departure, aoi)` with `aoi` = the FWCP boundary (`data-raw/peace_fwcp_vignette_data.R:30-31,137`). #151 names only `example_aoi_fwcp_peace.gpkg`. + + Suggested fix: in NOTICE, list `context_fwcp_peace.gpkg` as `lakes` and `wsgs` only, or add "clipped to the FWCP Peace boundary (see #151)". Extend #151's FWCP bullet to the files that carry the boundary: the clipped layers in `context_fwcp_peace.gpkg`, the masked `peace_fwcp_departure_tmean.tif`, and the derived `peace_wsg_ecoregion_commentary.csv` and `peace_fwcp.rds`. + +- **[false-claim, low] `planning/active/review-round2.md` enumeration, and `NOTICE.md:16-22` coverage.** The table closes with "Every file is either named in NOTICE under a verified licence, own work, or in #151". Three rows contradict it: + - `peace_wsg_ecoregion_commentary.csv` reads "covered by OGL statement", but NOTICE's OGL list does not name it. + - `vignette-data/*.rds` reads "CC BY 4.0 + OGL / yes", but NOTICE names `inst/vignette-data/` only under ERA5-Land. `kootenay_lake.rds$wsg_eco_overlap` and the ecoregion `area_km2` values are computed from FWA and ecoregion geometry. + - `vignette-data/*.tif` reads CC BY only, but each is masked to an AOI. Two of those AOIs are FWA-derived (OGL) and one is FWCP (above). + + So NOTICE's "in:" lists omit OGL-derived content in the csv and in vignette-data. The closing OGL attribution sentence is present, so the practical gap is small. The table header's "(18)" is also wrong: its rows cover 20 data files (21 under `inst/` with `inst/CITATION`). All 20 have a row, so the population is complete. + +No other defects. + +## Where the mechanism reaches, checked place by place + +| Place | Claim about a set | Members checked | Verdict | +|---|---|---|---| +| NOTICE:3 | "cd's climate data are derived from ERA5-Land" | example_climate.tif is not | accepted (#151) | +| NOTICE:9 | derived variables list | registry: means/totals, vpd, rh, soil, snow metrics, daily | true | +| NOTICE:13 | example_daily/ = ERA5-Land daily 2002 | 3 tifs, `data-raw/example_daily.R` | true | +| NOTICE:14 | vignette-data = modified ERA5-Land | 3 tif (cd_crop of the catalog), 3 rds (no sf geometry; all classes read) | true, but they also carry OGL/FWCP-derived content (finding 2) | +| NOTICE:20 | 3 example_aoi files = watershed groups and watersheds | kootenay_lake = union of 4 FWA WSGs; kotl = FWA WSG (bcdc 51f20b1a); northern_bc = 3 WSGs + 2 Bulkley parts (FWA watershed at measure) | true | +| NOTICE:21 | context_* every layer except towns/highways | kootenay_lake: clipped by the FWA AOI, so OGL; northern_bc: rivers, lakes, `bc` from FWA; fwcp_peace: rivers/streams/ecoregions clipped by FWCP | **false for fwcp_peace** (finding 1) | +| README:9 | "air temperature, precipitation, humidity, soil moisture and snow … since 1950" | 15 variables; one contiguous span | true | +| README:9 | "daily air temperature at any point in the province" | live cube 2002 band 1, 20,000 random points in FWA-BC: 220 fall in no-data cells, 9 have no data in the 3×3 window (0.045%); `cd_extract_daily` documents the fallback and the NA warning | true in substance | +| README:9 / DESCRIPTION | baseline and trend steps take any annual series | `?cd_anomaly` contract | true | +| README:46 | "Files are cached after the first read" | `cd_extract(cache = TRUE)` and `cd_extract_daily(cache = TRUE)` defaults; `cd_cache_fetch` ETag | true | +| README:46 | "Extracted rows record which commit … built each file" | `cd_sha` from the file's `CD_SHA` tag in both extractors | true | +| README:73 | Mann-Kendall / Theil-Sen from Kendall and zyp | `R/cd_trend.R:74-75` | true | +| README:73 | core variables follow bc_climate_anomaly | R2 verified | true | +| README:81 | "The ERA5-Land data it ships and publishes are CC BY 4.0" | ERA5-derived files only | true | +| README fig/caption/alt | 1950–2025, red warmer / blue cooler, trend since 1951, ~1.9 | PNG viewed; slope 0.025 × 75 years | true | +| _pkgdown "Read the data" | series for an area, or daily at points | 5 functions | true | +| _pkgdown "Departures and trends" | "These take any annual series in cd's long format" | cd_summary takes a trend table, cd_anomaly takes a series plus a baseline | true as a chain reading; not flagged | +| _pkgdown Cache | revalidation wording | R2 verified | true | +| _pkgdown Publishing | the scheduled workflow uses these | cd_aggregate and cd_cog_write in stage3 and update; cd_stac_catalog; cd_s3_push (also pushes the daily cube via `_publish.R:274`) | true | +| _pkgdown CDS | not how the catalog is built | not called in scripts/ | true | +| DESCRIPTION / Rd | each clause | as above | true; the Rd matches | +| pkgdown.yaml allowlist | adds NOTICE | NOTICE.md renders to NOTICE.html | correct | +| update-citation-cff | `authors_roles =` | cffr 1.4.2 has the argument; the workflow installs current cffr | correct | +| Pin advice | `@vX.Y.Z` | tags are `v0.6.x` | true | + +## Triage (session) + +Both findings confirmed against `data-raw/example_context_fwcp_peace.R` and `peace_fwcp_vignette_data.R`. The per-file NOTICE kept gaining qualifiers (convention: consider dropping the claim), so NOTICE now makes no per-file claims: it names each **source** with its licence, and points unresolved ones to #151. #151's FWCP bullet widened to every file clipped or masked to the boundary. + +### Terminal enumeration: every external source read by `data-raw/` (7) + +From a grep of every `bcdc_query_geodata()`, `FROM `, `st_read()`, `rast()`, `cd_catalog()`/`cd_extract*()` call in `data-raw/example_*.R`, `*_vignette_data.R` and `peace_wsg_ecoregion_commentary.R` (the vignette and commentary scripts read only cd and the bundled gpkgs): + +| Source | Read by | NOTICE row | +|---|---|---| +| ERA5-Land (cd catalog, daily cube) | example_daily, *_vignette_data | CC BY 4.0 | +| FWA wsgs/lakes/rivers/streams (bcdata, fwapg) | example_aoi_*, example_context_* | OGL-BC | +| Ecoregions `d00389e0` | example_context_fwcp_peace, _kootenay_lake | OGL-BC | +| GNS geographical names | example_context_* | #151 | +| DRA `transport_line` | example_context_fwcp_peace, _kootenay_lake | #151 | +| FWCP boundary (local geojson) | example_aoi_fwcp_peace (+ files clipped/masked to it) | #151 | +| bc_climate_anomaly NetCDF | example_climate_tmean | #151 | + +7 of 7 sources have a NOTICE row. `example_aoi.gpkg` and `example_catalog.json` are hand-made. Loop ends on this enumeration. From 45591e46b84c71e1ac195bf061cd827dd7891339 Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:57:25 -0700 Subject: [PATCH 10/13] Archive PWF for #142 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- CLAUDE.md | 1 + .../README.md | 13 +++++++++++++ .../findings.md | 0 .../progress.md | 0 .../review-1.md | 0 .../review-round1.md | 0 .../review-round2.md | 0 .../review-round3.md | 0 .../task_plan.md | 14 +++++++------- 9 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 planning/archive/2026-10-issue-142-readme-convention-rewrite/README.md rename planning/{active => archive/2026-10-issue-142-readme-convention-rewrite}/findings.md (100%) rename planning/{active => archive/2026-10-issue-142-readme-convention-rewrite}/progress.md (100%) rename planning/{active => archive/2026-10-issue-142-readme-convention-rewrite}/review-1.md (100%) rename planning/{active => archive/2026-10-issue-142-readme-convention-rewrite}/review-round1.md (100%) rename planning/{active => archive/2026-10-issue-142-readme-convention-rewrite}/review-round2.md (100%) rename planning/{active => archive/2026-10-issue-142-readme-convention-rewrite}/review-round3.md (100%) rename planning/{active => archive/2026-10-issue-142-readme-convention-rewrite}/task_plan.md (91%) diff --git a/CLAUDE.md b/CLAUDE.md index 2451dfc..be71ce4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -133,6 +133,7 @@ Configurable via `cd_seasons()`. Default: standard meteorological (DJF, MAM, JJA - `scripts/rag_departure_framing_build.R` — ragnar store for departure framing - Naming: `rag__.R` (`noun_verb`, mirrors the `cd_*` function convention) - `data-raw/make_hexsticker.R` — hex sticker (reads from DESCRIPTION) +- `data-raw/readme_figure.R` — the README figure and the `cd_summary()` output pasted under its example, from one live run; its marked block is the README example verbatim, so re-run it and repaste when the catalog gains a year (#142) - `data-raw/example_*.R` — bundled AOIs + context geodata for vignettes ## Vignettes diff --git a/planning/archive/2026-10-issue-142-readme-convention-rewrite/README.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/README.md new file mode 100644 index 0000000..2d0a017 --- /dev/null +++ b/planning/archive/2026-10-issue-142-readme-convention-rewrite/README.md @@ -0,0 +1,13 @@ +## Outcome + +Rewrote cd's README to soul's `readme.md` convention at the user's direction (simple, plain language, a figure from committed code): a plain opening naming what cd measures and what restoration decision it informs, with daily point temperatures and any-series baselines as one clause each; a figure of the Kootenay Lake watershed group's annual temperature departure from a 1951–1980 baseline, built by `data-raw/readme_figure.R`; one example whose code is that script's marked block and whose output is pasted from the same run. The function table (with the internal `cd_stac_item()`), roadmap, caching section and data inventory came out; the VPD fix stays in NEWS. DESCRIPTION Title/Description, the README tagline and the GitHub About now say the same thing; the citation workflow passes `authors_roles` so New Graph Environment Ltd. becomes a CITATION.cff author; `_pkgdown.yml` groups the reference index in seven sections. Writing attribution for the ERA5-Land data the package ships produced `NOTICE.md`, and reviewing it surfaced bundled data with unconfirmed licences (#151). Learned: a per-file licence list kept failing review because a glob or category stood in for its members (rounds 1–3 each found one inside the previous fix); listing by source, with the unresolved ones pointed at an issue, ended it on an enumeration of the 7 external sources `data-raw/` reads. + +## Measurement + +README 962 → 626 words (`wc -w`, including the example's code and output). No forecast was set; the floor is the convention's fixed sections. Example result: Kootenay Lake (KOTL) annual mean temperature trend 0.025 °C/yr over 75 years (1951–2025), total change 1.9 °C. Review: plan review + 3 code-check rounds, 1 + 5 + 1 + 2 findings; filed #150 (anomaly axis label) and #151 (bundled data licences). + +## Evidence + +`planning/archive/2026-10-issue-142-*/review-*.md` + +Closed by: PR (see branch `142-readme-add-daily-point-temperatures-and`) diff --git a/planning/active/findings.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/findings.md similarity index 100% rename from planning/active/findings.md rename to planning/archive/2026-10-issue-142-readme-convention-rewrite/findings.md diff --git a/planning/active/progress.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/progress.md similarity index 100% rename from planning/active/progress.md rename to planning/archive/2026-10-issue-142-readme-convention-rewrite/progress.md diff --git a/planning/active/review-1.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/review-1.md similarity index 100% rename from planning/active/review-1.md rename to planning/archive/2026-10-issue-142-readme-convention-rewrite/review-1.md diff --git a/planning/active/review-round1.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round1.md similarity index 100% rename from planning/active/review-round1.md rename to planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round1.md diff --git a/planning/active/review-round2.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round2.md similarity index 100% rename from planning/active/review-round2.md rename to planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round2.md diff --git a/planning/active/review-round3.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round3.md similarity index 100% rename from planning/active/review-round3.md rename to planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round3.md diff --git a/planning/active/task_plan.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/task_plan.md similarity index 91% rename from planning/active/task_plan.md rename to planning/archive/2026-10-issue-142-readme-convention-rewrite/task_plan.md index 07ede5f..e59f2de 100644 --- a/planning/active/task_plan.md +++ b/planning/archive/2026-10-issue-142-readme-convention-rewrite/task_plan.md @@ -35,13 +35,13 @@ Scope set at the plan gate (2026-10-17): rewrite the README to soul's `readme.md ## Phase 5: Close out -- [ ] Edit #142's body: scope is the convention rewrite; VPD fix left to NEWS -- [ ] Mechanical checks: every function the README names is exported; every link resolves -- [ ] `/code-check branch` with every README/DESCRIPTION claim enumerated against code +- [x] Edit #142's body: scope is the convention rewrite; VPD fix left to NEWS +- [x] Mechanical checks: every function the README names is exported; every link resolves +- [x] `/code-check branch` with every README/DESCRIPTION claim enumerated against code ## Validation -- [ ] Tests pass -- [ ] `/code-check` clean (each commit, or once over the branch with `/code-check branch`) -- [ ] PWF checkboxes match landed work -- [ ] `/planning-archive` on completion +- [x] Tests pass +- [x] `/code-check` clean (each commit, or once over the branch with `/code-check branch`) +- [x] PWF checkboxes match landed work +- [x] `/planning-archive` on completion From e33a4649129b8e67cf9c3cfbd668509ba2d25ac3 Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 00:58:08 -0700 Subject: [PATCH 11/13] Archive README: closing PR ref (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- .../2026-10-issue-142-readme-convention-rewrite/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planning/archive/2026-10-issue-142-readme-convention-rewrite/README.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/README.md index 2d0a017..2b20f07 100644 --- a/planning/archive/2026-10-issue-142-readme-convention-rewrite/README.md +++ b/planning/archive/2026-10-issue-142-readme-convention-rewrite/README.md @@ -10,4 +10,4 @@ README 962 → 626 words (`wc -w`, including the example's code and output). No `planning/archive/2026-10-issue-142-*/review-*.md` -Closed by: PR (see branch `142-readme-add-daily-point-temperatures-and`) +Closed by: PR #152 From f6c4a21892e4069f7a07727396fd338dbc39df31 Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 01:51:33 -0700 Subject: [PATCH 12/13] Tagline, Title and About: the 12-word one-liner the user chose (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- DESCRIPTION | 2 +- README.md | 2 +- man/cd-package.Rd | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5c03ea6..c2ee2d6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: cd -Title: Climate Departure for British Columbia from ERA5-Land Reanalysis +Title: How far any BC watershed's climate has shifted from your chosen baseline Version: 0.6.12 Date: 2026-10-17 Authors@R: c( diff --git a/README.md b/README.md index 5f7c136..c28e50b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) -> Climate departure for British Columbia: how far the climate of any area has moved from any baseline, from ERA5-Land reanalysis +> How far any BC watershed's climate has shifted from your chosen baseline cd measures how much the climate of a watershed or any other area in British Columbia has changed: air temperature, precipitation, humidity, soil moisture and snow, by season and year since 1950, compared with whatever reference period you choose, with the trend and how much it has moved. It reads ERA5-Land reanalysis from a public catalog that needs no account, so restoration can be planned and monitored against the climate a site has now rather than the one it had. It also gives daily air temperature at any point in the province, for stream-temperature models and degree-day work, and its baseline and trend steps take any annual series, such as streamflow or stream temperature. diff --git a/man/cd-package.Rd b/man/cd-package.Rd index c8e67a1..c5f7fa1 100644 --- a/man/cd-package.Rd +++ b/man/cd-package.Rd @@ -4,7 +4,7 @@ \name{cd-package} \alias{cd} \alias{cd-package} -\title{cd: Climate Departure for British Columbia from ERA5-Land Reanalysis} +\title{cd: How far any BC watershed's climate has shifted from your chosen baseline} \description{ \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} From 681a80d6620512067692602c3cd8d0407ac6ef71 Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sat, 17 Oct 2026 01:54:58 -0700 Subject: [PATCH 13/13] Review of the tagline commit (#142) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GignjoKpZADXywTf6pAMgj --- .../review-round4.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round4.md diff --git a/planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round4.md b/planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round4.md new file mode 100644 index 0000000..4a03ea2 --- /dev/null +++ b/planning/archive/2026-10-issue-142-readme-convention-rewrite/review-round4.md @@ -0,0 +1,40 @@ +# Review round 4 — HEAD f6c4a21 (Title / tagline / About, #142) + +Reviewed 2026-10-17. Scope: is "How far any BC watershed's climate has shifted from your +chosen baseline" true against the code, and does the new Title break anything mechanical. + +## Findings + +**[Low]** DESCRIPTION:2, README.md:7 — "any BC watershed" does not hold for a watershed on a +small offshore island. `cd_crop()` (R/cd_crop.R:36) is `terra::crop(snap = "out", mask = TRUE)` +and `cd_extract()` (R/cd_extract.R:77) takes `global(mean, na.rm = TRUE)`; ERA5-Land is +land-only, so 10,835 of the 31,581 cells in the live `tmean_annual` COG are NA. Measured: +a 0.01° polygon inland near Squamish (-123.01, 49.61) returns 1.76 °C for 1950 (sub-cell +inland watersheds are fine, the touched cell counts), while a 0.02° polygon on Triangle +Island (-129.08, 50.86) returns `NaN`, silently, with no warning. Not new to this commit: +the DESCRIPTION `Description` and the README opening already say "any area", so the Title +inherits the same overstatement. Whether a watershed in the Freshwater Atlas sits entirely +on sea cells was not checked. Acceptable as is for a one-line tagline; noted so the +silent `NaN` is a known limit, not a surprise. + +## Checked and clean + +- `cd_extract()`: takes any `sf`/`sfc`/`SpatVector` polygon, reprojects if the CRS differs + (R/cd_crop.R:30-35). True for any polygon on land. +- `cd_baseline()`: any `baseline_years` vector; years outside the data warn, not error + (R/cd_baseline.R:31-40). "your chosen baseline" holds. +- Extent: grid 47.95–60.05 N, 140.05–113.95 W covers all of BC. "climate" = temperature, + precipitation, humidity (rh, vpd), soil moisture and snow, per `cd_variables()`. +- `read.dcf("DESCRIPTION")` parses; `tools:::.check_package_description()` returns no + problems; `tools::checkRd("man/cd-package.Rd")` is silent (an apostrophe is not special in Rd). +- `inst/CITATION` evaluates to title "cd: How far any BC watershed's climate has shifted + from your chosen baseline"; BibTeX output well formed. +- cffr (the workflow's own recipe, written to a scratch path): YAML writes `''` for the + apostrophe, `yaml::read_yaml()` round-trips it, `cff_validate()` TRUE for both `title` + and `preferred-citation$title`. The committed CITATION.cff still carries an older title + ("Climate Departure Analysis…"), which predates this commit and the workflow regenerates + on the next push to main touching DESCRIPTION. +- pkgdown home (built to a scratch destination): `… • cd` and `og:title` + carry the new Title, apostrophe intact inside double-quoted attributes. +- GitHub About matches the Title exactly (`gh repo view`). +- No stale copy of the previous Title outside `planning/archive/` and `docs/`.