Ground suspected-case case-finding in contact tracing (headline; merges #389)#400
Open
seabbs-bot wants to merge 9 commits into
Open
Ground suspected-case case-finding in contact tracing (headline; merges #389)#400seabbs-bot wants to merge 9 commits into
seabbs-bot wants to merge 9 commits into
Conversation
Add the situation-report contact-tracing follow-up rate ("taux de suivi
des contacts", 7 June-1 July) as an observed covariate for the non-BVD
suspected-case background, following the case-finding analysis in #374.
Active case-finding scales with the outbreak, so the non-BVD suspect
background has an outbreak-scaled component the calendar-time
background_walk cannot attribute. Scaling on the latent BVD signal would
reopen the p_drc/outbreak-size degeneracy, so the covariate is a fixed
offset on observed data instead.
- data: [contact_followup_history] manifest block + history_float loader
- model: reported_cases_model gains contact_covariate + contact_background_model
coefficient; bg_daily += beta_contact * covariate, threaded through bvd_joint
- expand_covariate helper (interpolate across span, zero outside)
- analysis: sens_contact_bg re-fit (gated by BVD_RUN_SENSITIVITY), reported
on the sensitivity page; news entry
- tests: test_contact_background.jl
Off by default (headline fits pass contact_covariate = nothing).
Co-authored-by: Sam Abbott <contact@samabbott.co.uk>
…374) Per review: the contact-tracing background belongs in the headline model, not a sensitivity toggle, and detection is a rate multiplier, so the covariate should SCALE the background rather than add to it. - multiplicative: bg_daily *= exp(β_contact * z̃), z̃ the follow-up rate mean-centred over its reported days (factor 1 at mean intensity and off-window); β_contact a non-negative log-scale elasticity, HalfNormal(0, 2) - headline: the live joint and frozen fits now pass the covariate (frozen fits truncate it to their cut-off); refit variants inherit it - the gated fit is flipped to sens_no_contact (covariate off) to show the effect on the headline C_T - scales the non-BVD background only, not p_drc, so it stays off the outbreak-size identification path (#374) Updates docstrings, manifest note, news and the sensitivity narrative. Co-authored-by: Sam Abbott <contact@samabbott.co.uk>
In the joint fit the current reproduction number R_T sits below the established R0, while the single-stream fits stay at or above R0. The DRC suspected-case surveillance grows more slowly over June than the confirmed cases (about 2x versus 5.5x), and the suspected likelihood reconciles the two with only a constant ascertainment and a tight background, neither of which can absorb a change in reporting effort over time. The discrepancy is instead carried by the shared reproduction-number walk, which bends R_T down through the one-sided intervention prior; the genetic anchor makes this visible by pinning the outbreak size and age. Add an opt-in reporting-effort multiplier (reporting_effort_walk_model): a smooth weekly log random walk centred at one that scales the suspected-case expected counts only, not the shared onset-to-report series the laboratory, treatment and death streams reuse, so it is identified by the suspected-versus -rest discrepancy. A suspected-specific reporting slowdown is then carried by effort rather than by R_T. Off by default (suspected_reporting_effort = false), so the headline fit is unchanged and sigma_eff -> 0 recovers the constant ascertainment exactly. Add a gated sensitivity re-fit (sens_reporting_effort) and a reporting-effort section on the sensitivity page comparing R_T with and without the term, plus tests.
…nfirmed overdispersion) Resolve overlap in docs/src/news.md by keeping both v1.8.0 Model entries. Code files (priors.jl, observations.jl, BVDOutbreakSize.jl, registry.jl) auto-merged; the reporting-effort term and main's confirmed-overdispersion change are independent and coexist.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #400 +/- ##
==========================================
+ Coverage 87.50% 88.33% +0.83%
==========================================
Files 13 13
Lines 2433 2530 +97
==========================================
+ Hits 2129 2235 +106
+ Misses 304 295 -9 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
PR #397 replaced the plain Binomial confirmed-case likelihood with a BetaBinomial, leaving Binomial imported but unused. ExplicitImports' check_no_stale_explicit_imports flags it on Julia 1.12 (the Test matrix's Julia 1 jobs), failing the quality tests on main and on any branch merged from it. Remove the unused import.
Contributor
|
📖 Documentation preview is ready! View the docs for this PR at: http://epiforecasts.io/BVDOutbreakSize/previews/PR400/ This preview will be updated automatically when you push new commits. |
…erge #389) Merge the contact-tracing branch (#389) and unify it with the reporting-effort work into one headline change: the observed contact-tracing follow-up rate drives BOTH channels case-finding acts through. - Latent follow-up-rate process (contact_tracing_model): the daily "taux de suivi des contacts" is modelled as a logistic random walk q_t over the whole grid, fitted to the reported rate where it exists. Being latent everywhere it is inferred before the reported window and PROJECTS INTO FORECASTS under its own dynamics rather than a fixed covariate stopping with the data. - The non-BVD background scales with it (exp(β_contact·(q−q̄)), contact_background_model), and the BVD suspected ascertainment carries a reporting-effort multiplier anchored to the same rate plus a random-walk deviation (exp(β_asc·(q−q̄)+w), reporting_effort_walk_model). Both touch the suspected likelihood only, not the shared onsets or p_drc, so no ascertainment / outbreak-size confounding (#374). - Headline: the live joint and every frozen re-fit pass the follow-up history and suspected_reporting_effort = true. Empty history / flag off recover the prior model. - Sensitivity re-fits sens_no_contact (drop the grounding) and sens_no_effort (drop the ascertainment effort) on the sensitivity page; the main analysis reports the contact-tracing grounding of the reproduction number. - Also carries #389's confirmed-case BetaBinomial overdispersion (from main). Supersedes the fixed-covariate form in #389 with the forecast-safe latent process. Tests: test_contact_background.jl, test_reporting_effort.jl.
Add the BVD-ascertainment elasticity to contact tracing (β_asc) and its random-walk SD to the surveillance-parameter summary, alongside the non-BVD background elasticity, so the headline table shows both case-finding channels.
Collaborator
|
This doesn't converge so we can't merge. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ground suspected-case case-finding in contact tracing (headline)
This began as an investigation into why the joint fit's reproduction number is
pulled down relative to the single-stream fits (leave-one-out traced it to the
DRC suspected surveillance reconciling a suspected-vs-confirmed growth conflict
through the reproduction-number walk, because the suspected stream had only a
constant ascertainment to absorb a change in case-finding effort). It now
merges and unifies with the contact-tracing work in #389 into a single headline
change: the observed contact-tracing follow-up rate drives both channels
case-finding acts through.
Model
contact_tracing_model). The daily"taux de suivi des contacts" is modelled as a logistic random walk
q_t ∈ (0,1)over the whole grid, fitted to the reported rate where it exists.Because it is latent everywhere it is inferred before the reported window and
projects into forecasts under its own dynamics rather than a fixed
covariate stopping at the data boundary (so the case-finding anchor does not
drop out when the data stop).
exp(β_contact·(q−q̄))(
contact_background_model, from feat(model): add contact-tracing background covariate (#374) #389).to the same rate plus a random-walk deviation,
exp(β_asc·(q−q̄) + w)(
reporting_effort_walk_model). Both touch the suspected likelihood only, notthe shared onsets or
p_drc, so neither moves the outbreak size (Testing & case-finding operations vs model: retesting/rule-out and background scaling #374).follow-up history with
suspected_reporting_effort = true. Empty history /flag off recover the prior model. Also carries main's confirmed-case
BetaBinomialoverdispersion.What the fits show (300 draws × 2, confirmatory)
scales detection of non-BVD (
β_contact ≈ 3.5) and BVD (β_asc ≈ 0.5)suspects.
C_Tis unchanged across the three (~5000), so thecase-finding channels re-shape the suspected reporting without moving the
size — no ascertainment / outbreak-size confounding.
from 22 (free walk) to 4: the observed anchor identifies the ascertainment
change far better than a free walk, so the grounded model is both more
defensible and better-behaved.
Analysis and sensitivity
number and the two elasticities (
background_contact_coef,β_asc).sens_no_contact(drop the grounding) and
sens_no_effort(drop the ascertainment effort),each compared to the headline for
R_TandC_T.Files
src/models/priors.jl—contact_tracing_model(latent rate),contact_background_model(feat(model): add contact-tracing background covariate (#374) #389),reporting_effort_walk_model(anchored).src/models/observations.jl— unified latent-qscaling of background andascertainment in
reported_cases_model.src/models/joint.jl—contact_followup_history+suspected_reporting_effortwiring;background_contact_coefdeterministic.src/data.jl,data/observations.toml— the follow-up-rate stream (feat(model): add contact-tracing background covariate (#374) #389).docs/fits/registry.jl,docs/examples/{_setup,analysis,sensitivity}.jl,docs/src/news.md,test/test_{contact_background,reporting_effort}.jl.Supersedes the fixed-covariate form in #389 with the forecast-safe latent
process; #389 can close in favour of this.
This was opened by a bot. Please ping @seabbs for any questions.