Skip to content

Export record_given_species_params() so callers can record changes without recalculating - #471

Merged
gustavdelius merged 3 commits into
masterfrom
record-given-params
Jul 29, 2026
Merged

Export record_given_species_params() so callers can record changes without recalculating#471
gustavdelius merged 3 commits into
masterfrom
record-given-params

Conversation

@gustavdelius

@gustavdelius gustavdelius commented Jul 29, 2026

Copy link
Copy Markdown
Member

The gap

species_params<-() does two things: it records the values the caller changed in given_species_params, and it then rebuilds the species parameters and recalculates every size-dependent rate.

Code that fits a species parameter together with the rate array it determines needs the first but not the second. An optimiser that solves for ks and writes the matching metab itself, or for z_ext and the matching mu_b, gets no benefit from the recalculation — and it can be actively wrong, because the recalculation overwrites the arrays the caller just set.

The obvious workaround, writing into the species_params slot directly, avoids the recalculation but loses the recording. The value is then silently reverted the next time anything triggers a recalculation, since it was never marked as given. This failure is quiet: the model keeps running and returns plausible numbers. It bit mizerEcopath in four places — setFeedingLevels() lost its h and ks, and matchCatch() its fitted z_ext and D_ext, as soon as any species parameter was assigned afterwards.

This PR

Extracts the change detection out of species_params<-() into record_given_species_params(given, value, old_sp) and exports it, so that such code can record its changes the same way. It returns the updated given_species_params data frame and does nothing else — no rebuild, no rate recalculation.

sp_before <- species_params(params)
params@species_params$ks[sp_select] <- ks
params@metab[sp_select, ] <- new_metab
params@given_species_params <-
    record_given_species_params(given_species_params(params),
                                species_params(params), sp_before)

species_params<-() now calls the same function, so the matrix/list/S4 column handling added in #465 serves both paths and there is one implementation to maintain rather than two. Behaviour of species_params<-() is unchanged.

Only entries that actually changed are recorded, which is the important part: recording an unchanged value would turn a calculated species parameter into a given one and thereby stop it responding to the parameters it is derived from. The comparison is per species per parameter, so a parameter is protected only for the species whose value moved, and a parameter the caller left alone is never pinned.

Alternative considered

Adding a recalculate = FALSE argument to species_params<-(). That is possible — replacement functions do take extra arguments — but it would not be enough on its own: the method rebuilds the whole table from given_species_params before it calls setParams(), so suppressing only setParams() still re-derives the calculated parameters while leaving the rate arrays they feed stale. A public setter that can return an internally inconsistent object also seemed like the wrong thing to offer.

Testing

Seven new tests in test-species_params.R cover recording, the no-change case, per-species recording, NA treated as a value, a wholly new column, survival of a subsequent recalculation, and the row-count checks. Full suite: 3362 pass, 0 fail.

🤖 Generated with Claude Code

`species_params<-()` records the values a caller changed in
`given_species_params` and then rebuilds the species parameters and
recalculates every size-dependent rate. Code that fits a species
parameter together with the rate array it determines — an optimiser,
say — needs the recording but not the rest, which is at best wasted
work and at worst undoes the caller's own adjustment.

Writing into the `species_params` slot directly avoids the
recalculation but is silently reverted the next time anything triggers
one, because the value was never recorded as given. That failure is
quiet: the model keeps running and returns plausible numbers.

Extract the change detection from `species_params<-()` into
`record_given_species_params()` and export it, so that such code can
record its changes the same way. Only the entries that actually changed
are recorded. Recording an unchanged value would turn a calculated
species parameter into a given one and stop it responding to the
parameters it is derived from, so the comparison is made entry by entry
and a parameter is protected only for the species whose value changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gustavdelius
gustavdelius force-pushed the record-given-params branch from 3f7fb76 to 874f899 Compare July 29, 2026 08:56
@gustavdelius gustavdelius changed the title Add recordGivenParams() to record changed species parameters without recalculating Export record_given_species_params() so callers can record changes without recalculating Jul 29, 2026
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