Skip to content

Add getMeanLength() and report the weight-length defaults - #576

Merged
gustavdelius merged 2 commits into
masterfrom
getMeanLength-and-length-weight-defaults
Aug 27, 2026
Merged

Add getMeanLength() and report the weight-length defaults#576
gustavdelius merged 2 commits into
masterfrom
getMeanLength-and-length-weight-defaults

Conversation

@gustavdelius

Copy link
Copy Markdown
Member

getMeanLength()

The counterpart of getMeanWeight(), sharing its man page under the new title
Calculate the mean size of the community. It divides the total length of all
individuals in the selected species and size range by their number:

$$\bar l = \frac{\sum_i \int N_i(w),(w/a_i)^{1/b_i},dw}{\sum_i \int N_i(w),dw}$$

The integral goes through sizeIntegral() with the species × size length matrix
as the weighting factor, so the size-range mask, the bin-averaging under
second_order_w(bin_average = TRUE) and the MizerParams/MizerSim shape
handling all come for free, and the bin integral is still performed in exactly
one place. Methods for both classes, plus the internal helper
length_at_size(), which errors if a/b are missing or NA as
get_size_range_array() does.

Reporting the weight-length defaults

Writing that showed a = 0.01 and b = 3 were being filled in silently.

At the point the default is filled inspecies_params.data.frame() now
passes a message to set_species_param_default(), which is the existing
mechanism (signal_info(), severity = "info", level = 3), so the report
sits alongside the ones for h, gamma and ks:

i No `a` column so using a = 0.01 in w = a l^b, with w in g and l in cm.
i No `b` column so using the isometric default b = 3 in w = a l^b.

At the point the conversion happenscalc_selectivity() reports a gear
whose selectivity is set from a length while the species' a or b was
defaulted. That is the case where an invented weight-length relationship changes
the dynamics rather than just a diagnostic, so it is level = 1 (survives the
setting that silences the routine chatter) and unhandled = "show" (both
setFishing() and calc_selectivity() are exported and get called outside any
with_info_level()). It names only the affected species and only the parameter
that was actually missing. Whether a gear selects on length is read off the
selectivity function's formals — mizer hands a selectivity function the species
parameters only so it can convert between length and weight — so a custom
sel_func taking species_params is covered, and knife_edge /
sigmoid_weight never trigger it.

Why it is worth saying: a = 0.01, b = 3 with weights in grams and lengths in
cm is Fulton's K = 1, the textbook fusiform fish. The exponent is a good
default, but a follows body shape over about two orders of magnitude. Against
the twelve North Sea species shipped with mizer (fitted a = 0.001–0.010,
b = 2.94–3.43) the default gives lengths 1–42% short at a weight of 1 g — 35%
short for the eel-like Sandeel.

Documentation

  • NEWS.md; new section in inst/skills/upgrade-mizer-code/references/mizer-3.4.md
    with two rows in the symptom index; getMeanLength() added to the
    analyse-and-plot skill and quick reference; inst/llms.txt / docs/llms.txt;
    guides regenerated with build_guides().
  • Corrects inst/skills/build-model/SKILL.md, which said the defaults were
    0.006 and 3 — wrong since 0b5b661 introduced a = 0.01, and it feeds the
    published guide.

Testing

devtools::test() on this commit: FAIL 0 | WARN 0 | SKIP 49 | PASS 4937.
New tests in test-indicator_functions.R (MizerSim and MizerParams against
hand-rolled sums, the min_l/min_w equivalence, the a = b = 1 case where
mean length must equal mean weight, both error paths), test-second_order_summary.R
(the required bin_average = TRUE test), test-species_params.R and
test-setFishing.R (the two reports, and silence when the parameters are
supplied or the gear selects on weight).

🤖 Generated with Claude Code

gustavdelius and others added 2 commits August 27, 2026 13:14
getMeanLength() is the counterpart of getMeanWeight() and shares its man
page, now titled "Calculate the mean size of the community". It divides
the total length of all individuals in the selected species and size
range by their number, converting weight to length with each species'
`a` and `b`. The integral goes through sizeIntegral(), so it follows the
model's own quadrature and is tested under both schemes.

Writing it showed that the length-weight defaults `a = 0.01` and `b = 3`
were filled in silently. They are now reported like mizer's other
defaults, and setFishing() reports them a second time when a gear
selects on length, which is the case where an invented weight-length
relationship changes the dynamics rather than just a diagnostic. Whether
a gear selects on length is read off the selectivity function's formals,
so a custom sel_func taking species_params is covered too.

Also corrects the build-model guide, which said the defaults were 0.006
and 3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Over the full size range the mean is dominated by the larvae, and for
the mean length it extrapolates the length-weight relationship far below
the sizes it was fitted to. Say so on the man page and lead the examples
with a minimum size, which is also what makes the indicator comparable
to one calculated from survey data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gustavdelius
gustavdelius force-pushed the getMeanLength-and-length-weight-defaults branch from 62ca04c to e231409 Compare August 27, 2026 12:16
@gustavdelius
gustavdelius merged commit c7ee4c9 into master Aug 27, 2026
@gustavdelius
gustavdelius deleted the getMeanLength-and-length-weight-defaults branch August 27, 2026 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant