Skip to content

Epidemiological metrics for netdiffuseR#79

Draft
aoliveram wants to merge 22 commits intomasterfrom
issue-78-epidemiological-metrics
Draft

Epidemiological metrics for netdiffuseR#79
aoliveram wants to merge 22 commits intomasterfrom
issue-78-epidemiological-metrics

Conversation

@aoliveram
Copy link
Copy Markdown
Member

Refs #78.

This draft PR tracks the implementation of epidemiological analysis capabilities in netdiffuseR, addressing the four gaps identified in the internal gap report:

  • Gap 1 — no support for time-of-disadoption (tod) / reinfection episodes.
  • Gap 2 — missing epi metrics (SAR, survival, peak, generation time, Rₜ).
  • Gap 3 — no transmission-tree representation.
  • Gap 4 — stochastic transmission / adoption (partially covered by the pre-existing stochastic-transmission branch, now integrated here).

This branch starts from master and has already integrated two upstream feature branches:

  • issue-75-epigames-dynamic-attrs — dynamic behavioral attributes for Epigames.
  • stochastic-transmissionmode = "stochastic" for exposure() / rdiffnet().

No new dependencies will be added to DESCRIPTION.

Implementation milestones

# Milestone Files touched
M1 Infra: \$tod slot, \$transmission slot, validators, coercions R/diffnet-class.r, R/adjmat.r, new R/transmission.R
M2 Gap 4A: pluggable link_fun in exposure() R/stats.R
M3 Gap 4B: continuous-weight regression tests tests/testthat/
M4 Gap 4C: adoption_model = \"logit\" in rdiffnet() R/rdiffnet.r
M5 Gap 2 easy: SAR, survival, peak, generation_time new R/epi_metrics.R
M6 Gap 1: hazard_rate(), plot_adopters() under \$tod R/stats.R, R/diffnet-methods.r
M7 Gap 2 repr_number: repr_number() + plot method R/epi_metrics.R
M8 Epigames parser: histories.csv → \$transmission data-raw/
M9 Vignette vignettes/epidemiological-analysis.Rmd new vignette
M10 Docs + CI + pkgdown tests/testthat/, .github/workflows/

…ion to 1.25.0, and fix exposure rownames issue
…Issue #75)

- Add data-raw/epigames.R: bundles epigames_hourly + dynamic_attrs_hourly.csv
  into epigames list with new $dyn_attrs slot (long format, 201,366 rows)
- Add data-raw/epigamesDiffNet.R: collapses hourly attrs to 15 daily windows,
  populates vertex.dyn.attrs with mask/med/quarantine proportions per day
- Regenerate data/epigames.rda and data/epigamesDiffNet.rda

Dynamic attributes (mask, med, quarantine) now visible in print(epigamesDiffNet):
  Dynamic attributes: mask, med, quarantine (3)

Validated: exposure(epigamesDiffNet, attrs = 'mask') works with time-varying
data. Correlation with static proxy = 0.88, confirming dynamic attrs
capture additional temporal variation.
- Removed redundant comments and sanity checks for better readability
- Simplified as_diffnet call structure
- Regenerated .rda files to match clean scripts
- new_diffnet() gains a -tod- argument (single-behavior vector) with
  validation (element-wise tod > toa, NA where toa is NA, length match).
- When -tod- is supplied, cumadopt is reconstructed from the intervals
  [toa, tod - 1] via cumadopt_from_intervals() in R/adjmat.r.
- New $transmission slot plus exported helpers as_transmission_tree()
  and get_transmissions() (R/transmission.R) storing the directed
  infection forest as a data.frame with columns date, source, target,
  source_exposure_date, virus_id, virus. Docs cite Lloyd-Smith et al.
  (2005) and White & Pagano (2008).
- Tests cover interval reconstruction, validation errors, coercion,
  and the transmission slot round-trip.

