Skip to content

Declare the predictor prior scale - #350

Merged
beckyfisher merged 2 commits into
devfrom
issue-317-predictor-scale
Sep 15, 2026
Merged

beckyfisher merged 2 commits into
devfrom
issue-317-predictor-scale

Conversation

@beckyfisher

@beckyfisher beckyfisher commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

What

Adds an explicit predictor_scale declaration to the default-prior routes. A user who supplies an already logged predictor can now select predictor_scale = "log", including when every value is non-negative. "concentration" makes the recorded-concentration interpretation explicit, and "auto" retains the existing sign-based choice.

Closes #317.

Why it matters

The nec and ec50 prior no longer has to depend on the units used to record an experiment. On the declared log scale, log(1) = 0 remains a tested predictor value rather than being discarded as a zero control.

Scientific decision

No property of a numeric column can distinguish precomputed logged values from recorded concentrations. The new declaration is therefore explicit. The default remains "auto" so existing calls and published analyses retain their priors.

"log" keeps every distinct supplied value and builds the existing normal prior on that scale. "concentration" omits zero controls, logs the positive concentrations, and builds the existing lognormal prior. It refuses negative values before any model or grouped level is fitted. The historical uninformative widths remain unchanged: 10 * sd(x) on an already logged predictor and the 95% coverage width on recorded concentrations. The "regularizing" set retains its 98% coverage rule.

Validation

Implementation detail

The declaration is passed through bnec(), get_priors(), amend(), bnec_group(), factorised hurdle fits and joint hurdle/zero-inflated prior construction. validate_predictor_scale() centralises the accepted values and checks a declared concentration scale before model or group loops. predictor_prior() repeats the validation as a backstop for internal routes.

The internal vector previously named predictor_scale was renamed prior_predictor; it represents the whole predictor used to prime and bound both blocks of a joint fit, not the user's scale declaration.

@beckyfisher

Copy link
Copy Markdown
Collaborator Author

The PR body was updated to include the factorised hurdle preflight coverage and its zero-component-call regression tests.

@beckyfisher

Copy link
Copy Markdown
Collaborator Author

Independent review completed after two cycles.

One real problem was found in the original PR: factorised hurdle fits and amendments validated the growth and survival components sequentially. If negative predictor values occurred only among deaths, the growth component could begin sampling before the survival component rejected predictor_scale = "concentration".

This is fixed by validating the complete predictor before either component call and explicitly forwarding the validated declaration to both components. Regression tests now verify that invalid full predictors cause zero component calls. The reviewer independently reproduced the corrected behaviour and found no remaining defects on re-review.

@beckyfisher
beckyfisher merged commit 63e1308 into dev Sep 15, 2026
5 checks passed
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