diff --git a/NEWS.md b/NEWS.md index a31d58c..3d13b5f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # fireSense_dataPrepFit (development version) +- Fixed: `init` is declared in the new `.neverCache` parameter, so it is never cached, even when `.useCache` (the module's or `.globals`) lists it. It reads the spread-fit ledger on Google Drive, which is not part of the event's cache key, so a cached `init` replayed an old "fit exists" or "no fit yet" answer. Needs SpaDES.core >= 3.2.1.9037. + - Changed: the defaults are the values production already passes. `spreadIntercept` is `TRUE` (spread formula `~ 1 + ...`, free intercept with centred covariates) and `areaMultiplier` is `function(size) 10 * fireSenseUtils::multiplier(size)`, 10 times the old default, built to be `identical()` to what runs pass so their caches are unchanged. Fits that relied on the old defaults now get the intercept and the 10x buffers. - Fixed: the structure of the spread model is decided at fit time, for the fit's decision year, and a hindcast's run of this module makes the same decision. Whether treed wetland is a spread covariate (`minCovariateProp`), the land-cover shares used to estimate fuel classes, and the dominant/secondary fuel classes are decided on the data year the last fire year uses (`fitDecisionYear()` = `max(fireYears)`; `fireSenseUtils::dataYearFor()`: the data year closest to and not after a year, the rule `yearGroups()` assigns vegetation to fire years with, now also used by `yearGroups()`), read from the per-year lists (`rstLCCs`, `flammableRTMs`, `cohortDatas`, ...), not from `sim$rstLCC_RTM`/`sim$flammableRTM` or the last element of the lists. `fireSense_dataPrepPredict` overwrites those two with the year it predicts, so a hindcast (e.g. 1985) rebuilt the spread formula on 1985 land cover and could add a `treedWetland_agb` term the fit did not have. Results of a fit are unchanged. Needs fireSenseUtils >= 0.2.3.9093 (`dataYearFor()`, `dataYearElement()`). diff --git a/fireSense_dataPrepFit.R b/fireSense_dataPrepFit.R index 6d1e8f3..c9ee656 100644 --- a/fireSense_dataPrepFit.R +++ b/fireSense_dataPrepFit.R @@ -21,7 +21,7 @@ defineModule(sim, list( "FOR-CAST/fireregimetools@main (>= 0.1.0.9008)", "ggplot2", "parallel", "purrr", "raster", "sf", "sp", "PredictiveEcology/LandR@development (>= 1.2.0.9015)", - "PredictiveEcology/SpaDES.core@development (>= 2.0.2.9006)", + "PredictiveEcology/SpaDES.core@development (>= 3.2.1.9037)", "PredictiveEcology/SpaDES.project@development", "PredictiveEcology/SpaDES.tools@development (>= 2.1.1.9000)", "terra"), @@ -144,6 +144,9 @@ defineModule(sim, list( defineParameter(".useCache", "logical", FALSE, NA, NA, paste("Should this entire module be run with caching activated? This is intended", "for data-type modules, where stochasticity and time are not relevant")), + defineParameter(".neverCache", "character", "init", NA, NA, + paste("Events that are never cached, whatever `.useCache` says (read by SpaDES.core, 3.2.1.9037 or later):", + "`init` asks Google Drive whether the spread-fit ledger already has parameters for this study area, and a cached `init` replays an older answer.")), defineParameter(".useCacheArgs", "list", list(dataPrepBuild = list(.cacheExtra = quote(list( LandR::.compareRas, LandR::asInt, LandR::defineFlammable, LandR::isInt, diff --git a/tests/testthat/test-declaredIsUsed.R b/tests/testthat/test-declaredIsUsed.R index dc3156c..9936f30 100644 --- a/tests/testthat/test-declaredIsUsed.R +++ b/tests/testthat/test-declaredIsUsed.R @@ -1,6 +1,6 @@ ## Metadata that the code never uses misleads a project into setting or supplying it. Six such ## entries were removed at 1.2.0.9007, with the non-xgboost ignition formula (it needed an object, -## `ignitionClimate`, that was never defined). `.useCache` and `.useCacheArgs` are read by SpaDES.core. +## `ignitionClimate`, that was never defined). `.useCache`, `.useCacheArgs` and `.neverCache` are read by SpaDES.core. test_that("every declared parameter and input is read, and every declared output is assigned", { md <- SpaDES.core::moduleMetadata(module = moduleName, path = modulePath) files <- c(file.path(moduleRoot, paste0(moduleName, ".R")), @@ -9,7 +9,7 @@ test_that("every declared parameter and input is read, and every declared output code <- code[!grepl("defineParameter\\(|expectsInput\\(|createsOutput\\(|^\\s*#", code)] used <- function(patterns) vapply(patterns, function(p) any(grepl(p, code, perl = TRUE)), logical(1)) - params <- setdiff(md$parameters$paramName, c(".useCache", ".useCacheArgs")) + params <- setdiff(md$parameters$paramName, c(".useCache", ".useCacheArgs", ".neverCache")) notRead <- params[!used(paste0("(\\$|\")", gsub(".", "\\.", params, fixed = TRUE), "\\b"))] expect_identical(notRead, character(0)) diff --git a/tests/testthat/test-metadata.R b/tests/testthat/test-metadata.R index 865b9d9..8bba2f4 100644 --- a/tests/testthat/test-metadata.R +++ b/tests/testthat/test-metadata.R @@ -95,7 +95,7 @@ test_that("parameters are the expected names", { md <- SpaDES.core::moduleMetadata(module = moduleName, path = modulePath) expect_identical( sort(md$parameters$paramName), - sort(c(".studyAreaName", + sort(c(".neverCache", ".studyAreaName", ".useCache", ".useCacheArgs", "areaMultiplier", "bufferForFireRaster", "cutoffForYoungAge", "dataYears", "escapeSizeHa", "estimateFuelClasses", "fireYears", "flammabilityThreshold", "forestedLCC", "fuelClassCol", "fuelCovariates", "heldOutFold", "igAggFactor", diff --git a/tests/testthat/test-neverCache.R b/tests/testthat/test-neverCache.R new file mode 100644 index 0000000..68ffdc6 --- /dev/null +++ b/tests/testthat/test-neverCache.R @@ -0,0 +1,14 @@ +## `.neverCache` (read by SpaDES.core >= 3.2.1.9037) wins over every form of `.useCache`, including a +## `.globals$.useCache` that lists the event. `init` asks Google Drive whether the spread-fit ledger already has parameters for this study area, and a cached `init` replays an older answer. +test_that(".neverCache is declared and SpaDES.core refuses to cache those events whatever .useCache says", { + md <- SpaDES.core::moduleMetadata(module = moduleName, path = modulePath) + declared <- md$parameters$default[[which(md$parameters$paramName == ".neverCache")]] + expect_setequal(declared, c("init")) + eventIsCached <- utils::getFromNamespace(".eventIsCached", "SpaDES.core") + for (useCache in list(c(".inputObjects", declared), TRUE)) { + for (ev in declared) + expect_false(eventIsCached(list(.useCache = useCache, .neverCache = declared), ev)$cache) + } + ## and the helper still caches what `.useCache` names that `.neverCache` does not list + expect_true(eventIsCached(list(.useCache = ".inputObjects", .neverCache = declared), ".inputObjects")$cache) +})