Skip to contents

Fits a lognormal prior, truncated below at 1, for the per-person-per-day symptomatic-to-asymptomatic shedding ratio \(\zeta_{\mathrm{ratio}} = \zeta_1 / \zeta_2\) used in sample_parameters() to derive \(\zeta_2 = \zeta_1 / \zeta_{\mathrm{ratio}}\) at sampling time. The truncation (lower = 1, applied by sample_from_prior()) is what makes \(\zeta_2 \le \zeta_1\) hold for every draw; see Details.

Usage

est_zeta_ratio_prior(
  PATHS,
  zeta_1_fit = NULL,
  zeta_2_fit = NULL,
  n_sim = 100000L,
  seed = 1L,
  diagnostic_candidate_fits = FALSE
)

Arguments

PATHS

A list of paths generated by get_paths(). Must include:

  • MODEL_INPUT: directory where parameter CSVs are saved.

  • DOCS_FIGURES: directory where the summary figure is saved.

zeta_1_fit

Either NULL, the full list returned by est_zeta_1_prior(), or the $fit sublist with at least meanlog and sdlog. If NULL, est_zeta_1_prior(PATHS) is called internally.

zeta_2_fit

Same contract as zeta_1_fit; calls est_zeta_2_prior(PATHS) if NULL.

n_sim

Integer. Monte-Carlo sample size for the derived channel. Default 100000L.

seed

Integer. Random-number seed for reproducible paired-bootstrap MC. Default 1L. Byte-equality of the written priors_default.json across builds requires an identical seed.

diagnostic_candidate_fits

Logical. If TRUE, attempt skew-normal / Student-t / generalised-normal diagnostic fits via fitdistrplus. Default FALSE. Requires the optional fitdistrplus package; if the package is not installed a message is emitted and $diagnostics$candidate_fits remains NULL.

Value

Invisibly returns a list with elements:

  • data: direct-literature anchor table (Table 7.A).

  • fit: the shipped direct-channel (A) prior: meanlog and sdlog of the untruncated lognormal, the truncation bound lower (= 1), the median, mode, mean, ci_lower and ci_upper of the truncated distribution that is sampled, and p_below_1 (the untruncated mass below 1 that the truncation removes).

  • param_df: long-format parameter data frame (as saved to disk).

  • prediction: density grid for the direct, derived and combined channels (tagged via the channel column).

  • diagnostics: a list with fit_direct, fit_derived, fit_combined, ratio_sample (paired-bootstrap MC draws on the log10 scale), analytic_check (independent-lognormal closed form, cross-check only), and candidate_fits.

Details

The function produces THREE candidate lognormal fits. The direct channel (A) is the shipped prior: it is returned as $fit, written to param_zeta_ratio_prior.csv, and stored by data-raw/make_priors_default.R in priors_default$parameters_global$zeta_ratio.

  • (A) Direct channel (shipped): weighted-MLE lognormal on literature ratio anchors (Smith 2026 medRxiv, Nelson 2009 paired, Kaper 1995, Harris 2012, Chao 2011, Finger 2018, Righetto 2012, Sugimoto 2014, MOSAIC calibration).

  • (B) Derived channel: paired Monte-Carlo lognormal from the fitted \(\zeta_1\) / \(\zeta_2\) marginals, with a paired-bootstrap step on the shared Nelson 2009 anchor.

  • (C) Combined: precision-weighted (inverse-variance) lognormal combination of (A) and (B). Diagnostic only since 2026-04-23 (returned in $diagnostics$fit_combined): its median (~2e5) is driven by the stool-concentration anchors and overestimates the ratio relative to the household-transmission and modelling-convention evidence (Smith 2026 ~1.6x, Chao 2011 / Finger 2018 ~10).

Direct channel (A). Weighted MLE on log10 of the literature ratio anchors in the direct-ratio table. The anchors span ~1.6x (Smith 2026 household per-person-day) to ~10^5 (Nelson 2009 paired stool concentrations). This spread reflects genuinely different quantities (household transmission probability vs stool concentration ratio) and is preserved in the fit's sdlog.

