This release brings new biological realism, improved numerics, a richer
interactive analysis experience, and a composable extension framework.
For an overview see the
blog post
pre-announcing the release.
Diffusion in mizer
The McKendrick-von Foerster equation now supports a diffusion term, allowing
individual variability in growth to be modelled.
-
New
getDiffusion()calculates the total diffusion rate D(w) (g²/year) for
each species, combining the predation-induced diffusion from the jump-growth
equation and any externally specified diffusion set viasetExtDiffusion().
It has bothMizerParamsandMizerSimmethods and returns an
ArraySpeciesBySizeorArrayTimeBySpeciesBySizeobject respectively,
consistent with the other rate-getter functions. -
The external diffusion coefficient is held in a new
ext_diffusionslot in
MizerParams. UsesetExtDiffusion()/ext_diffusion()/
ext_diffusion<-()to set and retrieve it. The new species parameterD_ext
(default 0) sets the coefficient of an external diffusion power law;
setExtDiffusion()calculates the default array from species parameters when
no custom array is supplied, following the same pattern as
setExtEncounter(). -
MizerParamsgains ause_predation_diffusionslot (logical, default
FALSE). WhenFALSE(the default),mizerDiffusion()omits the
predation-induced diffusion term, preserving the behaviour of previous mizer
versions. Set toTRUEvia the newuse_predation_diffusion()accessor to
enable the jump-growth diffusion term. -
New
getFlux()function calculates the flux of individuals entering each
size class, combining the advective flux from somatic growth and the
diffusive flux. It has apowerargument, similar to that ofplotSpectra(),
for multiplying the flux by a power of the weight;power = 1gives the flux
of biomass. -
getRequiredRDD()is exported. It calculates the recruitment rate needed
to maintain a given initial abundance, accounting for both growth and
diffusion. -
steadySingleSpecies()correctly preserves the steady state under
project(), including when diffusion is non-zero. -
The vignette cohort dynamics
demonstrates the effect of diffusion in an example.
Higher-order numerical scheme
-
project(),projectToSteady()andsteady()gain amethodargument for
choosing the consumer density time-stepper. The default"euler"preserves
the existing semi-implicit update, while"predictor_corrector"uses a new
second-order predictor-corrector method. The accuracy of the two methods is
compared in the numerical details
vignette. -
MizerSimobjects now have asim_paramsslot (a named list) that records
the projection parameters — currentlymethodanddt— passed to
project()orprojectToSteady(). The newgetSimParams()accessor
retrieves this list. Whenproject()is called on an existingMizerSim
object it defaultsdtandmethodfrom the storedsim_params, with a
warning if the supplied values differ. Older objects are upgraded
automatically byvalidSim(), withsim_paramsset to an empty list. -
project_n()andproject_n_2(2)are new exported functions, factored out of
project_simple(), that projects the abundance spectrum forward in time with
the different methods.
Convenient plot methods for mizer return values
-
New
ArraySpeciesBySizeS3 class for the species × size arrays returned by
many mizer functions. AnArraySpeciesBySizeobject behaves like a regular
matrix for arithmetic and subsetting but carries a human-readable
value_nameandunitsattribute and provides enhancedprint(),
summary(),plot(), andas.data.frame()methods. Theplot()method
acceptslog_y,wlim, andylimarguments for controlling the y-axis
scale and limits. -
New
ArrayTimeBySpeciesS3 class for the time × species arrays returned by
getBiomass(),getSSB(),getN(), andgetYield()when called on a
MizerSimobject. LikeArraySpeciesBySize, it carriesvalue_nameand
unitsattributes and provides enhancedprint(),summary(),plot(),
andas.data.frame()methods. Theplot()method acceptslogandylim
arguments. -
New
ArrayTimeBySpeciesBySizeS3 class for the time × species × size arrays.
TheN()accessor on aMizerSimobject now returns an
ArrayTimeBySpeciesBySizeobject. Many rate-getter functions —
getEGrowth(),getEReproAndGrowth(),getPredMort(),getFMort(),
getMort(),getFeedingLevel(),getEncounter(),getPredRate(),
getRDI(),getRDD()— now also accept aMizerSimobject and return an
ArrayTimeBySpeciesBySize. Ananimate()method allows interactive
playback. Subsetting anArrayTimeBySpeciesBySizeobject returns an
ArraySpeciesBySizeobject when a single time is selected, and an
ArrayTimeBySpeciesobject when a single size is selected. -
New
plot2()generic with methods for comparing two compatible mizer array
objects in one plot, with species or group shown by colour and model by
linetype. TheplotSpectra2()helper has moved frommizerExperimentalinto
mizer for comparing two abundance spectra. -
New
plotRelative()generic with methods for plotting the symmetric relative
difference between two compatible mizer array objects. The
plotSpectraRelative()andplotlySpectraRelative()helpers have moved from
mizerExperimentalinto mizer. -
New
plotCDF()andplotCDF2()generics for plotting cumulative abundance
or biomass distributions fromMizerParamsandMizerSimobjects, together
withplotlyCDF()andplotlyCDF2()wrappers. -
New
plotHover()generic with methods forArraySpeciesBySize,
ArrayTimeBySpecies,ArrayTimeBySpeciesBySize, andmizer_plotconverts
mizer plots into hover-enabled plotly figures. -
New
addPlot()generic with methods for addingArraySpeciesBySizeand
ArrayTimeBySpeciesvalues as extra lines on an existing compatible ggplot. -
The
animate()methods produces animated plots showing the time evolution
during a simulation. It can take aMizerSimandArrayTimeBySpeciesBySize
argument and supports axis range settings (xlim,ylim), timing controls,
interpolation options, argumentslog_xlog_yandlogto control which
axis is log-transformed, andtotalandbackgroundarguments, consistent
withplotSpectra(). -
Plotting functions now consistently expose
log_x,log_yandlog
arguments. In all cases, when supplied,logoverrideslog_xandlog_y.
plotBiomass()andplotYield()keep support for logicallogvalues for
backward compatibility. -
Time-filtering is now consistent across all time-series plot functions via a
newtlimparameter (analogous towlimandylim): a length-two numeric
vectorc(start, end)that restricts the plotted time window.plotYield(),
plotYieldGear(), andanimate()gain this parameter for the first time.
plotBiomass()andanimate.MizerSim()now usetlimin place of the
formerstart_time/end_timeandtime_rangeparameters respectively;
the old parameters are deprecated and will be removed in a future release. -
Size-based plots now accept
size_axis = "l"to show length in cm on the
size axis instead of weight in grams, using the species' allometric
weight-length relationship. -
Size-based plots with a
size_axisargument now acceptllim, the
length-axis equivalent ofwlim, for filtering and limiting plots when
size_axis = "l".
Extracting model state from a simulation
-
A shift in interpretation of a MizerParams object from just a specification
of the model to a representation of its state, consisting of both model
parameters and current values of the state variables (the abundances). -
getParams(sim, time_range, geometric_mean = FALSE)now extracts the
ecosystem state from aMizerSimobject at a particular time or averaged
over a time range. When notime_rangeis given, the state at the final time
step is extracted. NewfinalParams(sim)andinitialParams(sim)return the
states at the initial and final times of a simulation respectively. -
Once a state has been extracted from a simulation, it can be analysed by all
the existing mizer functions. For that purpose the indicator functions
getProportionOfLargeFish(),getMeanWeight(),getMeanMaxWeight(), and
getCommunitySlope()now also accept aMizerParamsobject and return a
single value (or named vector forgetMeanMaxWeight()with
measure = "both") calculated from that state. Closes #262. -
setInitialValues()is deprecated. Replace
setInitialValues(params, sim)withfinalParams(sim)(or
getParams(sim, time_range, geometric_mean)when averaging over a time
range).
New extension mechanism allowing extension chains
-
Many functions are now S3 generics with methods for
MizerParamsorMizerSimobjects, and users can define their own subclass
methods to modify mizer behaviour (#330). -
New composable extension chain infrastructure:
registerExtensions(),
getRegisteredExtensions(),coerceToExtensionClass(),
clearExtensionChain(), andregisterExtension(). Extension classes are S3
marker classes;MizerSimderives its extension chain from
sim@params@extensions. Extensions that do not provide a marker class remain
metadata-only and do not trigger the S3 projection-rate dispatch path. -
S3 projection hooks have been added for all standard mizer rate functions.
Extension-aware projections dispatch throughprojectRates(),
projectEncounter(),projectFeedingLevel(),projectEReproAndGrowth(),
projectERepro(),projectEGrowth(),projectDiffusion(),
projectPredRate(),projectPredMort(),projectFMort(),projectMort(),
projectRDI(),projectRDD(), andprojectResourceMort()— while models
without extensions continue to use the pre-resolvedmizerRates()pipeline
directly, with no per-step overhead. -
The
MizerSimaccessorsgetParams(),
validSim(),N(),NResource(),finalN(),finalNResource(),
idxFinalT(),getTimes(),getEffort(), and are now
registered as S3 generics withMizerSimmethods, making extension-specific
methods possible.validParams()is also now an S3 generic. -
saveParams()now serialises extension objects as plainMizerParams
objects while preserving their extension chain, andreadParams()restores
the appropriate extension class. NewsaveSim()andreadSim()helpers
provide the same lifecycle forMizerSimobjects. -
Extension installation support now integrates
pakfor managing missing or
outdated extension packages. -
New vignette
Extending mizer
documents when to usesetRateFunction(),setComponent(), and
customFunction(), summarises required function signatures and return shapes,
and gives worked examples for both a custom encounter function and an added
ecosystem component. A companion vignette
Using extension packages
is aimed at users of extension packages, and
Creating a mizer extension package
guides extension authors through setting up a new extension package. -
setRateFunction()now validates the registered function by calling it with
test inputs and checking that the return value has the correct dimensions,
catching mismatched custom rate functions at registration time rather than
during a simulation run. Closes #167. -
setComponent()now accepts optionalcolourandlinetypearguments and
applies them viasetColours()andsetLinetypes()so added components can
be styled directly in plots. -
The
plot()andsummary()methods forMizerParams,MizerSim, and the
mizer array classes are now registered as S3 methods rather than S4 methods,
soplot()andsummary()remain plain S3 generics when mizer is loaded,
avoiding interference with S4 method dispatch for other packages.
Species parameters for external mortality, encounter and diffusion rates
See the model description vignette for
the mathematical details.
-
New species parameters
z_ext(default 0) andd(defaultn - 1) add an
optional power-law term to the external mortality:mu_ext(w) = z0 + z_ext * w^d. Whenz_extis zero (the default) the behaviour is unchanged. Closes
#329. -
New species parameter
E_ext(default 0) sets the coefficient of the
external encounter rate power law.setExtEncounter()now calculates the
default external encounter rate asE_ext * w^nwhen no custom array is
supplied, matching the pattern ofsetMaxIntakeRate(). Aresetargument is
also added tosetExtEncounter()to force recalculation from species
parameters. -
New species parameter
D_ext(default 0) sets the coefficient of the
external diffusion rate power law.setExtDiffusion()calculates the default
array from species parameters when no custom array is supplied.
Other improvements
-
The
MizerSimmethods of the rate-getter functions (getEncounter(),
getFeedingLevel(),getEReproAndGrowth(),getERepro(),getEGrowth(),
getDiffusion(),getPredRate(),getPredMort(),getMort(),getFMort(),
getFMortGear(),getRDI(),getRDD()andgetFlux()) are now much faster.
They resolve the rate functions and validate the parameters once and then, at
each saved time step, calculate only the rates needed (and their
dependencies) rather than re-resolving and recomputing the whole rate chain.
The speed-up grows with the depth of the rate chain, e.g. roughly 100× for
getRDI()andgetFlux()on a 50-step simulation. -
New
scaleRates(params, factor)function that rescales all rates in a model
by a given factor. This is equivalent to a time rescaling: it speeds up or
slows down all dynamics without affecting the steady state. All rate slots
(search_vol,intake_max,metab,mu_b,ext_encounter,
ext_diffusion,catchability,rr_pp) and their associated species
parameters (gamma,h,ks,k,z0,z_ext,z0pre,E_ext,
D_ext,R_max) are rescaled consistently. -
New
getTrophicLevel()function returns a matrix (species × size) with the
trophic level of individuals at each size, accounting for ontogenetic diet
shifts by integrating the consumption-weighted average prey trophic level
over the individual's growth trajectory. NewgetTrophicLevelBySpecies()
returns the consumption-rate-weighted mean trophic level per species. Both
functions acceptMizerParamsandMizerSimobjects. Closes #307. -
New
expandSizeGrid()function (an S3 generic) expands the size grid of a
MizerParamsobject to a new minimum and/or maximum size while preserving
all existing species data. BothaddSpecies()andexpandSizeGrid()now
preserve theMizerParamssubclass.upgradeParams()also preserves
MizerParamssubclasses and their extra slots. -
compareParams()output is now printed in a human-readable format, with each
difference as its own block separated by blank lines. When array slots differ,
the max absolute difference is shown per species. When slots differ only in
theircommentattributes, both comments are displayed. Closes #205. -
summary()forMizerParamsandMizerSimnow displays metadata from the
@metadataslot, including title, description, authors, DOI, URL, mizer
version, and creation/modification timestamps (when set). Closes #294. -
New
str()methods forMizerParamsandMizerSimobjects, and the mizer
array classes (ArraySpeciesBySize,ArrayTimeBySpecies, and
ArrayTimeBySpeciesBySize), showing a clean, compact overview of their
structures without dumping large amounts of internal data. -
A new
steadyargument toaddSpecies()controls whethersteady()is
called after adding the new species. -
constantEggRDI()now accounts for diffusion across the egg-size boundary,
including whenproject()uses the"predictor-corrector"method. -
setRateFunction()now validates custom RDI functions with the same
diffusionargument that they receive during projection. -
Growth is now forced to always be non-negative, preventing unphysical
shrinkage. No warning is issued when growth stops at or after maturity size. -
Added
info_levelargument toprojectToSteady(),steady(),setParams(),
newCommunityParams(),newTraitParams(),matchBiomasses(),
matchNumbers(),matchYields()andaddSpecies()to control the
verbosity of information messages, consistent withnewMultispeciesParams().
Setinfo_level = 0to suppress all messages. Closes #290. -
t_maxandt_savearguments inproject()are now respected even when an
effort array is supplied. Whent_maxis provided, the simulation extends
beyond the times in the effort array using the last known effort values. When
t_saveis provided, it controls the save frequency with effort values
interpolated as needed (#231). -
getBiomass()now has ause_cutoffargument to restrict the biomass
calculation to sizes above thebiomass_cutoffspecies parameter.
plotBiomass()andplotlyBiomass()also gain this argument. -
setResource()now allowsresource_level = 1. When balancing would
otherwise divide by zero because the resource capacity equals the current
resource abundance at positive consumption, the capacity is increased
slightly with a warning instead of failing early. -
project()now warns whent_maxis not a multiple oft_saveand ensures
that the state att_maxis always saved, even if the final save interval is
shorter thant_save. (#341) -
New function
psi()returns anArraySpeciesBySizewith the population-level
reproductive proportion. -
age_mat_vB()is now exported. -
New Cheatsheet: Analysis and Plotting
vignette provides a quick reference for all functions that access simulation
arrays, compute summaries, calculate indicators, and create plots.
Closes #176.
Bug fixes
-
getFMort()on aMizerSimobject was silently dropping the component
names fromn_otherwhen passing it to the rate function and its
dependencies (getEGrowth(),getPredMort()), causing failures whenever
rate functions accessedn_otherby name (e.g.n_other[["resource"]]).
The implementation has been refactored to use the sameplyr::aaplypattern
asgetFeedingLevel()andgetPredMort(). -
getFMort.MizerSim()was not passing the time argumenttto user-defined
fishing mortality functions. -
plotSpectra()was incorrectly forcing the y-axis lower limit to 1e-20
(instead of auto-scaling to the data) and was usingmin(params@w) / 100
as the default lower w-axis limit even whenresource = FALSE, where
min(params@w)is more appropriate. -
upgradeParams()was silently dropping some slots (e.g.resource_dynamics)
and was not preservingMizerParamssubclasses and their extra slots when
upgrading older objects. -
getMeanMaxWeight()now correctly applies the species selector to the
denominator. -
plotDataFrame()now correctly applies custom log-scale x breaks. -
get_size_range_array()no longer gives an error when no size brackets are
selected.
Breaking changes
-
The default
ratioargument inplotBiomassObservedVsModel()and
plotlyBiomassObservedVsModel()is now consistentlyFALSEfor all object
types. Calls that relied on the previous default ratio plot should now set
ratio = TRUE. -
The first argument of
plotBiomass(),plotYield(),plotYieldGear()and
theirMizerSimmethods andplotly*wrappers has been renamed fromsim
toobjectfor consistency with other plot generics. Calls using
sim = ...as a named argument must be updated toobject = .... -
The names of the dimnames of the arrays returned by
getMort(),
getPredRate()are nowspandwto be in line with other
functions likegetFMort(). -
Functions that return arrays of the form (species x size), (time x species)
or (time x species x size) now return them with extra attributes and an S3
class ofArraySpeciesBySize,ArrayTimeBySpeciesor
ArrayTimeBySpeciesBySize. While this does not change their old behaviour,
the differences will be flagged by functions likeis.identical(). -
Because
plotDataFrame()now correctly applies custom log-scale x breaks,
the axis ticks in plots that use this function have changed. -
plotDiet()no longer accepts atime_rangeargument.