No new package dependencies.
@aoliveram aoliveram changed the title Epidemiological metrics for netdiffuseR (#78) Epidemiological metrics for netdiffuseR Apr 17, 2026
aoliveram and others added 4 commits April 17, 2026 17:13
Avoid masking epiworldR::get_transmissions() when both packages are
loaded. No behavior change; exported name and docs renamed, tests
updated accordingly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds link_fun + link_pars arguments to exposure(). Supported named
kernels: identity (default), linear (min(beta*w, 1)), sigmoid
(plogis((w-h)/scale)), wells-riley (1 - exp(-beta*w)). Custom user
functions are accepted with either signature function(w) or
function(w, pars). Non-identity kernels force valued = TRUE with a
warning. Default behavior unchanged; 639 pre-existing tests still pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ange weights (M3, #78)

Adds four test_that blocks to tests/testthat/test-stochastic-exposure.R
covering each link kernel under seconds-scale weights, the
degree-denominator fix, and zero-weight self-loop handling. Small code
changes in R/stats.R: (1) warn when stochastic mode sees post-kernel
weights outside [0, 1] -- the sampler silently saturated before;
(2) denominator now counts non-zero-weight neighbours instead of every
stored entry, so link kernels that zero out some edges no longer
inflate the normaliser. No NAMESPACE / Rd changes. 652 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Drop the dual signature for user-supplied link_fun. The helper now
always calls `link_fun(W@x)` with a single argument; parameters are
expected to be baked into the closure. `link_pars` remains relevant
only for the named kernels ("linear", "sigmoid", "wells-riley").
Simpler API, simpler docs, simpler tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@aoliveram aoliveram requested a review from gvegayon April 20, 2026 15:57
@aoliveram aoliveram self-assigned this Apr 20, 2026
Adds adoption_model = c("threshold", "logit") and adoption_pars
arguments to rdiffnet(). In logit mode, node i adopts at step t with
probability plogis(beta0 + beta_expo * exposure_i), drawn from
runif() each step. Threshold stays the default so fixed-seed calls
that omit the new argument remain bit-identical.

15 new tests cover backward compatibility, parameter validation,
saturation / suppression extremes, and multi-behaviour runs. Full
suite: 665 pass, 0 fail.
…tic/stochastic (M4 follow-up, #78)

Renames the two values accepted by adoption_model in rdiffnet() so
the vocabulary matches the existing exposure.mode (which already
uses deterministic/stochastic). No behavior change:
  - adoption_model = c("deterministic", "stochastic"), default
    "deterministic" (was "threshold")
  - "stochastic" keeps the same plogis(beta0 + beta_expo * exposure)
    Bernoulli draw previously called "logit"
  - Error message, roxygen doc and man page updated to match
  - Test file renamed test-rdiffnet-logit.R -> test-rdiffnet-stochastic.R;
    all 15 existing expectations updated to use the new names

Full suite: 665 passed, 0 failed.
@aoliveram
Copy link
Copy Markdown
Member Author

aoliveram commented Apr 22, 2026

The milestones tabla have been updated, following @gvegayon's comments:

# Milestone Status Notes
M1 $tod vector + $transmission slot, validators landed $tod part reformulated in M5; $transmission part migrates to M7
M2 Pluggable link_fun in exposure() landed no changes
M3 Continuous-weight tests + safety warnings landed no changes
M4 adoption_model string API landed superseded by M6
M5 $status array as canonical representation. as_diffnet(graph, toa) intact; as_diffnet(graph, status) added for multi-cycle. tod argument removed from constructor before merge planned R/diffnet-class.r, R/adjmat.r
M6 adoption_mechanism as function. Exports adoptmech_threshold, adoptmech_logit, adoptmech_probit planned R/rdiffnet.r, new R/adoption_mechanisms.R
M7 diffnet_epi subclass + as_diffnet_epi() planned new R/diffnet-epi.R
M8 Native lineage tracking in rdiffnet() via source_attribution callback with _uniform / _weighted / _earliest; auto-promotes to diffnet_epi + adoption_mechanism extension: pass behavior = q and expo_all` (n × 1 × Q) to enable per-behavior coupling planned R/rdiffnet.r, new R/source_attribution.R, update R/adoption_mechanisms.R
M9 plot_transmission_tree() for diffnet_epi — first goal: unambiguous cases planned new R/plot_transmission_tree.R
M10 SAR, survival, peak, generation_time (diffnet_epi methods) planned new R/epi_metrics.R
M11 hazard_rate() and plot_adopters() status-aware planned R/stats.R, R/diffnet-methods.r
M12 repr_number() + offspring plot planned R/epi_metrics.R
M13 Epigames histories.csv parser → $transmission planned new data-raw/ helper
M14 Vignette epidemiological-analysis.Rmd planned new vignettes/
M15 Docs + CI + pkgdown planned tests/, .github/workflows/

Order of execution: M6 → M5 → M7 → M8 → M9 → M10+.

…M4 -adoption_model = c('deterministic', 'stochastics'). Bumps version 1.25.0 -> 1.26.0
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