Derived channel (B). If \(\zeta_1 \sim \mathrm{LN}(\mu_1, \sigma_1^2)\) and \(\zeta_2 \sim \mathrm{LN}(\mu_2, \sigma_2^2)\) are independent, their ratio is exactly \(\mathrm{LN}(\mu_1 - \mu_2, \sigma_1^2 + \sigma_2^2)\). The derived channel uses this analytic closed form directly. Nelson 2009 is a shared primary source for both marginals, which would in principle induce positive correlation and reduce the ratio's variance, but correctly propagating that requires decomposing each marginal's variance into a Nelson-attributable component and a residual independent component – a subjective attribution that is not well-supported by the available literature. The closed-form variance \(\sigma_1^2 + \sigma_2^2\) is therefore a conservative upper bound on the true derived-channel spread. A 100,000-draw Monte Carlo sample of the ratio distribution is generated for the diagnostic figure and returned in $diagnostics$ratio_sample; it does not enter the fit statistics.

Truncation at 1. The direct channel is wide (the anchors span ~1.6x to ~10^5), so the untruncated lognormal puts a non-trivial share of its mass below 1 ($fit$p_below_1, about 0.16 at the v0.100.0 anchors), inherited from the Smith 2026 household odds-ratio interval (0.11-3.23). Such draws would give \(\zeta_2 > \zeta_1\), which contradicts the shedding biology the model encodes: symptomatic stool carries \(10^5\)-\(10^8\) cells/mL at up to litres per day (the est_zeta_1_prior() anchors), while asymptomatic carriers shed about \(10^3\) (Nelson 2009) to \(10^5\) (Kaper 1995) cells per gram of formed stool (the est_zeta_2_prior() anchors), and the model description samples the ratio precisely to rule out \(\zeta_1 < \zeta_2\). The Smith 2026 interval concerns household transmission odds, not per-day shedding, so it does not license ratios below 1. The shipped prior is therefore the direct-channel lognormal truncated below at 1 (lower = 1): its meanlog/sdlog are unchanged and the removed mass is redistributed proportionally over \(\zeta_{\mathrm{ratio}} \ge 1\), which moves the median up (to $fit$median).

Combined channel (C). Given direct and derived fits \(\mathrm{LN}(\mu_A, \sigma_A^2)\) and \(\mathrm{LN}(\mu_B, \sigma_B^2)\), the precision-weighted mean on the log scale is $$\mu_C = \frac{\mu_A / \sigma_A^2 + \mu_B / \sigma_B^2}{1/\sigma_A^2 + 1/\sigma_B^2}, \quad \sigma_C = \left(1/\sigma_A^2 + 1/\sigma_B^2\right)^{-1/2}$$ This is the Bayesian posterior for the log-ratio under flat priors when both channels are treated as independent normal likelihoods.

Smith 2026 dose-response note. Smith et al. 2026 (medRxiv) report an odds ratio of 0.60 (95 percent CI 0.11-3.23) for household transmission with asymptomatic vs symptomatic index cases, giving an inverse transmission ratio of ~1.6. Under a near-linear Hill dose-response regime and equal contact patterns this is compatible with a low per-person-per-day zeta_ratio. The value is included at weight 0.5 alongside Nelson's 10^5 stool-concentration ratio so the reader can see the tension.

fitdistrplus dependency. This function does NOT import fitdistrplus. If diagnostic_candidate_fits = TRUE the package is loaded via requireNamespace() with a graceful fallback; this follows the pattern at R/est_initial_R.R:704-710.

References

  • Smith CP, Lessler J, Hegde ST, et al. (2026). Estimating the transmission potential of symptomatic and asymptomatic cholera cases from household microbiological and clinical data. medRxiv.

  • Nelson EJ, et al. (2009). Nat Rev Microbiol 7(10):693-702.

  • Chao DL, Halloran ME, Longini IM (2011). Vaccination strategies for epidemic cholera in Haiti. PNAS 108(17):7081-85.

  • Finger F, Bertuzzo E, Luquero FJ, et al. (2018). The potential impact of case-area targeted interventions in response to cholera outbreaks. PLoS Med 15(2):e1002509.

  • Righetto L, Casagrandi R, Bertuzzo E, et al. (2012). The role of aquatic reservoir fluctuations in long-term cholera patterns. Epidemics 4(1):33-42.

  • Sugimoto JD, Koepke AA, Kenah E, et al. (2014). Household transmission of V. cholerae in Bangladesh. PLoS NTD 8(11):e3314.

  • Kaper JB, Morris JG, Levine MM (1995). Cholera. Clin Microbiol Rev 8(1):48-86.

  • Harris JB, et al. (2012). Cholera. Lancet 379(9835):2466-76.

Examples

if (FALSE) { # \dontrun{
PATHS <- get_paths()
z1 <- est_zeta_1_prior(PATHS)
z2 <- est_zeta_2_prior(PATHS)
est_zeta_ratio_prior(PATHS, zeta_1_fit = z1, zeta_2_fit = z2)
} # }