Epidemiological linkage inference from temporal and genetic data with an E/P/I infectiousness model.
Project description
EpiLink
EpiLink scores how compatible a pair of samples is with recent transmission scenarios using sampling-time differences and consensus genetic distance.
It is useful when you have:
- a sampling-time difference in days
- a consensus genetic distance in mutations
- a question like "is this pair more compatible with direct transmission or a recent shared ancestor?"
EpiLink returns per-scenario compatibility scores and can also sum scores across a user-defined target subset such as ["ad(0)", "ca(0,0)"].
Installation
Clone the repository first if you are starting from GitHub:
git clone https://github.com/ydnkka/epilink.git
cd epilink
The repository environment is the easiest way to get everything needed for the package, examples, and simulation helpers:
conda env create -f environment.yml
conda activate epilink
If you prefer pip:
python -m pip install -e .
python -m pip install networkx pandas
EpiLink requires Python 3.10 or newer.
Scenario labels
ad(0): direct ancestor-descendant transmissionad(1): ancestor-descendant transmission with one hidden intermediateca(0,0): a recent shared common ancestor with one branch to each sampled caseca(m_i,m_j): a common-ancestor scenario withm_iandm_jhidden generations on each branch
maximum_depth controls how many of these latent scenarios are generated.
Which method to use
score_pair(...): one observed pair, plus a full per-scenario breakdownscore_target(...): only the target score, for scalar or array inputspairwise_model(...): a cached scorer for repeatedly evaluating the same target subset
Each individual scenario compatibility lies in [0, 1]. If target contains multiple scenarios, target_compatibility is the sum across that subset, so it can be greater than 1.
Quick start
from epilink import EpiLink, InfectiousnessToTransmission
profile = InfectiousnessToTransmission(rng_seed=2026)
model = EpiLink(
transmission_profile=profile,
maximum_depth=2,
mc_samples=20000,
target=["ad(0)", "ca(0,0)"],
mutation_process="stochastic",
)
result = model.score_pair(
sample_time_difference=3.0,
genetic_distance=2.0,
)
print(result["target_labels"])
print(result["target_compatibility"])
print(result["scenario_scores"]["ad(0)"]["compatibility"])
More examples
Score only a target subset
Use score_target when you only care about the combined score:
score = model.score_target(
sample_time_difference=3.0,
genetic_distance=2.0,
target=["ad(0)", "ad(1)", "ca(0,0)"],
)
print(score)
Use Scenario objects instead of strings
from epilink import Scenario
score = model.score_target(
sample_time_difference=3.0,
genetic_distance=2.0,
target=[
Scenario(kind="ad", intermediates=0),
Scenario(kind="ca", branch_to_i=0, branch_to_j=0),
],
)
Score many pairs at once
score_target and pairwise_model broadcast NumPy inputs, so you can score a whole grid or batch efficiently:
import numpy as np
pairwise = model.pairwise_model(target=["ad(0)", "ca(0,0)"])
time_differences = np.array([[0.0], [2.0], [4.0]])
genetic_distances = np.array([[0.0, 1.0, 2.0, 3.0]])
scores = pairwise(time_differences, genetic_distances)
print(scores.shape) # (3, 4)
Build a toy simulated pair table
The simulation helpers are useful for generating synthetic examples and benchmarking downstream workflows:
import networkx as nx
from epilink import (
build_pairwise_case_table,
simulate_epidemic_dates,
simulate_genomic_sequences,
)
tree = nx.DiGraph(
[
("case-0", "case-1"),
("case-0", "case-2"),
]
)
dated_tree = simulate_epidemic_dates(profile, tree, fraction_sampled=1.0)
simulated = simulate_genomic_sequences(profile, dated_tree, genome_length=500)
pair_table = build_pairwise_case_table(simulated["packed"], dated_tree)
print(pair_table.head())
Mutation models
mutation_process="deterministic"compares the observation with expected mutation countsmutation_process="stochastic"compares the observation with Poisson mutation-count draws
The stochastic option is usually the better choice when you want mutation-count variability to be part of the score.
Background and model characteristics
- Manuscript: docs/assets/epilink.pdf
- Latent histories: docs/assets/epilink_scenarios.svg
- Workflow figure: docs/assets/epilink_schematic.svg
- Notebook: docs/epilink_characterisation.ipynb
Citation
If you use EpiLink in research, please cite the software metadata in CITATION.cff. The underlying infectiousness model is:
- Hart WS, Maini PK, Thompson RN. High infectiousness immediately before COVID-19 symptom onset highlights the importance of continued contact tracing. eLife. 2021;10:e65534. http://dx.doi.org/10.7554/eLife.65534
License
MIT. See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file epilink-0.1.3.tar.gz.
File metadata
- Download URL: epilink-0.1.3.tar.gz
- Upload date:
- Size: 1.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2eb5b94b8b704414999120303b6ed37e8c29956ee8f12b8f505aede978c38ad0
|
|
| MD5 |
39913fe6ec79c952e60f8f11d43ec22d
|
|
| BLAKE2b-256 |
72136ee06509ed1f5eb0fae2bb603bb2d3430892307ba4c740dd11d8f3403278
|
Provenance
The following attestation bundles were made for epilink-0.1.3.tar.gz:
Publisher:
release.yml on ydnkka/epilink
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
epilink-0.1.3.tar.gz -
Subject digest:
2eb5b94b8b704414999120303b6ed37e8c29956ee8f12b8f505aede978c38ad0 - Sigstore transparency entry: 1148064781
- Sigstore integration time:
-
Permalink:
ydnkka/epilink@7acf26bf0fa96f08c692232071d3b4b68da625eb -
Branch / Tag:
refs/tags/v0.1.3-alpha - Owner: https://github.com/ydnkka
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7acf26bf0fa96f08c692232071d3b4b68da625eb -
Trigger Event:
release
-
Statement type:
File details
Details for the file epilink-0.1.3-py3-none-any.whl.
File metadata
- Download URL: epilink-0.1.3-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae4b62ea8c92ab27402f948dfb021695c78c38b7c56d059e6e7cab3d262c5d27
|
|
| MD5 |
556124a16cf099b4d3221ccd24068e97
|
|
| BLAKE2b-256 |
1f0286b847d4e6ae15b2ee326aa264d6dd5f3583c32d669c48c9371b32b4f527
|
Provenance
The following attestation bundles were made for epilink-0.1.3-py3-none-any.whl:
Publisher:
release.yml on ydnkka/epilink
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
epilink-0.1.3-py3-none-any.whl -
Subject digest:
ae4b62ea8c92ab27402f948dfb021695c78c38b7c56d059e6e7cab3d262c5d27 - Sigstore transparency entry: 1148065148
- Sigstore integration time:
-
Permalink:
ydnkka/epilink@7acf26bf0fa96f08c692232071d3b4b68da625eb -
Branch / Tag:
refs/tags/v0.1.3-alpha - Owner: https://github.com/ydnkka
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7acf26bf0fa96f08c692232071d3b4b68da625eb -
Trigger Event:
release
-
Statement type: