From 5d72d2cb79f4e11662b52732dc72d490f59eccb3 Mon Sep 17 00:00:00 2001 From: Eliot McIntire Date: Thu, 15 Oct 2026 14:41:45 -0700 Subject: [PATCH 1/2] Fire raster holds the latest fire at or before dataYear (needs LandR#275) Co-Authored-By: Claude Opus 5.5 --- Biomass_borealDataPrep.R | 5 +++-- NEWS.md | 3 +++ R/estimateCoverModel.R | 2 +- tests/testthat/test-dataYear.R | 23 +++++++++++++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Biomass_borealDataPrep.R b/Biomass_borealDataPrep.R index 3a47253..a974971 100644 --- a/Biomass_borealDataPrep.R +++ b/Biomass_borealDataPrep.R @@ -23,7 +23,7 @@ defineModule(sim, list( "archive", "assertthat", "cli", "crayon", "curl", "data.table", "dplyr", "ggplot2", "httr", "httr2", "lme4", "merTools", "plyr", "qs2", "rasterVis", "Require", "sf", "terra", "tidyterra", "googledrive", "quickPlot", "reproducible (>= 2.1.0)", "SpaDES.core (>= 2.1.0)", "SpaDES.tools (>= 2.0.0)", - "PredictiveEcology/LandR@development (>= 1.2.0.9046)", # makeAndCleanInitialCohortData(minSpeciesEcoregionShare), LandR#264 + "PredictiveEcology/LandR@development (>= 1.2.0.9057)", # makeAndCleanInitialCohortData(minSpeciesEcoregionShare), LandR#264; prepInputsFireYear(latestYear) "PredictiveEcology/pemisc@development", "PredictiveEcology/SpaDES.project@development (>= 0.0.8.9026)" ), @@ -1812,7 +1812,8 @@ Save <- function(sim) { studyArea = sa, rasterToMatch = sim$rasterToMatch_biomassParam, url = extractURL("firePerimeters"), - fireField = "YEAR" + fireField = "YEAR", + latestYear = P(sim)$dataYear ## the latest fire at or before dataYear, not the most recent ) |> Cache( omitArgs = "destinationPath", diff --git a/NEWS.md b/NEWS.md index 0454c1d..ab454c4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,9 @@ Known issues: = 1.2.0.9057). The biomass re-estimate inside fire perimeters uses the same raster, so it now covers those pixels too. A `firePerimeters` input supplied by another module is used as given. +* `estimateCoverModel()` uses `data.table::copy()` instead of an unprefixed `Copy()`, which was not found when the module's tests run without `reproducible` attached. + * Without Biomass_speciesData, a study area with no tree species no longer stops in `.inputObjects` ("unable to find an inherited method for function `cover`"): the `NULL` species layers from SCANFI now pass through to the no-species branch. * `quickPlot` is now in `reqdPkgs` (`dev()`, `clearPlot()` are used). * The spin-up that re-estimates biomass of young cohorts inside fire perimeters now starts each cohort at `initialB` (new parameter, default 10 g/m2, must match Biomass_core's; `NA` starts at `maxANPP`) instead of 0, so growthcurve-1 species such as spruce are no longer held to the 1 g/m2/yr growth floor while pioneers take the pixel. The sanity check on the result now allows 1.2 x the age-based limit, capped at the raw biomass map maximum, so fast-growing pioneers no longer stop runs. diff --git a/R/estimateCoverModel.R b/R/estimateCoverModel.R index 99de924..5ee5c3c 100644 --- a/R/estimateCoverModel.R +++ b/R/estimateCoverModel.R @@ -12,7 +12,7 @@ ## nothing was fitted) and `cohortDataShort` (with a `pred` column when probabilities were set). estimateCoverModel <- function(cohortDataShort, fitCover) { cdsWh <- cohortDataShort$coverPres == cohortDataShort$coverNum - cds <- Copy(cohortDataShort) + cds <- data.table::copy(cohortDataShort) cds <- cds[!cdsWh] if (!NROW(cds)) { diff --git a/tests/testthat/test-dataYear.R b/tests/testthat/test-dataYear.R index 6b27b4f..f38514e 100644 --- a/tests/testthat/test-dataYear.R +++ b/tests/testthat/test-dataYear.R @@ -36,3 +36,26 @@ test_that("the SCANFI species-layer call passes dataYear, not year", { expect_true("dataYear" %in% argNames) expect_false("year" %in% argNames) }) + +## `prepInputsFireYear()` rasterizes with fun = max, so each pixel holds its most recent fire of any +## year; replaceAgeInFires() then skipped a pixel that burned in 1980 and 2015 for dataYear 1990. +## The data year must reach the fire raster as `latestYear`. Static, so it needs no download. +test_that("the fire-year call passes dataYear as latestYear", { + skip_if_not_installed("LandR") + expect_true("latestYear" %in% names(formals(LandR::prepInputsFireYear))) + + code <- parse(file.path(moduleRoot, paste0(moduleName, ".R"))) + found <- list() + walk <- function(x) { + if (is.call(x)) { + if (identical(x[[1]], as.name("prepInputsFireYear"))) { + found[[length(found) + 1L]] <<- x + } + lapply(as.list(x), walk) + } + invisible(NULL) + } + lapply(as.list(code), walk) + expect_length(found, 1L) + expect_identical(found[[1L]]$latestYear, quote(P(sim)$dataYear)) +}) From 2c3a8c4741f26385bf300e452506fe174e94e4dc Mon Sep 17 00:00:00 2001 From: Eliot McIntire Date: Thu, 15 Oct 2026 14:42:26 -0700 Subject: [PATCH 2/2] Revert estimateCoverModel Copy change (out of scope) Co-Authored-By: Claude Opus 5.5 --- NEWS.md | 1 - R/estimateCoverModel.R | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index ab454c4..cac230e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,7 +3,6 @@ Known issues: = 1.2.0.9057). The biomass re-estimate inside fire perimeters uses the same raster, so it now covers those pixels too. A `firePerimeters` input supplied by another module is used as given. -* `estimateCoverModel()` uses `data.table::copy()` instead of an unprefixed `Copy()`, which was not found when the module's tests run without `reproducible` attached. * Without Biomass_speciesData, a study area with no tree species no longer stops in `.inputObjects` ("unable to find an inherited method for function `cover`"): the `NULL` species layers from SCANFI now pass through to the no-species branch. * `quickPlot` is now in `reqdPkgs` (`dev()`, `clearPlot()` are used). diff --git a/R/estimateCoverModel.R b/R/estimateCoverModel.R index 5ee5c3c..99de924 100644 --- a/R/estimateCoverModel.R +++ b/R/estimateCoverModel.R @@ -12,7 +12,7 @@ ## nothing was fitted) and `cohortDataShort` (with a `pred` column when probabilities were set). estimateCoverModel <- function(cohortDataShort, fitCover) { cdsWh <- cohortDataShort$coverPres == cohortDataShort$coverNum - cds <- data.table::copy(cohortDataShort) + cds <- Copy(cohortDataShort) cds <- cds[!cdsWh] if (!NROW(cds)) {