Skip to content

Releases: sizespectrum/mizer

mizer 3.2.0

Choose a tag to compare

@gustavdelius gustavdelius released this 21 Jul 06:27

This release overhauls how species and resource parameters are set, makes the
extension framework composable regardless of load order, adds a new
adjustSizeGrid() function and cheatsheets, and includes a range of smaller
improvements and bug fixes.

For an overview see the
release announcement
on the mizer blog.

Resource setting

  • Assigning to resource_params() (or one of its components, e.g.
    resource_params(params)$kappa <- ...) now immediately rebuilds the
    size-dependent resource rate (rr_pp) and capacity (cc_pp) arrays from the
    scalars, leaving any manually set (frozen) arrays untouched, exactly as
    species_params<- feeds the species rates. As a result changing the
    rate-side scalars r_pp or n now takes effect (previously the value was
    silently discarded), and successive scalar edits accumulate instead of
    overwriting each other. Assigning to resource_params() no longer balances
    the resource; balancing to preserve the steady state is now solely a feature
    of setResource().

  • The resource_rate<-, resource_capacity<-, resource_level<- and
    resource_dynamics<- setters gained a balance argument (default
    unchanged) so it can be switched off, e.g.
    resource_capacity(params, balance = FALSE) <- my_capacity.

  • setResource() no longer silently overwrites a manually set (frozen) rate
    or capacity array when balancing: the frozen array wins and a warning is
    issued. The one exception to the frozen-array protection is that steady()
    will rebalance the resource_capacity in order to return a steady state,
    ignoring any freeze.

These changes and how to adapt existing code are described in the new
vignette("upgrading") ("Upgrading mizer").

