Dynamic Multi-Species Size Spectrum Modelling
Overview
A set of classes and methods to set up and run multi-species, trait based and community size spectrum ecological models, focused on the marine environment.
The headline change is one you should not be able to feel: MizerParams and
MizerSim are now ordinary S3 objects rather than S4 objects. Slot access with
@ still works and models saved by earlier versions still load, but extension
packages need a version built for this release. The release also changes what
getSteadyResidual() measures and takes components registered with
setComponent() out of the criterion by which mizer decides whether a model is
at steady state. It adds getMeanLength(), reconcileSpeciesParams(), and
accessors for extra mortality and encounter rates (other_mort(),
other_encounter()), and it fixes bugs in the species parameter setters, in the
defaults for gamma and f0, in scaleModel(), in validSim() and in
summary() of an array.
For an overview see the
Show all changes in 3.4.0Hide the rest of the changes in 3.4.0
on the mizer blog.
S4 to S3 conversion
MizerParamsandMizerSimhave been converted from S4 classes to pure S3 classes based on named lists. Backwards compatibility for@and@<-slot access is fully preserved via S3@operator methods, while standard list operations ($,[[]],names()) now work directly on model objects. Legacy S4 objects saved with earlier versions of mizer are automatically upgraded to S3 lists on access.- Extension packages now chain using standard S3 class vectors (e.g.
c("mizerShelf", "MizerParams")), completely replacing dynamic S4 marker class generation, runtimesetClass()calls, and search-path attachment. saveParams()andsaveSim()now store the object's complete S3 class vector instead of stripping extension classes before serialisation.readParams()andreadSim()still repair the class on legacy files through their normal validation, but no longer need a separate coercion step.- The
NS_paramsandNS_simobjects shipped with mizer are now stored as S3 objects, soisS4(NS_params)isFALSEand they no longer go through the legacy-object conversion on first use.
Steady state and calibration
getSteadyResidual()now reports, for each size class, its contribution to the relative rate of change of its species' biomass, in 1/year, so thatrowSums(getSteadyResidual(params))is the drift(dB_i/dt) / B_ithatisSteady(), thesummary()line andproject(check_steady = TRUE)judge a model by. The array therefore says *where* a model is unsteady in the same currency that mizer uses to decide *whether* it is. Pass the experimentalmeasure = "per_capita"for the previous default,(dN/dt)/N(#572, #589).getSteadyResidual()reports every size class, including the ones holding no fish, so only a species with no biomass at all comes back asNA. Under the new default measure a class holding a trace contributes a trace, which is what makes a threshold unnecessary. Withmeasure = "per_capita"theNAs are where they always were (#570, #572).- Components registered with
setComponent()are no longer folded into the biomass drift thatisSteady(), thesummary()line,project(check_steady = TRUE), the"convergence"attribute andgetStability()judge a model by. Every function that finds a steady state holds the components fixed, so a criterion that included them was one those functions could not satisfy. Components are now reported separately, throughattr(getSteadyResidual(params), "other")and on their own lines insummary(); a model can therefore beisSteady()while a component of it is drifting, andprojectUntilSettled()is what settles it (#589). - Mizer now names the species, resource or component responsible for a model's drift, instead of reporting that "a biomass" is changing and sending the user to look at which species are moving (#589).
- Fixed: a size class holding a negligible density could stop
projectUntilSettled()from ever converging (#570). Above the size where growth stops, the density decays exponentially without ever reaching zero, anddistanceSSLogN()counted every class with a positive density, so an infinitesimal trace of 3e-92 g contributed almost the whole distance at every check. It gains abiomass_share_cutoffargument, defaulting to1e-8: a size class counts only if it holds at least that share of its species' biomass. Nothing changes for a model without such a trace, so existingdistance_tolvalues keep their meaning, and what decides whether a state is a fixed point is unchanged and still integrates over every size class (#570, #574). - Fixed:
projectUntilSettled()now says so when a run that stopped att_maxnonetheless reached a fixed point.converged = FALSEbesideattractor = "fixed_point"is correct — they answer different questions — but read as a contradiction (#570). - Fixed:
tuneSteadyState()no longer reports that it could not rebalance the resource capacity when the resource dynamics isresource_constant(). A constant resource hands back the abundance it was given, so there is nothing to rebalance. The report is meant for a custom resource dynamics with nobalance_<dynamics>()function, but it fired on every model that switches the built-in resource off, which includes every model of an extension package that supplies its own resources (#591). - Fixed: the
residualentry of the"convergence"attribute, and theresidualcolumn of aMizerScanfilled from it, were documented as the largest per-capita rate of change. They hold the largest relative rate of *biomass* change, which is the quantityresidual_tolis a tolerance on and the numberrowSums(getSteadyResidual(params))gives (#572). - Fixed:
scaleModel()wrote the rescaledR_maxandgammastraight into the species parameter table, bypassing the record of the values the user has supplied, so the next recalculation of the species parameters silently undid the rescaling. They are now recorded as given species parameters, asmatchGrowth()already did.calibrateBiomass(),calibrateNumber(),matchBiomasses()andmatchNumbers()inherit the fix (#599, #602).
Species parameters
- Mizer now reports the length-weight defaults
a = 0.01andb = 3atinfo_level = 3when it fills them in, alongside the other defaults it reports. This matters because a length-based selectivity function converts the lengths ingear_params()to weights throughaandb, so a defaulted relationship silently puts the selectivity curve at the wrong weights. The defaults themselves are unchanged, andinfo_level = 0silences the report as it does the rest (#576). setFishing()additionally names any species whose gear selects on length while itsaorbwas defaulted. That is the case in which an invented weight-length relationship changes the dynamics rather than just a diagnostic, so the report is atinfo_level = 1and is shown even whencalc_selectivity()orsetFishing()is called on its own. Whether a gear selects on length is decided from the selectivity function's formals, so a customsel_functakingspecies_paramsis covered too (#576).- New
reconcileSpeciesParams()makes a model'sspecies_params()a fixed point of mizer's recalculation. Values written straight into thespecies_paramsslot are not recorded as given, so mizer used to undo them at the next recalculation without saying so. The function records every value that a recalculation would change — repeating until the parameters reproduce themselves, so that the parameters mizer derives from the hand-set ones are caught too — and leaves the model itself untouched.readParams()now calls it automatically, so a saved model whose species parameters had drifted out of step with its given species parameters keeps the values it holds (#604). - Fixed: a species parameter column can be removed by dropping it from the table you assign, with either setter (#578, #582). Mizer takes the column out of
given_species_params(), recalculates the parameters it knows how to calculate and removes the ones it does not, sospecies_params(params)$my_col <- NULLandgiven_species_params(params)$my_col <- NULLnow do what they look like they do. Previously the first silently restored the column from the given table and the second left it inspecies_params()reported as one mizer had calculated. Removing a column fromgiven_species_params()now also recalculates the parameter it handed back, which makes it the same instruction as setting that parameter toNA. This is what an extension package needs in order to withdraw a species parameter it added when the user switches the extension off. The removal is reported atinfo_level3. - Fixed: the defaults for
gammaandf0are no longer measured through the extension chain (#577, #584).get_gamma_default()measured the energy available to a species withgetEncounter(), so on an extension object any modification the extension makes to the encounter rate was folded into mizer's owngammaand re-applied on every rebuild: an extension that halves the search volume doubledgammaeach time the species parameters were touched, and one whose factor is zero turned the calculation into an error. Bothget_gamma_default()and its inverseget_f0_default()now measure withmizerEncounter(), so a rate function registered withsetRateFunction()no longer enters the calculation either. These defaults are a property of the species parameters, not of the model's dynamics. - Fixed: the defaults for
gammaandf0now also exclude external encounter and the functions registered throughother_encounter(), including a component'sencounter_fun(#586, #596). These additive contributions still affect the realised encounter and feeding level, but the defaults describe feeding on the reference power-law resource alone. Previouslyget_gamma_default()measured them where they were negligible whileget_f0_default()counted them at full scale, so the two were not inverses. When no defaultgammacan be calculated, the error now names the species concerned and reports the energy measured for them. - Fixed: an invalid
w_mat25is now reported as a missing value for which the default will be used, and anyl_mat25is cleared with it (#580, #583). Previously the rejected value was put straight back by the length-to-weight conversion, landing within rounding error ofw_mat, which passed thew_mat25 < w_matcheck and turned the maturity ogive into a step function. - Fixed: assigning a likely misspelling of a species parameter now produces one warning, when the column is introduced, rather than one per validation pass (#581, #583). The report also goes through the information-signal mechanism, so it is collected with mizer's other reports and
info_level = 0silences it along with everything else mizer says.
Extensions
- New accessors
other_mort()andother_encounter(), with their replacement forms, for the extra contributions to the mortality and encounter rates thatgetMort()andgetEncounter()sum into their results (#579, #585): ``r other_mort(params)[["starvation"]] <- "starvMort"`An extension that adds a term depending on the state of the model but carrying no state of its own can now register it this way, where previously the only route was to assign intoparams@other_mortdirectly, sincesetComponent()requires adynamics_funand aninitial_valuethat such a term has nothing to supply. Likeother_params(), the new accessors hide the entries belonging to a component created withsetComponent(), so assigning a whole list can no longer wipe them out. Encounter contributions now receive the current simulation time ast, as mortality contributions already did, andsetComponent()` refuses a component name that a free-standing contribution is already registered under. - The reference index now separates model-level extension functions from the
recordExtension()andcoerceToExtensionClass()infrastructure intended only for extension package authors. - Fixed:
validSim()passed the resource spectrum where the rate functions expect the list of other components, so diagnosing a failed simulation of a model with components created bysetComponent()failed with$ operator is invalid for atomic vectorsinstead of reporting which rates went non-finite (#601).
Time stepping
project()and the other functions taking amethodargument now accept"second_order"as an alias formethod = "tr_bdf2", matching the name of the spatial second-order optionsecond_order_w(). Aliases are resolved to the canonical name, sogetSimParams()still reports"tr_bdf2".method = "predictor_corrector"is now documented as superseded bymethod = "tr_bdf2". The two are second order at the same cost and treat the nonlinear rates identically, but the Crank-Nicolson corrector is only A-stable and rings at large time steps, where TR-BDF2 does not. It remains available for backwards compatibility and for comparison.
Summaries and plots
- New
getMeanLength()calculates the mean length of the community, the counterpart ofgetMeanWeight(), with which it shares a help page (#576). - Fixed:
summary()of a species-by-size array now covers the same sizes asplot()of the same array, namely each species' own range fromw_mintow_max(#575). The two described different arrays:summary(getEncounter(NS_params))gave Sprat a maximum encounter rate of 40000 g/year, the rate a 40 kg Sprat would have, against 240 g/year over the sizes a Sprat reaches. Because a rate usually grows with size, theMinandMaxcolumns were affected most. Bothsummary()methods with a size dimension takeall.sizes = TRUEfor the old behaviour. - Fixed:
summary()of an array now reportsNAfor a species with no values left, rather than the-Inf/Infand warning thatmin()andmax()of an empty selection give (#575). - Fixed:
plotYield(return_data = TRUE)once again returns only the three documented columnsYear,YieldandSpecies. In mizer 3.3.0 it also returned the internalLegendcolumn (#593, #594).
Documentation and skills
- A new
upgrade-extension-packageskill and guide walk extension package authors through migrating their packages to mizer 3.4.0. - The
upgrade-mizer-codeskill gained an **audit mode** and a **code-pattern index**, allowing maintainers to systematically audit and update an entire codebase for mizer 3.4.0 even when no errors or visible symptoms are present.
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-05
- NOTE12 OK, 1 NOTE2026-08-01
- OK13 OK2026-07-22
- NOTE12 OK, 1 NOTE2026-07-11
- OK13 OK2026-06-09
Show 4 earlier changesHide 4 earlier changes
- ERROR12 OK, 1 ERROR2026-06-08
- OK14 OK2026-04-22
- ERROR13 OK, 1 ERROR2026-04-18
- OK14 OK2026-03-10
Documentation
- Help pages
- 395 (145 internal)includes a package overview page
- Examples that run
- 56%88 run in a plain check · 69 only when donttest examples are enabled (R CMD check --as-cran) · 1 never run
- Exported functions with examples
- 62%
- Documented parameters
- 98%
- Return-value docs
- 99%
- Help pages citing references
- 1%
Downloads
Repository
- PRs merged (all time)
- 93%
- Median days to close, 50 most recently updated closed issues
- 1
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Forks over time
Releases over time
Issues over time
PRs over time
Commits over time
14 development-tooling and community-health practices detected across 9 families in the upstream repository
Checks run against github.com/sizespectrum/mizer on 2026-10-11.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-09-29
pkgdown site last built 2026-09-02
Show all practicesHide 5 practices
This repository shows signs of AI coding tools.
- Codexfirst seen 2025-07-13Named in .Rbuildignore: .codexNamed in .gitignore: .codexPull request it wrote: opened by a project member
- GitHub Copilotfirst seen 2025-11-16Pull request: opened by its own accountCommits: 50 by its own account · at least 12 crediting it in the message
- Claude Codefirst seen 2026-03-18Seen in the repository: .claude, .claude/skills, CLAUDE.mdNamed in .Rbuildignore: .claude, CLAUDE.mdNamed in .gitignore: .claude, .claude/skillsPull request it wrote: opened by a project memberCommits: at least 167 crediting it in the message
- Gemini CLIfirst seen on or before 2026-07-18Config: a file or ignore line, not recorded which
- Claude Opus 4.849 commits · Jun to Jul 2026
- Claude Opus 532 commits · Jul to Aug 2026
- Claude Sonnet 4.624 commits · Apr to Jun 2026
- Claude Fable 58 commits · Jun to Jul 2026
- Claude Sonnet 51 commit · Jul 2026
Some of these counts are a minimum, because the search stopped before the oldest commits.
Dependencies
Installing mizer adds 77 packages (43 with compiled code, 70 MB of source tarballs). Heaviest: stringi 11 MB, ggplot2 6.0 MB, data.table 5.7 MB.
Code & Tests
Datasets
People & History
Previously maintained by Finlay Scott (0.1 to 0.2).
Pick two releases to compare their code metrics.
- 3.4.0Latest2026-08-31 · current release · diff ↗ ·
removed 4 exports
clearExtensionChain, getRegisteredExtensions, registerExtension, registerExtensionsadded 6 exports
other_encounter<-, other_mort<-, getMeanLength, other_encounter, other_mort, reconcileSpeciesParams - 3.3.02026-08-24 · diff ↗ ·
removed 2 exports
calibrateYield, matchYieldsadded 26 exports
reproduction_level<-, MizerScan, bin_average_weight, default_info_level, encounter_kernel, findSteadyState, gaussian_mixture_pred_kernel, getDiscreteStability, getOscillationModeSim, getStability, getSteadyResidual, is.MizerScan, isSteady, knife_edge_length, plotYieldVsF, projectUntilSettled, reproduction_level, scanEffort, scanFishingMortality, scanModel, scanSpeciesParam, signal_info, signal_not_recalculated, sizeIntegral, tuneSteadyState, with_info_level - 3.2.1
- 3.2.02026-07-19 · diff ↗ ·
added 4 exports
adjustSizeGrid, is.gear_params, is.given_species_params, is.species_params - 3.1.02026-06-29 · diff ↗ ·
added 11 exports
second_order_w<-, ArrayResourceBySize, ArrayTimeByResourceBySize, apply_wlim, getFluxGradient, is.ArrayResourceBySize, is.ArrayTimeByResourceBySize, parsePlotLog, project_n_tr_bdf2, recordExtension, second_order_w - RR 4.6.0 released · 2026-04-24
- 3.0.02025-11-16 · diff ↗ ·
added 63 exports
ext_diffusion<-, use_predation_diffusion<-, ArraySpeciesBySize, ArrayTimeBySpecies, ArrayTimeBySpeciesBySize, addPlot, age_mat_vB, animate, clearExtensionChain, coerceToExtensionClass, expandSizeGrid, ext_diffusion, finalParams, getDiffusion, getFlux, getRegisteredExtensions, getRequiredRDD, getSimParams, getTrophicLevel, getTrophicLevelBySpecies, initialParams, is.ArraySpeciesBySize, is.ArrayTimeBySpecies, is.ArrayTimeBySpeciesBySize, markBackground, mizerDiffusion, plot2, plotCDF, plotCDF2, plotHover and 33 more - 2.5.4
- RR 4.5.0 released · 2025-04-11
- 2.5.3
- 2.5.2
- RR 4.4.0 released · 2024-04-24
- 2.5.12024-03-09 · diff ↗
- 2.5.02023-12-08 · diff ↗ ·
added 8 exports
ext_encounter<-, given_species_params<-, calculated_species_params, completeSpeciesParams, ext_encounter, getExtEncounter, given_species_params, setExtEncounter - unarchivedReturned to CRAN2023-04-26
- 2.4.12023-04-26 · diff ↗
Show 29 earlier eventsHide 29 earlier events
- archivedRemoved from CRAN2023-04-24issues were not corrected in time
- RR 4.3.0 released · 2023-04-21
- 2.4.02022-12-23 · diff ↗ ·
added 16 exports
interaction_matrix<-, resource_level<-, age_mat, balance_resource_logistic, balance_resource_semichemostat, calibrateNumber, defaults_edition, getResourceLevel, interaction_matrix, l2w, matchGrowth, matchNumbers, resource_level, resource_logistic, steadySingleSpecies, w2l - 2.3.12022-07-06 · diff ↗
- RR 4.2.0 released · 2022-04-22
- 2.3.0.12021-09-15 · diff ↗
- 2.3.02021-09-11 · diff ↗ ·
removed 1 export
retune_ereproadded 39 exports
catchability<-, ext_mort<-, initial_effort<-, intake_max<-, maturity<-, metab<-, pred_kernel<-, repro_prop<-, resource_capacity<-, resource_dynamics<-, resource_rate<-, search_vol<-, selectivity<-, calibrateBiomass, calibrateYield, catchability, ext_mort, getMetadata, initial_effort, intake_max, matchBiomasses, matchYields, maturity, metab, plotBiomassObservedVsModel, plotYieldObservedVsModel, plotlyBiomassObservedVsModel, plotlyYieldObservedVsModel, pred_kernel, readParams and 9 more - 2.2.1
- 2.2.02021-06-24 · diff ↗ ·
added 6 exports
addSpecies, animateSpectra, get_f0_default, newSingleSpeciesParams, removeSpecies, renameSpecies - RR 4.1.0 released · 2021-05-18
- 2.1.02021-03-21 · diff ↗ ·
removed 3 exports
resource_encounter, semichemostat, test_dynadded 6 exports
compareParams, constantEggRDI, customFunction, distanceMaxRelRDI, distanceSSLogN, projectToSteady - 2.0.42020-08-30 · diff ↗ ·
removed 1 export
validate_effort_vectoradded 7 exports
getRates, setBevertonHolt, validEffortVector, validGearParams, validParams, validSpeciesParams, valid_species_arg - 2.0.32020-07-28 · diff ↗
- 2.0.22020-06-08 · diff ↗ ·
removed 3 exports
effort, params, timesadded 7 exports
constant_other, getEffort, getParams, getTimes, project_simple, resource_encounter, semichemostat - 2.0.1
- RR 4.0.0 released · 2020-04-24
- 2.0.02020-04-04 · diff ↗ ·
removed 6 exports
addSpecies, display_frames, getBiomassFrame, getSSBFrame, setBackground, set_scaling_modeladded 125 exports
gear_params<-, initialN<-, initialNOther<-, initialNResource<-, resource_params<-, species_params<-, BevertonHoltRDD, N, NOther, NResource, RickerRDD, SheperdRDD, box_pred_kernel, constantRDD, default_pred_kernel_params, double_sigmoid_length, dw, dw_full, effort, emptyParams, finalN, finalNOther, finalNResource, gear_params, getCatchability, getColours, getComponent, getCriticalFeedingLevel, getDiet, getERepro and 95 more - RR 3.6.0 released · 2019-04-26
- 1.0.12019-01-27 · diff ↗
- 1.02018-05-02 · diff ↗ ·
added 8 exports
addSpecies, display_frames, getBiomassFrame, getSSBFrame, plotGrowthCurves, setBackground, set_scaling_model, steady - RR 3.5.0 released · 2018-04-23
- 0.42017-12-14 · diff ↗ ·
added 32 exports
MizerParams, MizerSim, getBiomass, getCommunitySlope, getEGrowth, getEReproAndGrowth, getESpawning, getFMort, getFMortGear, getFeedingLevel, getM2, getM2Background, getMeanMaxWeight, getMeanWeight, getN, getPhiPrey, getPredRate, getProportionOfLargeFish, getRDD, getRDI, getSSB, getYield, getYieldGear, getZ, plotBiomass, plotFMort, plotFeedingLevel, plotM2, plotSpectra, plotYield and 2 more - RR 3.4.0 released · 2017-04-21
- RR 3.3.0 released · 2016-05-03
- RR 3.2.0 released · 2015-04-16
- 0.22014-04-16 · diff ↗
- RR 3.1.0 released · 2014-04-10
- 0.12013-10-08
- RR 3.0.0 released · 2013-04-03
Package metadata
- First published
- 2013-10-08
- Total releases
- 29 / 13 yrs
- License
- GPL-3 OSI
- Minimum R
- ≥ 3.5
- Bundled data
- 468 KB / 6 files
- Download size
- 3.9 MB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("mizer")This package has no citation file, so citation() returns this entry built from DESCRIPTION.
The repository also keeps a CITATION.cff.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-19, which the citation names so these numbers can be found later. More on citing and the projects behind them.