From 8d4b1a031ecfa63c0997f1552d40ef43eacfc5c6 Mon Sep 17 00:00:00 2001 From: Gustav Delius Date: Wed, 8 Jul 2026 11:52:24 +0100 Subject: [PATCH 1/2] Improve reference index and clarify w_max terminology in docs Documentation-only changes to make the website more useful and to make the maximum-size terminology consistent. Reference index (pkgdown/_pkgdown.yml): - Add an "Overview: the mizer workflow" section at the top framing the page as a five-stage pipeline (create -> calibrate -> tune dynamics -> project -> analyse) with links to the key function in each stage. - Disambiguate related function families: calibrate...()/match...() and ...Biomass/...Number, and the plot...() variants (...2, ...Relative, ...ObservedVsModel). - Map mizer's mortality-rate names onto standard fisheries notation (M2, F, Z), noting getResourceMort() is resource mortality, not fish M. w_max message wording (R/setReproduction.R, R/manipulate_species.R): - Error messages that called w_max a species' "maximum size" now describe it as the upper size-grid boundary, consistent with w_max being purely computational (biological max size is w_inf, reproduction cut-off is w_repro_max). Tests updated to match. Model-setup wrappers (R/newSingleSpeciesParams.R, R/wrapper_functions.R): - Document why newSingleSpeciesParams(), newTraitParams() and newCommunityParams() set w_max = w_repro_max: without diffusion no individual grows beyond w_repro_max, so no grid headroom is needed. To be revisited when the constructors gain a diffusion parameter (#339). No behaviour changes. docs/ site regeneration is intentionally excluded; rebuild on merge as usual. Co-Authored-By: Claude Opus 4.8 --- NEWS.md | 23 ++++++++ R/manipulate_species.R | 2 +- R/newSingleSpeciesParams.R | 12 +++- R/setReproduction.R | 11 ++-- R/wrapper_functions.R | 22 ++++++- man/newCommunityParams.Rd | 7 +++ man/newSingleSpeciesParams.Rd | 9 ++- man/newTraitParams.Rd | 9 ++- pkgdown/_pkgdown.yml | 75 ++++++++++++++++++++++-- tests/testthat/test-manipulate_species.R | 2 +- tests/testthat/test-setReproduction.R | 6 +- 11 files changed, 161 insertions(+), 17 deletions(-) diff --git a/NEWS.md b/NEWS.md index e5c2f1fc6..e78af95a6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,28 @@ # mizer 3.1.0.9000 (development version) +- The reference index on the website now opens with an "Overview: the mizer + workflow" section that frames the whole page as a five-stage pipeline (create → + calibrate → tune dynamics → project → analyse) with links to the key function + in each stage, so readers can see how the sections below fit together. + +- The reference index on the website now explains the differences between related + families of functions. It disambiguates the `calibrate...()`/`match...()` and + `...Biomass`/`...Number` calibration functions and the `plot...()` variants + (`...2`, `...Relative`, `...ObservedVsModel`), and maps mizer's mortality-rate + names onto the standard fisheries notation (*M2*, *F*, *Z*). + +- Error messages that referred to `w_max` as a species' "maximum size" now + correctly describe it as the upper size-grid boundary, consistent with `w_max` + being a purely computational parameter (the biological maximum size is `w_inf` + and the reproduction cut-off is `w_repro_max`). + +- `newSingleSpeciesParams()`, `newTraitParams()` and `newCommunityParams()` now + document why they place the size-grid boundary at the maximum size + (`w_max = w_repro_max`): because they do not yet set up stochastic growth by + diffusion, no individual grows beyond `w_repro_max`, so no headroom above it is + needed. This will be revisited when the constructors gain a diffusion parameter + (#339). + - Assigning to `resource_params()` no longer balances the resource. It now only rebuilds the size-dependent rate (`rr_pp`) and capacity (`cc_pp`) arrays from the scalars, leaving any manually set (frozen) arrays untouched, exactly as diff --git a/R/manipulate_species.R b/R/manipulate_species.R index eba52503c..b1ade3dc8 100644 --- a/R/manipulate_species.R +++ b/R/manipulate_species.R @@ -637,7 +637,7 @@ adjustSizeGrid.MizerParams <- function(params, } too_small_species <- params@species_params$species[sp_sel & params@species_params$w_max < new_min_w] if (length(too_small_species) > 0) { - stop("The following species have their maximum size w_max smaller than the new minimum size: ", + stop("The following species have their upper size-grid boundary w_max smaller than the new minimum size: ", paste(too_small_species, collapse = ", ")) } too_large_species <- params@species_params$species[sp_sel & params@species_params$w_min > new_max_w] diff --git a/R/newSingleSpeciesParams.R b/R/newSingleSpeciesParams.R index 547f85081..c3d45ad7c 100644 --- a/R/newSingleSpeciesParams.R +++ b/R/newSingleSpeciesParams.R @@ -32,7 +32,14 @@ #' size, and `erepro` is then adjusted so the initial state satisfies the egg #' boundary condition. #' -#' The diffusion rate is set to `0` +#' The diffusion rate is set to `0`. Because growth is therefore deterministic, +#' no individual grows beyond `w_repro_max`, the size at which all available +#' energy is invested into reproduction. The upper boundary of the size grid is +#' therefore placed at that size, so that `w_max = w_repro_max`, instead of the +#' `1.5 * w_repro_max` headroom that [newMultispeciesParams()] leaves to +#' accommodate the stochastic growth produced by diffusion. This choice will be +#' revisited once these constructors gain a diffusion parameter, see +#' \url{https://github.com/sizespectrum/mizer/issues/339}. #' #' @param species_name A string with a name for the species. Will be used in #' plot legends. @@ -154,6 +161,9 @@ newSingleSpeciesParams <- species_params <- data.frame( species = species_name, w_min = w_min, + # Without diffusion nothing grows beyond w_repro_max (= w_inf here), so + # the computational grid boundary w_max is placed there too, with no + # headroom above the maximum size. To be revisited with diffusion (#339). w_inf = w_max, w_max = w_max, w_mat = w_mat, diff --git a/R/setReproduction.R b/R/setReproduction.R index 0cf4a6936..8575d9bcb 100644 --- a/R/setReproduction.R +++ b/R/setReproduction.R @@ -184,18 +184,21 @@ setReproduction.MizerParams <- function(params, maturity = NULL, comment(params@psi) <- NULL } - # Check maximum sizes + # Check that the upper size-grid boundary w_max is set. This is the + # computational boundary of the size grid, not the size at which + # reproduction is maximal (that is `w_repro_max`, used below). if (!("w_max" %in% colnames(species_params))) { - stop("The maximum sizes of the species must be specified in the w_max ", + stop("The upper size-grid boundary must be specified in the `w_max` ", "column of the species parameter data frame.") } missing <- is.na(species_params$w_max) if (any(missing)) { - stop("The following species are missing data for their maximum size w_max: ", + stop("The following species are missing their upper size-grid boundary `w_max`: ", toString(species_params$species[missing])) } if (any(species_params$w_max <= species_params$w_min)) { - stop("Some of the maximum sizes are smaller than the egg sizes.") + stop("Some of the upper size-grid boundaries (`w_max`) are smaller ", + "than the egg sizes.") } # # Round maximum sizes to nearest grid point # for (i in seq_along(species_params$w_max)) { diff --git a/R/wrapper_functions.R b/R/wrapper_functions.R index 76442e898..2a61e11b5 100644 --- a/R/wrapper_functions.R +++ b/R/wrapper_functions.R @@ -25,6 +25,13 @@ #' `knife_edge_size`, which determines the size at which species are #' selected. #' +#' Because this constructor does not yet set up stochastic growth by diffusion, +#' the size grid is not extended beyond the community's maximum size `max_w` +#' (so that `w_max = w_repro_max`), rather than leaving the headroom that +#' [newMultispeciesParams()] uses to accommodate stochastic growth. This will be +#' revisited once these constructors gain a diffusion parameter, see +#' \url{https://github.com/sizespectrum/mizer/issues/339}. +#' #' The resulting `MizerParams` object can be projected forward using #' \code{project()} like any other `MizerParams` object. When projecting #' the community model it may be necessary to keep a small time step size @@ -111,6 +118,9 @@ newCommunityParams <- function(max_w = 1e6, # Make the species data.frame species_params <- data.frame( species = "Community", + # Without diffusion nothing grows beyond the maximum size, so the + # computational grid boundary w_max is placed there too, with no + # headroom above it. To be revisited with diffusion (#339). w_inf = w_max, w_max = w_max, f0 = f0, @@ -200,7 +210,14 @@ newCommunityParams <- function(max_w = 1e6, #' The search rate coefficient `gamma` is calculated using the expected #' feeding level, `f0`. #' -#' The diffusion rate is set to `0`. +#' The diffusion rate is set to `0`. Because growth is therefore deterministic, +#' no individual grows beyond `w_repro_max`, the size at which all available +#' energy is invested into reproduction. The upper boundary of the size grid is +#' therefore placed at that size, so that `w_max = w_repro_max`, instead of the +#' `1.5 * w_repro_max` headroom that [newMultispeciesParams()] leaves to +#' accommodate the stochastic growth produced by diffusion. This choice will be +#' revisited once these constructors gain a diffusion parameter, see +#' \url{https://github.com/sizespectrum/mizer/issues/339}. #' #' The option of including fishing is given, but the steady state may loose its #' natural stability if too much fishing is included. In such a case the user @@ -484,6 +501,9 @@ newTraitParams <- function(no_sp = 11, species_params <- data.frame( species = as.factor(1:no_sp), w_min = w_min, + # Without diffusion nothing grows beyond w_repro_max (= w_inf here), so + # the computational grid boundary w_max is placed there too, with no + # headroom above the maximum size. To be revisited with diffusion (#339). w_inf = w_max, w_max = w_max, w_mat = w_mat, diff --git a/man/newCommunityParams.Rd b/man/newCommunityParams.Rd index 5a984b17f..7c060542f 100644 --- a/man/newCommunityParams.Rd +++ b/man/newCommunityParams.Rd @@ -118,6 +118,13 @@ Fishing selectivity is modelled as a knife-edge function with one parameter, \code{knife_edge_size}, which determines the size at which species are selected. +Because this constructor does not yet set up stochastic growth by diffusion, +the size grid is not extended beyond the community's maximum size \code{max_w} +(so that \code{w_max = w_repro_max}), rather than leaving the headroom that +\code{\link[=newMultispeciesParams]{newMultispeciesParams()}} uses to accommodate stochastic growth. This will be +revisited once these constructors gain a diffusion parameter, see +\url{https://github.com/sizespectrum/mizer/issues/339}. + The resulting \code{MizerParams} object can be projected forward using \code{project()} like any other \code{MizerParams} object. When projecting the community model it may be necessary to keep a small time step size diff --git a/man/newSingleSpeciesParams.Rd b/man/newSingleSpeciesParams.Rd index 34480f3bf..ac480a047 100644 --- a/man/newSingleSpeciesParams.Rd +++ b/man/newSingleSpeciesParams.Rd @@ -138,7 +138,14 @@ maximum abundance is half the background abundance at the corresponding size, and \code{erepro} is then adjusted so the initial state satisfies the egg boundary condition. -The diffusion rate is set to \code{0} +The diffusion rate is set to \code{0}. Because growth is therefore deterministic, +no individual grows beyond \code{w_repro_max}, the size at which all available +energy is invested into reproduction. The upper boundary of the size grid is +therefore placed at that size, so that \code{w_max = w_repro_max}, instead of the +\code{1.5 * w_repro_max} headroom that \code{\link[=newMultispeciesParams]{newMultispeciesParams()}} leaves to +accommodate the stochastic growth produced by diffusion. This choice will be +revisited once these constructors gain a diffusion parameter, see +\url{https://github.com/sizespectrum/mizer/issues/339}. } \examples{ params <- newSingleSpeciesParams() diff --git a/man/newTraitParams.Rd b/man/newTraitParams.Rd index 12f548ff0..05abc7d80 100644 --- a/man/newTraitParams.Rd +++ b/man/newTraitParams.Rd @@ -196,7 +196,14 @@ initial condition that is close to steady state. The search rate coefficient \code{gamma} is calculated using the expected feeding level, \code{f0}. -The diffusion rate is set to \code{0}. +The diffusion rate is set to \code{0}. Because growth is therefore deterministic, +no individual grows beyond \code{w_repro_max}, the size at which all available +energy is invested into reproduction. The upper boundary of the size grid is +therefore placed at that size, so that \code{w_max = w_repro_max}, instead of the +\code{1.5 * w_repro_max} headroom that \code{\link[=newMultispeciesParams]{newMultispeciesParams()}} leaves to +accommodate the stochastic growth produced by diffusion. This choice will be +revisited once these constructors gain a diffusion parameter, see +\url{https://github.com/sizespectrum/mizer/issues/339}. The option of including fishing is given, but the steady state may loose its natural stability if too much fishing is included. In such a case the user diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 401659a5f..604afcd84 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -97,6 +97,38 @@ articles: - plotting reference: +- title: "Overview: the mizer workflow" + description: | + mizer builds and simulates dynamic, size-structured models of fish + communities. Building and using a model follows five stages, and the + reference sections below are organised in roughly this order: + + 1. **Create** a model from species and gear parameters, starting with + [`newMultispeciesParams()`](newMultispeciesParams.html) or one of the + simpler [`newCommunityParams()`](newCommunityParams.html), + [`newTraitParams()`](newTraitParams.html) and + [`newSingleSpeciesParams()`](newSingleSpeciesParams.html). + 2. **Calibrate the steady state** so that growth, biomass and yield match + observations, with [`matchGrowth()`](matchGrowth.html), + [`calibrateBiomass()`](calibrateBiomass.html), + [`matchBiomasses()`](matchBiomasses.html) and [`steady()`](steady.html). + 3. **Tune the dynamics** so the model responds realistically to + perturbations away from the steady state, with + [`setBevertonHolt()`](setBevertonHolt.html) and + [`setResource()`](setResource.html). + 4. **Project** the model forward in time under a fishing scenario, with + [`project()`](project.html). + 5. **Analyse and plot** the results, with summary functions such as + [`getBiomass()`](getBiomass.html) and [`getYield()`](getYield.html) and + plots such as [`plotBiomass()`](plotBiomass.html) and + [`plotSpectra()`](plotSpectra.html). + + New users should start with the + [Get started guide](https://sizespectrum.org/mizer/articles/mizer.html) and + the topic [cheat sheets](https://sizespectrum.org/mizer/articles/index.html), + or open the package overview page below. + contents: + - mizer-package - title: Creating a new model description: Mizer allows the easy set-up of four different types of models, of increasing level of complexity. See @@ -135,11 +167,23 @@ reference: - use_predation_diffusion - second_order_w - title: Steady state tuning - description: The first task after creating a multi-species model is to tune + description: > + The first task after creating a multi-species model is to tune the model parameters so that in its steady state the model reproduces average observed growth rates, abundances and fisheries yields. The [Model setup and calibration cheatsheet](https://sizespectrum.org/mizer/articles/cheatsheet-model-setup-and-calibration.html) walks through this calibration workflow. + + + Two families of functions rescale abundances to match observations. + The `calibrate...()` functions apply a single overall scaling factor to + the whole model, whereas the `match...()` functions rescale each species + individually. Within each family, the `...Biomass` variant matches + observed biomasses (a `biomass_observed` column in the species parameters) + while the `...Number` variant matches observed numbers + (a `number_observed` column). Use `matchGrowth()` to match observed + von Bertalanffy growth, and the `plot...ObservedVsModel()` functions to + see how well the current model reproduces the observations. contents: - steady - steadyNewton @@ -197,8 +241,21 @@ reference: - getFeedingLevel - getCriticalFeedingLevel - title: Calculating rates - description: Calculate instantaneous ecological rates from a `MizerParams` + description: > + Calculate instantaneous ecological rates from a `MizerParams` object, such as encounter rate, predation mortality, or somatic growth rate. + + + For readers coming from single-species fisheries assessment, mizer's fish + mortality rates map onto the standard notation as follows: predation + mortality `getPredMort()` is the multi-species analogue of *M2*, external + mortality `getExtMort()` is the residual natural mortality not resolved by + the model, fishing mortality `getFMort()` is *F*, and the total mortality + `getMort()` is *Z*, the sum of all of these. The older names `getM2()` and + `getZ()` are retained as deprecated aliases for `getPredMort()` and + `getMort()`. Note that `getResourceMort()` is different in kind: it is the + predation mortality imposed by fish *on the background resource* spectrum, + not a component of fish mortality (its deprecated alias is `getM2Background()`). contents: - getRates - has_concept("rate functions") @@ -209,10 +266,21 @@ reference: - indicator_functions - has_concept("functions for calculating indicators") - title: Plotting results - description: Visualise size spectra, biomass and yield trajectories, growth + description: > + Visualise size spectra, biomass and yield trajectories, growth curves, and comparisons of model output with observations. See the [Analysis and plotting cheatsheet](https://sizespectrum.org/mizer/articles/cheatsheet-analysis-and-plotting.html) for a quick reference. + + + Several plots come in related variants. A plain plot such as + `plotSpectra()` shows a single model or simulation. The `...2` variants + (`plotSpectra2()`, `plotCDF2()`) overlay **two** objects in one figure so + you can compare them, and the `...Relative` variants + (`plotSpectraRelative()`) show the ratio between two objects. The + `...ObservedVsModel` functions compare model output against observed data. + Most `plot...()` functions have a matching `get...()` accessor that returns + the underlying data frame if you would rather build the plot yourself. contents: - plotting_functions - plot @@ -312,7 +380,6 @@ reference: description: The S4 and S3 classes used by mizer, together with functions for constructing, inspecting, comparing, and validating them. contents: - - mizer-package - MizerParams-class - summary.MizerParams - str.MizerParams diff --git a/tests/testthat/test-manipulate_species.R b/tests/testthat/test-manipulate_species.R index cc5386114..65bbcbf8f 100644 --- a/tests/testthat/test-manipulate_species.R +++ b/tests/testthat/test-manipulate_species.R @@ -537,7 +537,7 @@ test_that("adjustSizeGrid works for expansion and truncation", { "new_min_w must be smaller than new_max_w.") # Species w_max smaller than new_min_w expect_error(adjustSizeGrid(NS_params_small, new_min_w = 100), - "The following species have their maximum size w_max smaller than the new minimum size: Sprat") + "The following species have their upper size-grid boundary w_max smaller than the new minimum size: Sprat") # Species w_min larger than new_max_w expect_error(adjustSizeGrid(NS_params_small, new_min_w = 0.00001, new_max_w = 0.0001), "The following species have their minimum size w_min larger than the new maximum size:") diff --git a/tests/testthat/test-setReproduction.R b/tests/testthat/test-setReproduction.R index 2d5fc361b..0fa740c50 100644 --- a/tests/testthat/test-setReproduction.R +++ b/tests/testthat/test-setReproduction.R @@ -33,13 +33,13 @@ test_that("setReproduction checks arguments", { params@species_params$w_max[[2]] <- NA sp_name <- params@species_params$species[2] expect_error(setReproduction(params), - paste0("The following species are missing data for their maximum size w_max: ", sp_name)) + paste0("The following species are missing their upper size-grid boundary `w_max`: ", sp_name)) params@species_params$w_max[[2]] <- 1e-5 expect_error(setReproduction(params), - "Some of the maximum sizes are smaller than the egg sizes.") + "Some of the upper size-grid boundaries \\(`w_max`\\) are smaller than the egg sizes.") params@species_params$w_max <- NULL expect_error(setReproduction(params), - "The maximum sizes of the species must be specified in the w_max column of the species parameter data frame.") + "The upper size-grid boundary must be specified in the `w_max` column of the species parameter data frame.") params <- NS_params_small params@species_params$w_mat[[3]] <- NA From b3c065e4dbecb97511faf877dd6c85f8a29dae52 Mon Sep 17 00:00:00 2001 From: Gustav Delius Date: Wed, 15 Jul 2026 10:52:49 +0100 Subject: [PATCH 2/2] Small correction to NEWS entry --- NEWS.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index e78af95a6..487d2468d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -13,8 +13,7 @@ - Error messages that referred to `w_max` as a species' "maximum size" now correctly describe it as the upper size-grid boundary, consistent with `w_max` - being a purely computational parameter (the biological maximum size is `w_inf` - and the reproduction cut-off is `w_repro_max`). + being a purely computational parameter. - `newSingleSpeciesParams()`, `newTraitParams()` and `newCommunityParams()` now document why they place the size-grid boundary at the maximum size