Species parameter changes

  • Modifying species parameters via species_params<-() now automatically
    detects your changes, records them in given_species_params so they are
    protected from being overwritten by defaults in the future, and silently
    triggers the recalculation of any dependent parameters and rate arrays.
    Previously, species_params<-() bypassed the given_species_params
    protection and didn't trigger recalculations. This restores expected
    behaviour and makes species_params<-() the recommended setter for scripts.

  • The given_species_params<-() setter remains as an explicit alternative
    that is particularly useful during interactive sessions, because it issues
    warnings if you change a parameter whose effect is overridden by another
    parameter that has already been given.

  • Each species parameter default now has a single home: the rate-setting
    function that uses the parameter. validSpeciesParams() now only fills in
    defaults for parameters that no single rate setter owns, namely w_max,
    w_repro_max, w_mat, w_min, alpha, n, a, b and is_background.
    The defaults for p, k, z_ext, d, E_ext, D_ext and
    interaction_resource are supplied by setMetabolicRate(), setExtMort(),
    setExtEncounter(), setExtDiffusion() and setInteraction() respectively,
    where they were already being set. Built models are unaffected, because
    setParams() calls all the rate-setting functions, but
    validSpeciesParams() applied to a bare species parameter data frame now
    returns fewer columns. See the default_parameters vignette.

  • The p argument of setMetabolicRate() is deprecated (#459). It never had
    any effect on a MizerParams object: such an object always has a p column
    already, and the argument was only ever used to fill in a missing one, so it
    was silently ignored. Set the species parameter instead, with
    species_params(params)$p <- value. The p argument of
    newMultispeciesParams() is a different argument and is not affected.

  • The default for the metabolic exponent p is now n rather than 3/4 in
    setMetabolicRate(), which is where the default now lives;
    validSpeciesParams() no longer sets p. No model changes as a result.
    Models built with newMultispeciesParams() take p from its own p
    argument (default 0.7), which is injected into the species parameter table
    before validation and is untouched by this change, so neither of these
    defaults fires for them. The validSpeciesParams() default (p = n) only
    ever applied when it was called directly on a bare species parameter data
    frame, which now returns no p column, and it shadowed the
    setMetabolicRate() default whenever both were in play.

  • Default values for the a (0.01) and b (3) species parameters (for the
    weight-length relationship) are now saved in species_params instead of
    being calculated internally by l2w() and w2l() only when needed.

  • The species_params data frame is now an S3 subclass of data.frame
    (class = c("species_params", "data.frame")). It supports class-preserving
    subsetting and subassignment S3 methods, making it safer to use and paving
    the way for future auto-recalculations.

  • Columns accessed via $ on a species_params or gear_params object now
    return named vectors, where the names are the species names (or "species,
    gear" row names for gear_params). For example,
    species_params(params)$w_mat now returns a named vector making it easier
    to identify entries. The species vector is left unnamed.

  • When sel_func is set on a gear_params object, any argument columns
    required by that selectivity function (other than w, species_params, and
    ...) are now automatically added as NA columns. This means, for example,
    that setting gp$sel_func <- "sigmoid_length" immediately creates the l25
    and l50 columns, ready to be filled in (#431).

  • Misspelled column names in the gear_params and species_params data
    frames are now detected by fuzzy matching against the recognised parameter
    names. A near miss such as sel_fun (instead of sel_func) triggers a
    warning that suggests the intended name, rather than being silently ignored
    (#442). Columns are only flagged, never renamed, so legitimate custom
    columns are left untouched.

See the new vignette("upgrading") ("Upgrading mizer") for how to adapt
existing code to these changes.

Extension framework

  • An installed extension package is now recognised as a dispatching extension
    from the S3 methods it registers for its marker class (e.g.
    getEncounter.mizerMR), rather than only from a statically defined S4 marker
    class. This lets extension packages omit the static
    setClass("mizerFoo", contains = "MizerParams") and instead let mizer create
    the marker class dynamically when the package is loaded, inserting it at the
    correct place in the S4 hierarchy relative to any other extensions loaded in
    the session. As a result, two independently developed extension packages
    (for example mizerReef and mizerMR) can now be chained in either load order,
    which a static sibling-of-MizerParams class prevented.

  • recordExtension() now prepends a genuinely new extension to the front of the
    object's @extensions chain, keeping it ordered outermost-first to match
    registerExtension(). Existing entries stay in place.

New functions

  • New adjustSizeGrid() function (an S3 generic) adjusts the size grid of
    a MizerParams object to a new minimum and/or maximum size. It can both
    expand and truncate (shrink) the grid. For each species it warns if
    truncation discards a non-negligible fraction of the species' biomass, of
    the diet of its smallest individuals, or of the diet of its largest
    individuals.

  • Added a callback parameter to project() to allow user-defined functions
    to be called at each saved time step.

Other improvements

  • Mizer plots no longer produce the unhelpful warning "log-10 transformation
    introduced infinite values" when a logged axis contains zero values (#463).

  • setColours() and setLinetypes() now also update the linecolour and
    linetype entries in species_params and given_species_params whenever a
    name being set coincides with a species name, so that the choice persists
    with the species rather than only living in the plotting slot.

  • library(mizer) now prints a one-line startup message the first time you
    load a new mizer version, pointing you to news(package = "mizer"). It is
    shown at most once per version and never interrupts a session more than
    that.

  • compareParams() now checks that the number of size bins, species and gears
    agree before comparing the array-valued slots. When they differ it reports the
    mismatch instead of erroring while trying to compare arrays of incompatible
    dimensions. It also compares the species-parameter tables by matching species
    and parameters by name, so differing species no longer produce a long list of
    per-column length mismatches, and duplicated messages are no longer repeated.

  • 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.

  • 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).

  • print() on ArraySpeciesBySize, ArrayTimeBySpecies, ArrayResourceBySize,
    ArrayTimeByResourceBySize and ArrayTimeBySpeciesBySize objects (as
    returned by getEncounter(), getBiomass(), getResourceMort(), NResource(),
    getFMort() and similar functions) now prints the array's actual values
    instead of a per-species min/mean/max summary, truncating large arrays to
    fit the console: species are shown as a leading ...

Read more

mizer 3.1.0

Choose a tag to compare

@gustavdelius gustavdelius released this 28 Jun 11:12

Version 3.1.0 builds on 3.0.0 with an experimental second-order accurate
numerical scheme in size, additional higher-order time-stepping options, and a
range of smaller improvements and bug fixes. Unless you opt in to the
experimental scheme, results are unchanged from 3.0.0.

For an overview see the release announcement on the mizer blog.

Experimental second-order in w accuracy

mizer gains an optional, experimental second-order accurate finite-volume scheme
in the size variable w. It is controlled by a new second_order_w slot and is
switched off by default, so all default results are unchanged (the first-order
path is byte-identical to previous mizer). Enabling it shifts size-integrated
diagnostics and the resource spectrum by O(Δw) (more on coarse grids), so
calibrated models may need recalibrating. See ?second_order_w and the
"Numerical Details" vignette.

  • The second_order_w slot is a named list with a character entry flux
    ("upwind", "van_leer" or "centred") selecting the advective
    reconstruction, and a logical entry bin_average selecting the bin-averaged
    rate quadratures. A fully second-order scheme needs both. Use the new
    second_order_w() / second_order_w<-() accessors to get and set them. The
    setter accepts a single logical, which sets both entries — flux = "van_leer"
    (a TVD reconstruction that keeps abundances non-negative) and
    bin_average = TRUE — or a named vector for individual control, e.g.
    second_order_w(params) <- c(flux = "centred") for the unlimited flux that is
    genuinely second order even at extrema. Setting it re-runs setParams() to
    rebuild the precomputed arrays. The default flux = "upwind",
    bin_average = FALSE is the original first-order upwind scheme. Old objects
    are upgraded automatically.

  • newMultispeciesParams(), newTraitParams(), newCommunityParams() and
    newSingleSpeciesParams() gain a second_order_w argument (default FALSE,
    accepting the same values as the setter) that builds the new model with the
    scheme already selected. Under bin_average the resource and abundance power
    laws are constructed bin-averaged from the start; the construction-time
    steady-state solve always uses the robust upwind flux, and the chosen flux is
    activated only for the returned model. (#379)

  • When bin_average is TRUE, every point-sampled power law and quadrature that
    feeds the finite-volume update is replaced by its exact bin average over each
    size bin (the bin straddling w_pp_cutoff receiving the partial average), so
    the sinks, sources and capacities are consistent with the bin-integrated
    encounter convolution (#374):

    • the external mortality \eqn{z_{ext} w^d} (setExtMort()) and external
      diffusion \eqn{D_{ext} w^{n+1}} (setExtDiffusion());
    • the auto-calculated resource intrinsic growth \eqn{r_p w^{n-1}} and carrying
      capacity \eqn{\kappa w^{-\lambda}} (setResource(); user-supplied full
      vectors are left untouched), together with the matching initial resource
      abundance \eqn{\kappa w^{-\lambda}} used both for the initial spectrum and
      for the temporary prey spectra behind the default gamma/f0 and consumer
      abundances;
    • the predation kernels, which are now predator- and prey-bin averaged (via
      trapezoid folds), so getEncounter(), getPredRate(), getPredMort(),
      getResourceMort() and getDiffusion() become second order with no change
      to the rate functions and no extra runtime cost. The predation-diffusion
      integral uses a dedicated Fourier kernel held in the new ft_pred_kernel_d
      slot, which carries the extra power of prey size (\eqn{w_p^2 dw_p}, the
      \eqn{\beta^{3s}} Jacobian) that the diffusion integrand needs; in the
      first-order scheme it equals ft_pred_kernel_e, so existing models are
      byte-identical. (#384)
    • the gear selectivity (calc_selectivity()), so a knife-edge gear gets the
      exact fraction of the straddling bin above the knife edge and fishing
      mortality is second order;
    • the per-capita reproductive investment \eqn{\psi(w) E_r(w)} in mizerRDI()
      (the full investment averaged together, not psi alone), making
      density-independent reproduction second order.
  • The advective growth flux uses the chosen flux reconstruction ("van_leer"
    or "centred") for a second-order transport step. Combined with the
    bin-averaged diffusion from getDiffusion(), the full growth-transport step is
    second order. The diffusion coefficient is consumed from getDiffusion()
    directly rather than being re-averaged by the transport routine.

  • Size-integrated and size-resolved diagnostics are placed and weighted
    consistently with the finite-volume scheme when bin_average is TRUE:

    • the summary integrals getBiomass(), getSSB(), getYield(),
      getYieldGear(), getDiet() and getTrophicLevel() use the trapezoidal
      bin-average of the size weight (getN() is already exact);
    • the size-resolved bin-average diagnostics — the mortalities getPredMort(),
      getFMort(), getMort(), getExtMort() and the reproductive investment
      getERepro() — are reported at the geometric bin centre
      \eqn{\sqrt{w_j w_{j+1}}}, the location where a bin average actually lives,
      while point-valued quantities (encounter, growth) stay on the grid nodes.
      The ArraySpeciesBySize / ArrayTimeBySpeciesBySize classes carry a
      representation tag ("point" / "average") recording this. (#382)
    • the spectrum plots plotSpectra(), plotlySpectra(),
      plotSpectraRelative() and animateSpectra() evaluate both the w^power
      weight and the marker location at the geometric bin centre
      \eqn{w^* = w \sqrt{\beta}}, placing each marker as a point on the continuous
      N w^power curve instead of misplacing it at the bin edge (the error grows
      with power, worst for the common power = 2 Sheldon plot). (#383)

Higher-order time-stepping

  • project() gains a new time-stepping option method = "tr_bdf2". This is an
    L-stable, second-order TR-BDF2 scheme that retains the second-order accuracy of
    method = "predictor_corrector" while damping the oscillations the
    Crank-Nicolson corrector can show at large time steps. Like the other methods
    it only requires tridiagonal solves. See the "Numerical Details" vignette.

  • Under the second-order methods ("predictor_corrector" and "tr_bdf2") the
    resource is now advanced with midpoint resource mortality rather than the
    start-of-step value, and the other components (set via setComponent()) now
    also receive a corrector step with the midpoint rates. So the resource and the
    other components are integrated to the same second-order accuracy in time as
    the consumer spectra. The "euler" method and the steady states are unchanged.

Other improvements

  • Extension packages can now upgrade their own data in saved model objects
    independently of the mizer version. The @extensions slot can record, for
    each extension, the version of the extension package that the object conforms
    to (write entries with the new recordExtension()). needs_upgrading() flags
    an object when an extension's recorded version is missing or older than the
    installed package version, and validParams() then calls the extension's own
    upgrade() method (an S3 method on utils::upgrade(), registered with
    @exportS3Method utils::upgrade). The core mizer upgrade is now itself the
    upgrade.MizerParams() / upgrade.MizerSim() method. See the "Upgrading
    objects across versions of your extension" section of
    vignette("creating-extension-packages").

  • getDiet() gains a MizerSim method and plotDiet() for a MizerSim now
    accepts a time_range argument, computing the diet from the simulated
    abundances at the requested times rather than always using the initial
    abundances. As for the other MizerSim plotting functions, time_range
    defaults to the final saved time step. When a range spanning several saved
    time steps is given, the consumption rates are averaged over the range and
    then normalised to proportions (rather than averaging the per-step
    proportions, which are normalised independently). (#357)

  • New getFluxGradient() function returns the flux divergence
    \eqn{(J_{j+1} - J_j)/\Delta w_j} that appears as the transport term in the
    discretised size-spectrum equation. The bin-boundary fluxes are obtained from
    getFlux(), so the advective-flux scheme stored in the flux entry of the
    second_order_w slot is used, with the largest size class closed by the
    boundary condition \eqn{N_{K+1} = 0}. Like getFlux(), it has both
    MizerParams and MizerSim methods, returning an ArraySpeciesBySize or
    ArrayTimeBySpeciesBySize object respectively.

  • getDiffusion() now works with a custom predation kernel that depends on
    predator and prey size separately rather than only on their ratio. As for
    getEncounter(), when such a kernel has been set (with
    setPredKernel(params, pred_kernel = ...)) the diffusion integral is
    evaluated by direct summation over the full predation kernel instead of via
    the FFT method, which assumes a ratio-only kernel. (#373)

  • getTrophicLevel() and getTrophicLevelBySpecies() now assign the resource a
    size-dependent trophic level
    \eqn{T_R(w) = \max(1, 1 + \log(w / w_R) / \log(\beta_R))} instead of treating
    it as trophic level 0. The new w_R (average primary-producer size) and
    beta_R (average resource predator/prey mass ratio) arguments control this.

  • Resource functions now return classed objects that support the same
    convenient print(), summary(), plot() and as.data.frame() methods as
    the consumer rate functions. getResourceMort(), initialNResource(),
    finalNResource(), resource_rate(), resource_capacity() and
    resource_level() return an `ArrayRes...

Read more

mizer 3.0.0

Choose a tag to compare

@gustavdelius gustavdelius released this 09 Jun 10:33

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 via setExtDiffusion().
    It has both MizerParams and MizerSim methods and returns an
    ArraySpeciesBySize or ArrayTimeBySpeciesBySize object respectively,
    consistent with the other rate-getter functions.

  • The external diffusion coefficient is held in a new ext_diffusion slot in
    MizerParams. Use setExtDiffusion() / ext_diffusion() /
    ext_diffusion<-() to set and retrieve it. The new species parameter D_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().

  • MizerParams gains a use_predation_diffusion slot (logical, default
    FALSE). When FALSE (the default), mizerDiffusion() omits the
    predation-induced diffusion term, preserving the behaviour of previous mizer
    versions. Set to TRUE via the new use_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 a power argument, similar to that of plotSpectra(),
    for multiplying the flux by a power of the weight; power = 1 gives 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() and steady() gain a method argument 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.

  • MizerSim objects now have a sim_params slot (a named list) that records
    the projection parameters — currently method and dt — passed to
    project() or projectToSteady(). The new getSimParams() accessor
    retrieves this list. When project() is called on an existing MizerSim
    object it defaults dt and method from the stored sim_params, with a
    warning if the supplied values differ. Older objects are upgraded
    automatically by validSim(), with sim_params set to an empty list.

  • project_n() and project_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 ArraySpeciesBySize S3 class for the species × size arrays returned by
    many mizer functions. An ArraySpeciesBySize object behaves like a regular
    matrix for arithmetic and subsetting but carries a human-readable
    value_name and units attribute and provides enhanced print(),
    summary(), plot(), and as.data.frame() methods. The plot() method
    accepts log_y, wlim, and ylim arguments for controlling the y-axis
    scale and limits.

  • New ArrayTimeBySpecies S3 class for the time × species arrays returned by
    getBiomass(), getSSB(), getN(), and getYield() when called on a
    MizerSim object. Like ArraySpeciesBySize, it carries value_name and
    units attributes and provides enhanced print(), summary(), plot(),
    and as.data.frame() methods. The plot() method accepts log and ylim
    arguments.

  • New ArrayTimeBySpeciesBySize S3 class for the time × species × size arrays.
    The N() accessor on a MizerSim object now returns an
    ArrayTimeBySpeciesBySize object. Many rate-getter functions —
    getEGrowth(), getEReproAndGrowth(), getPredMort(), getFMort(),
    getMort(), getFeedingLevel(), getEncounter(), getPredRate(),
    getRDI(), getRDD() — now also accept a MizerSim object and return an
    ArrayTimeBySpeciesBySize. An animate() method allows interactive
    playback. Subsetting an ArrayTimeBySpeciesBySize object returns an
    ArraySpeciesBySize object when a single time is selected, and an
    ArrayTimeBySpecies object 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. The plotSpectra2() helper has moved from mizerExperimental into
    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() and plotlySpectraRelative() helpers have moved from
    mizerExperimental into mizer.

  • New plotCDF() and plotCDF2() generics for plotting cumulative abundance
    or biomass distributions from MizerParams and MizerSim objects, together
    with plotlyCDF() and plotlyCDF2() wrappers.

  • New plotHover() generic with methods for ArraySpeciesBySize,
    ArrayTimeBySpecies, ArrayTimeBySpeciesBySize, and mizer_plot converts
    mizer plots into hover-enabled plotly figures.

  • New addPlot() generic with methods for adding ArraySpeciesBySize and
    ArrayTimeBySpecies values as extra lines on an existing compatible ggplot.

  • The animate() methods produces animated plots showing the time evolution
    during a simulation. It can take aMizerSim and ArrayTimeBySpeciesBySize
    argument and supports axis range settings (xlim, ylim), timing controls,
    interpolation options, arguments log_x log_y and log to control which
    axis is log-transformed, and total and background arguments, consistent
    with plotSpectra().

  • Plotting functions now consistently expose log_x, log_y and log
    arguments. In all cases, when supplied, log overrides log_x and log_y.
    plotBiomass() and plotYield() keep support for logical log values for
    backward compatibility.

  • Time-filtering is now consistent across all time-series plot functions via a
    new tlim parameter (analogous to wlim and ylim): a length-two numeric
    vector c(start, end) that restricts the plotted time window. plotYield(),
    plotYieldGear(), and animate() gain this parameter for the first time.
    plotBiomass() and animate.MizerSim() now use tlim in place of the
    former start_time/end_time and time_range parameters 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_axis argument now accept llim, the
    length-axis equivalent of wlim, 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 a MizerSim object at a particular time or averaged
    over a time range. When no time_range is given, the state at the final time
    step is extracted. New finalParams(sim) and initialParams(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 a MizerParams object and return a
    single value (or named vector for getMeanMaxWeight() with
    measure = "both") calculated from that state. Closes #262.

  • setInitialValues() is deprecated. Replace
    setInitialValues(params, sim) with finalParams(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
    MizerParams or MizerSim objects, and users can define their own subclass
    methods to modify mizer behaviour (#330).

  • New composable extension chain infrastructure: registerExtensions(),
    getRegisteredExtensions(), coerceToExtensionClass(),
    clearExtensionChain(), and registerExtension(). Extension classes are S3
    marker classes; MizerSim derives 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 through projectRates(),
    projectEncounter(), projectFeedingLevel(), `project...

Read more

v2.5.4

Choose a tag to compare

@gustavdelius gustavdelius released this 17 Nov 07:43
  • New function renameGear() to rename gears in a MizerParams object, similar
    to renameSpecies().
  • addSpecies() now proceeds with a warning instead of an error when species
    growth stops after maturity (#315).
  • matchBiomasses() and matchNumbers() now provide more informative error
    messages.
  • plotDiet() now restricts the plot to size ranges with meaningful biomass
    density (#317).
  • The wlim and ylim arguments in plotting functions now set the actual axis
    limits instead of just zooming (#320).
  • The legend in plotlyFeedingLevel() is improved when critical feeding level
    is included.
  • species and gears columns are now never factors, so no longer need to
    call as.character() so often.
  • validParams() also calls validGearParams().
  • validParams() checks that w_min is valid for all species and increases it
    if necessary.
  • validSpeciesParams() now also sets default for p to be equal to n.
  • species_params<-() and given_species_params<-() now check that species
    names match.
  • The params argument in l2w() and w2l() has been renamed to species_params
    to follow mizer's convention that params refers to a MizerParams object.

Bug fixes

  • animateSpectra() now uses consistent colours and preserves colour identity
    across frames (#321).
  • getReproductionProportion() no longer returns incorrect proportions > 1 (#299)
  • setResource() now correctly applies the w_pp_cutoff parameter to the
    carrying capacity and initial resource abundance when changed without
    providing resource_capacity(#306).
  • Predation kernels are now truncated as documented.
  • given_species_params() no longer makes unwanted changes to the species
    parameters.
  • steadySingleSpecies() no longer changes time_modified.

Full Changelog: v2.5.3...v2.5.4

v2.5.3

Choose a tag to compare

@gustavdelius gustavdelius released this 17 Oct 16:10

This is a patch release with many small fixes and improvements since the v2.5.0 release.

  • validSpeciesParams() has extra checks on consistency of species parameters.
  • validParams() checks that rate arrays contain finite numeric values.
  • validSim() checks that simulation results are finite and truncates the
    simulation if they are not.
  • Fixed bug that had led newCommunityParams() to set up resource parameters
    differently since version 2.4.0 (#293).
  • addSpecies() now correctly preserves all species_params of the existing
    model.
  • addSpecies() no longer requires new species to grow to maximum size, only
    maturity size is required.
  • Now validGivenSpeciesParams() validates the given species parameters without
    adding defaults and validSpeciesParams() validates and returns a completed
    species parameter dataframe.
  • New species parameter w_repro_max giving the size at which a species
    invests 100% of its energy into reproduction. Set to w_max by default.
  • removeSpecies() now also removes species parameters that are NA for
    all of the remaining species.
  • Changing w_max now also correctly updates ft_mask (#296).
  • compareParams() now also spells out differences in given species parameters.
  • getDiet() now also includes the contribution of the external encounter rate
    to the diet.
  • setPredKernel() now throws an error if some of the required predation kernel
    parameters are NA.
  • In plotYieldGear() one can select a subset of gears with a new gears
    argument.
  • New helper function valid_gears_arg() to check the gears argument in
    functions that take a gears argument.
  • Improved scaling of the y-axis in plotGrowthCurves().
  • steadySingleSpecies() no longer requires species to grow to w_max.
  • matchGrowth() now also rescales the external encounter rate.
  • setExtEncounter() no longer resets the external encounter rate to zero when
    called without the ext_encounter argument.
  • The function plotBiomassObservedVsModel() now plots the ratio of modelled
    to observed biomass as default (ratio = TRUE).
  • The time_modified field is now updated correctly by steadySingleSpecies(),
    setColours() and setLinetypes().
  • Deprecated matchYields() and calibrateYield().
  • project() and projectToSteady(..., return_sim = TRUE) now correctly
    returns also the other components of the MizerSim object stored in n_other.
    #285
  • Improved some unit tests.
  • Some improvements to documentation.

mizer 2.5.0

Choose a tag to compare

@gustavdelius gustavdelius released this 08 Dec 17:42

This release introduces a change that requires you to upgrade your old
MizerParams and MizerSim objects with upgradeParams() or upgradeSim().

External encounter rate

Now the model can include an external encounter rate that represents the
rate at which a predator encounters food that is not explicitly modelled.
This encounter rate is set with setExtEncounter() or ext_encounter<-()
and can be read with getExtEncounter() or ext_encounter(). So this is
similar to how external mortality is handled.

Given versus calculated species parameters

You can now use given_species_params() to see the species parameter
values that you have explicitly specified and calculated_species_params()
to see the species parameter values that mizer has calculated automatically or
set to defaults. You can continue to use species_params() to get all
species parameters, irrespective of whether they were given or calculated.

You can still set parameter values with species_params<-(), but you can also
use the stronger given_species_params<-() which not only sets the values you
give but also triggers a re-calculation of the calculated species parameters.
Using given_species_params<-() is therefore usually the better option.

New mizer course

There is now a three-part mizer course at https://mizer.course.sizespectrum.org
with each part consisting of several tutorials, including code and exercises:

  • Part 1: Understand
    You will gain an understanding of size spectra and their dynamics by exploring simple example systems hands-on with mizer.

  • Part 2: Build
    You will build your own multi-species mizer model for the Celtic sea, following our example. You can also create a model for your own area of interest.

  • Part 3: Use
    You will explore the effects of changes in fishing and changes in resource dynamics on the fish community and the fisheries yield. You will run your own model scenarios.

Other improvements

  • Warnings are given if user gives irrelevant species parameter values.
  • Some messages have been converted to warnings and some to signals that are not
    shown as frequently.
  • Frequent warnings are avoided when length-based and weight-based parameters
    are both given and are inconsistent. #277
  • Documentation of effort argument in project() is improved.
  • An error message is given if a predation kernel returns negative values or
    is everywhere zero. #283

Bug fixes

  • When the coefficient h of the maximum intake rate is not given, it is now
    again given a default value. #282
  • matchGrowth() no longer gives an error when there is no w_inf column. #279

mizer 2.4.0

Choose a tag to compare

@gustavdelius gustavdelius released this 23 Dec 15:41

This release introduces a change that requires you to upgrade your old
MizerParams and MizerSim objects with upgradeParams() or upgradeSim():

Avoid confusion between maximum size and von Bertalanffy asymptotic size

For an explanation see blog post at
https://blog.mizer.sizespectrum.org/posts/2022-11-30-dont-use-von-bertalanffy-growth-parameters/

The species parameter that specifies the size at which also the largest fish stop
growing is renamed from w_inf to w_max. The parameter w_inf is now
reserved for the von Bertalanffy asymptotic size parameter. If you upgrade
your existing MizerParams object with upgradeParams() the w_inf column is
copied over to the w_max column automatically, but you may want to change
the values yourself if they do not currently reflect the maximum size of the
species. Otherwise the size distributions predicted by mizer will not match
observations.

Set resource abundance rather than carrying capacity

The resource parameters kappa and lambda are now used to set the abundance
of the resource in the steady state rather than the carrying capacity, because
the latter is not observable.

While tuning the steady state using the steady() function the resource
abundance is now being kept fixed at the chosen value. Then the resource
dynamics can be switched on later with setResource() without changing the
steady state. At that stage you only choose either the resource intrinsic
growth rate or the resource carrying capacity and the other is determined by
setResource() in such a way that the resource replenishes at the same rate at
which it is consumed. If you want to keep the old behaviour and switch off this
automatic balancing you have to add the balance = FALSE argument when calling
setResource().

You can also choose between semichemostat dynamics resource_semichemostat()
or logistic dynamics resource_logistic() or you can write your own function
implementing more sophisticated resource dynamics.

The setParams() function no longer includes the arguments for setting the
resource parameters. Instead you set these separately with setResource().

Automatically match growth rates

As explained in the blog post at https://blog.mizer.sizespectrum.org/posts/2022-11-30-dont-use-von-bertalanffy-growth-parameters/,
the von Bertalanffy curves fitted to size-at-age
data are not suitable for estimating the size-dependent growth rates in mizer.
It is therefore now recommended that instead of von Bertalanffy parameters you
supply the age at maturity in the age_mat column of the species parameter
data frame. This is then used by mizer to calculate a default for the
maximum intake rate parameter h if you do not supply this.

In the past, whenever you changed any model parameters, you needed to re-tune
other parameters to keep the growth rates in line with observations. There is
now a new function matchGrowth() that automatically scales the search volume,
the maximum consumption rate and the metabolic rate all by the same factor in
order to achieve a growth rate that allows individuals to reach their maturity
size by their maturity age while keeping the feeding level and the critical
feeding level unchanged. This function does not however preserve the steady
state, so you will need to also call steady() after matching the growth rates.

Other improvements

  • New function steadySingleSpecies() that only balances the size-spectrum
    dynamics while ignoring multi-species effects. In other words, it calculates
    the steady-state size spectrum of each species as it would be if the abundance
    of prey and predators could be kept constant at their current values.
  • plotGrowthCurves() can now superimpose a scatterplot of size-at-age data
    if you supply this via the new size_at_age argument.
  • New functions calibrateNumber() and matchNumbers() that are like
    calibrateBiomass() and matchBiomasses() but work with observed numbers
    instead of observed biomasses.
  • New function age_mat() to calculate the age at maturity from the growth
    rate and the size at maturity.
  • If an effort vector or effort array contains NA's, these are now replaced by
    the default effort value. #230
  • The entries of the interaction matrix and of interaction_resource are no
    longer restricted to be less or equal to 1. #232
  • If user supplies no row names in the interaction matrix but gives column names
    then the column names are also used as row names. #247
  • project() now also works when called with a MizerSim object with additional
    components.
  • steady() now preserves the RDD function in the MizerParams object rather
    than always setting it to "BevertonHoltRDD".
  • When averaging abundances over time in plotSpectra() or setInitialValues()
    the user can now choose geometric averaging with geometric_mean = TRUE.
  • The w_mat25 species parameter is no longer filled in automatically if it is
    not supplied. This makes it easier to change w_mat without having to change
    w_mat25 at the same time.
  • compareParams() now also checks the validity of its second argument.
  • Hide the printing of messages about chosen defaults in newTraitParams().
  • Higher values for the info_level argument in newMultispeciesParams() now
    leads to more messages.
  • Giving more helpful messages in validSpeciesParams(). #136
  • New helper functions l2w() and w2l() for converting between length-based
    and weight-based species parameters. #258
  • Check that assessor functions for MizerSim slots are called with a MizerSim
    object.
  • Add style argument to plotDataFrame() to facilitate producing area plots.
  • Add wrap_scale argument to plotDataFrame() to control scaling of axes in
    faceted plots.
  • plotDiet() can now show diets of several predator species in a faceted
    plot. #267
  • Change from size to linewidth aesthetic to avoid warnings in new version
    of ggplot2.
  • Better error message when functions are called with no valid species selected.
    #251
  • If there are no differences then compareParams() says so clearly.
  • getReproductionLevel() works as long as R_max is set. #252
  • Converted several unit tests to edition 3 of testthat package.
  • Improved documentation for gear_params().
  • Improved defaults can now be implemented while keeping backwards compatibility
    via defaults_edition(). #186
  • New defaults edition 2: catchability = 0.3 instead of 1, initial effort = 1
    instead of 0. #243
  • In defaults edition 2, get_gamma_default() ensures a feeding level of f0
    for larvae also if interaction_resource is not equal to 1. #238
  • Set default linecolour and linetype for external mortality.

Bug fixes

  • Restored the line colours to NS_params
  • Comment field now preserved by set_species_default(). #268
  • Comment on w_inf no longer leads to error in plyr::aaply(). #269
  • Can now again set url field in metadata.
  • Correct species now listed in the legend of plotYieldObservedVsModel() and
    plotBiomassObservedVsModel(). #266
  • Standard order for legend in plotDiet() restored after change to ggplot2
    package. #265
  • Fix handling of column names when interaction matrix is read from .csv file.
    #263

mizer 2.3.1

Choose a tag to compare

@gustavdelius gustavdelius released this 06 Jul 16:50
  • Resolved conflict in mizerPredRate() between the argument t and the
    function base::t().
  • Assert that upgradeParams() must be called with a MizerParams object and
    upgradeSim() with a MizerSim object.
  • Errors changed to warnings in getRequiredRDD()
  • renameSpecies() no longer fails when linecolour and linetype are of
    different lengths.
  • matchYields() now also works for a model with only a single species.
  • setInitialValues() can now average over a time_range.
  • getSSB(), getBiomass(), getN(), getYieldGear() and getYield()
    can now be called with a MizerParams object as well as with a MizerSim
    object. (#200)
  • Updated the shiny app in inst/shiny/selectivity_effects to current mizer
    version.

v2.3.0

Choose a tag to compare

@gustavdelius gustavdelius released this 11 Sep 19:42

New features

  • New plots plotBiomassObservedVsModel() and plotYieldObservedVsModel()
    contributed by @SamikDatta., together with their plotly counterparts.
  • New calibrateBiomass(), calibrateYield() to set the model scale to agree
    with total observed biomass or total observed yield. Uses the new
    scaleModel().
  • New matchBiomasses() and matchYields() will try to adjust the abundances
    of the species to produce the observed biomasses or yields.
    See blog post at https://bit.ly/2YqXESV .
  • There are now accessor and replacement functions for rates. So for example
    instead of params <- setReproduction(params, maturity = my_maturity) one
    can simply use maturity(params) <- my_maturity. These are documented
    together with the setter functions. #213
  • New setMetadata() to add information to a MizerParams object describing
    the model, for example a title, a description, the author or list of
    authors, a url and a doi. This will be particularly useful for sharing your
    models with others
  • New saveParams() for saving a MizerParams object to a file and
    readParams() for reading it back in. The resulting files can be shared
    with others who want to run your model.
  • A MizerParams object now registers the mizer version under which the model was
    last saved. Should the model not be working as expected in the current version
    of mizer, you can go back to the older version under which presumably it was
    working. This helps with the reproducibility of your research.
  • A MizerParams object registers the time when it was created and the time it
    was last modified. See getMetadata(). This helps you keep track of
    different versions of your model.
  • steady() now has a preserve argument with possible values erepro,
    R_max or reproduction_level to specify which quantity to preserve.
    This means that one can continue to use steady() also
    once one has started to tune the density dependence in reproduction. #208
  • Our website is now using the nice new mizer logo designed by Kira Askaroff
    (www.kiraaskaroff.com)
  • There is a new mizer extension package
    mizerMR
    allowing you to include multiple resource spectra in your model.

Small improvements

  • The rownames of gear_params are now set to "species, gear", so that one
    can access individual entries with for example
    gear_params(NS_params)["Cod, Otter", "catchability"]. #212
  • The z0 argument of setExtMort() has been deprecated in favour of
    ext_mort in order to avoid confusion with the species parameter z0.
  • setColours() and setLinetypes() now issue warnings when invalid values
    are given and ignores NAs.
  • The experimental comment arguments to the setter functions have been
    removed. #214
  • The setter functions have a new reset argument which, when set to TRUE
    will recalculate the rates from the species_, gear_ and resource_params even
    when custom values had been set. #214
  • The species argument to various functions, which is checked with
    valid_species_arg(), now does not throw an error even when there is no
    valid species included. Only a warning is issued. That means that for
    example plotSpectra(NS_params, species = list(), total = TRUE) is now
    allowed.
  • getComponent() from the mizer extension mechanism now returns NULL when
    asked for a non-existent component instead of giving an error. This gives
    an easy way to check for the existence of a component.
  • The example interaction matrix inter for the North Sea model now has the
    alternative name NS_interaction, with the old name deprecated.
  • Species added with addSpecies() are now by default given a reproduction
    level of 1/4 instead of 0, because at the low densities at which they are
    introduced there would otherwise not be enough density dependence to
    stabilise them.
  • The size range arguments min_w, max_w, min_l and max_l used in some
    summary functions and processed by get_size_range_array() accept vector
    values setting different limits for different species.
  • The resource dynamics function is now also passed the resource_rate and the
    resource_capacity as arguments, which makes it easier to use them in
    extension packages.
  • Species names are now always coerced to strings, even if the user gives them
    as numbers. #202
  • There is a new system for informing the user about how defaults were set by
    newMultispeciesParams(), #199
  • Many improvements in the documentation.
  • Many small improvements to code quality and testing.
  • Better social media cards, especially for twitter.
  • mizer can be run on binder, https://mybinder.org/v2/gh/sizespectrum/mizer/HEAD?urlpath=rstudio

Bug fixes

  • Changing linecolour or linetype in the species parameters now actually
    changes the linecolours and linetypes as intended.
  • Growth curves calculated with getGrowthCurves() and plotted with
    plotGrowthCurves() are now correct, and no longer extend above the
    asymptotic size.
  • plotGrowthCurves() with species_panel = TRUE now respects the species
    argument to only show growth curves for selected species, it works with
    a MizerParams object as well as a MizerSim object, and it shows the panels
    in the correct order. #201
  • Reinstated the example .csv files that were missing from the package because
    the vignettes are no longer included.

v2.2.1

Choose a tag to compare

@gustavdelius gustavdelius released this 24 Jun 06:54
Updated website for version 2.1.1