diff --git a/Dockerfile b/Dockerfile index d4b7986..1725dac 100755 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ USER root RUN apt-get update -y && apt-get install -y bc # Install treesimulator -RUN cd /usr/local/ && pip3 install --no-cache-dir treesimulator==0.1.22 +RUN cd /usr/local/ && pip3 install --no-cache-dir treesimulator==0.2.0 # Switch to your new user in the docker image USER evolbioinfo diff --git a/README.md b/README.md index 6421fcc..3bdc211 100755 --- a/README.md +++ b/README.md @@ -1,11 +1,41 @@ # treesimulator -Simulation of rooted phylogenetic trees under a given Multitype Birth–Death (MTBD) model. +Simulation of rooted phylogenetic trees under a given Multitype Birth–Death (MTBD) model, with or without partner notification (PN). + +[//]: # ([![DOI:10.1093/sysbio/syad059](https://zenodo.org/badge/DOI/10.1093/sysbio/syad059.svg)](https://doi.org/10.1093/sysbio/syad059)) +[![GitHub release](https://img.shields.io/github/v/release/evolbioinfo/treesimulator.svg)](https://github.com/evolbioinfo/treesimulator/releases) +[![PyPI version](https://badge.fury.io/py/treesimulator.svg)](https://pypi.org/project/treesimulator/) +[![PyPI downloads](https://shields.io/pypi/dm/treesimulator)](https://pypi.org/project/treesimulator/) +[![Docker pulls](https://img.shields.io/docker/pulls/evolbioinfo/treesimulator)](https://hub.docker.com/r/evolbioinfo/treesimulator/tags) + +## MTBD The MTBD models were introduced by Stadler & Bonhoeffer [[_Philos. Trans. R. Soc. B_ 2013]](https://royalsocietypublishing.org/doi/10.1098/rstb.2012.0198). +An MTBD model with m states has + +m(m-1) state transition rate parameters: +* μij -- transition rate from state i to state j (1 ≤ i, j ≤ m; i ≠ j), where μij ≥ 0 + +m2 transmission rate parameters: +* λij -- transmission rate from state i (donor) to state j (recipient) (1 ≤ i, j ≤ m), where λij ≥ 0 + +m removal (becoming non-infectious) rate parameters: +* ψi -- removal rate of state i (1 ≤ i ≤ m), where ψi ≥ 0 + +m sampling probability upon removal parameters: +* pi -- probability to sample the pathogen of an individual in state i upon removal (1 ≤ i ≤ m), where 0 < pi ≤ 1 + +## Partner Notification (PN) +Partner notification adds two parameters to the initial MTBD model: + +* υ -- probability to notify partners upon sampling +* φ -- notified partner removal and sampling rate: φ >> ψi ∀i (1 ≤ i ≤ m). The pathogen of a notified partner is sampled automatically (with a probability of 1) upon removal. + + We pay particular interest to the classical BD model, the BD Exposed-Infectious (BDEI) model, and BD with superspreading (BDSS), -as they are described in [[Voznica _et al._ 2021]]((https://www.biorxiv.org/content/10.1101/2021.03.11.435006v1)). +as they are described in [[Voznica _et al._ 2021]]((https://www.biorxiv.org/content/10.1101/2021.03.11.435006v1)), and to their -PN versions. + ## BD 3 parameters: @@ -17,8 +47,23 @@ Epidemiological parameters: * R0=λ/ψ -- reproduction number * 1/ψ -- infectious time + +## BD-PN +5 parameters: +* λ -- transmission rate +* ψ -- removal rate +* p -- sampling probability upon removal +* υ -- probability to notify partners upon sampling +* φ -- notified partner removal and sampling rate: φ >> ψ + + +Epidemiological parameters: +* R0=λ/ψ -- reproduction number +* 1/ψ -- infectious time +* 1/φ -- notified partner removal time + ## BDEI -2 compartments: +2 states: * E, exposed, i.e. infected but not yet infectious * I, infectious @@ -33,6 +78,26 @@ Epidemiological parameters: * 1/ψ -- infectious time * 1/μ -- incubation period + +## BDEI-PN +2 states: +* E, exposed, i.e. infected but not yet infectious +* I, infectious + +6 parameters: +* μ -- transition rate from E to I (becoming infectious) +* λ -- transmission rate from I to E +* ψ -- removal rate of I +* p -- sampling probability upon removal +* υ -- probability to notify partners upon sampling +* φ -- notified partner removal and sampling rate: φ >> ψ + +Epidemiological parameters: +* R0=λ/ψ -- reproduction number +* 1/ψ -- infectious time +* 1/μ -- incubation period +* 1/φ -- notified partner removal time + ## BDSS 2 compartments: * N, standard infectious individual @@ -48,104 +113,242 @@ Epidemiological parameters: * ψ -- removal rate of S and of N (the same) * p -- sampling probability upon removal (the same for N and S) +Epidemiological parameters: +* R0=(λnn + λss)/ψ -- reproduction number +* 1/ψ -- infectious time +* X=λssnssnnn -- super-spreading transmission ratio +* f=λss/(λsn + λss) -- super-spreading fraction + +## BDSS-PN +2 states: +* N, standard infectious individual +* S, superspreader +8 parameters: +* λnn -- transmission rate from N to N +* λns -- transmission rate from N to S +* λsn -- transmission rate from S to N +* λss -- transmission rate from S to S + + (with a constraint that λssnssnnn) +* ψ -- removal rate of S and of N (the same) +* p -- sampling probability upon removal (the same for N and S) +* υ -- probability to notify partners upon sampling +* φ -- notified partner removal and sampling rate: φ >> ψ Epidemiological parameters: * R0=(λnn + λss)/ψ -- reproduction number * 1/ψ -- infectious time * X=λssnssnnn -- super-spreading transmission ratio * f=λss/(λsn + λss) -- super-spreading fraction +* 1/φ -- notified partner removal time + ## Installation -To install treesimulator: + +There are 4 alternative ways to run __treesimulator__ on your computer: +with [docker](https://www.docker.com/community-edition), +[apptainer](https://apptainer.org/), +in Python3, or via command line (requires installation with Python3). + + +### Installation in python3 or command-line + +You could either install python (version 3.6 or higher) system-wide and then install treesimulator via pip: ```bash +sudo apt install -y python3 python3-pip python3-setuptools python3-distutils pip3 install treesimulator ``` -## Usage -### Command line +or alternatively, you could install python (version 3.6 or higher) and treesimulator via [conda](https://conda.io/docs/) (make sure that conda is installed first). -## BD -The following command simulates a tree with 200-500 tips under BD model, with λ=0.5, ψ=0.25, p=0.5, -and saves it to a file tree.nwk, while saving the parameters to a comma-separated file params.csv: +(Optional) to install treesimulator in a new conda environment (e.g., called _phyloenv_ below), first create and activate the environment: ```bash -generate_bd --min_tips 200 --max_tips 500 --la 0.5 --psi 0.25 --p 0.5 --nwk tree.nwk --log params.csv +conda create --name phyloenv python=3.6 +conda activate phyloenv ``` -To seee detailed options, run: + +Install treesimulator with conda +```bash +conda install treesimulator +``` + + +### Basic usage in a command line +If you installed __treesimulator__ in a conda environment (here named _phyloenv_), do not forget to first activate it, e.g. + +```bash +conda activate phyloenv +``` + + +#### BD and BD-PN +The following command simulates a tree with 200-500 tips under the BD model, with λ=0.5, ψ=0.25, p=0.5, +and saves it to the file tree.nwk, while saving the parameters to the comma-separated file params.csv: +```bash +generate_bd --min_tips 200 --max_tips 500 \ +--la 0.5 --psi 0.25 --p 0.5 \ +--nwk tree.nwk --log params.csv +``` +The following command simulates a tree with 200-500 tips under the BD-PN model, with λ=0.5, ψ=0.25, p=0.5, φ=2.5, υ=0.2, +and allowing to notify only the most recent partner of each sampled index case. +The simulated tree is saved to the file tree.nwk, while the model parameters are saved to the comma-separated file params.csv: +```bash +generate_bd --min_tips 200 --max_tips 500 \ +--la 0.5 --psi 0.25 --p 0.5 \ +--phi 2.5 --upsilon 0.2 --max_notified_partners 1 \ +--nwk tree.nwk --log params.csv +``` +To see detailed options, run: ```bash generate_bd --help ``` -## BDEI -The following command simulates a tree with 200-500 tips under BDEI model, with μ=1, λ=0.5, ψ=0.25, p=0.5, -and saves it to a file tree.nwk, while saving the parameters to a comma-separated file params.csv: +#### BDEI and BDEI-PN +The following command simulates a tree with 200-500 tips under the BDEI model, with μ=1, λ=0.5, ψ=0.25, p=0.5, +and saves it to the file tree.nwk, while saving the parameters to the comma-separated file params.csv: +```bash +generate_bdei --min_tips 200 --max_tips 500 \ +--mu 1 --la 0.5 --psi 0.25 --p 0.5 \ +--nwk tree.nwk --log params.csv +``` +The following command simulates a tree with 200-500 tips under the BDEI-PN model, with μ=1, λ=0.5, ψ=0.25, p=0.5, φ=2.5, υ=0.2, +and allowing to notify only the most recent partner of each sampled index case. +The simulated tree is saved to the file tree.nwk, while the model parameters are saved to the comma-separated file params.csv: ```bash -generate_bdei --min_tips 200 --max_tips 500 --mu 1 --la 0.5 --psi 0.25 --p 0.5 --nwk tree.nwk --log params.csv +generate_bdei --min_tips 200 --max_tips 500 \ +--mu 1 --la 0.5 --psi 0.25 --p 0.5 \ +--phi 2.5 --upsilon 0.2 --max_notified_partners 1 \ +--nwk tree.nwk --log params.csv ``` -To seee detailed options, run: +To see detailed options, run: ```bash generate_bdei --help ``` -## BDSS -The following command simulates a tree with 200-500 tips under BDSS model, +#### BDSS and BDSS-PN +The following command simulates a tree with 200-500 tips under the BDSS model, with λnn=0.1, λns=0.3, λsn=0.5, λss=1.5, ψ=0.25, p=0.5, -and saves it to a file tree.nwk, while saving the parameters to a comma-separated file params.csv: +and saves it to the file tree.nwk, while saving the parameters to the comma-separated file params.csv: +```bash +generate_bdss --min_tips 200 --max_tips 500 \ +--la_nn 0.1 --la_ns 0.3 --la_sn 0.5 --la_ss 1.5 --psi 0.25 --p 0.5 \ +--nwk tree.nwk --log params.csv +``` +The following command simulates a tree with 200-500 tips under the BDSS-PN model, +with λnn=0.1, λns=0.3, λsn=0.5, λss=1.5, ψ=0.25, p=0.5, φ=2.5, υ=0.2, +and allowing to notify only the most recent partner of each sampled index case. +The simulated tree is saved to the file tree.nwk, while the model parameters are saved to the comma-separated file params.csv: ```bash -generate_bdss --min_tips 200 --max_tips 500 --la_nn 0.1 --la_ns 0.3 --la_sn 0.5 --la_ss 1.5 --psi 0.25 --p 0.5 --nwk tree.nwk --log params.csv +generate_bdss --min_tips 200 --max_tips 500 \ +--la_nn 0.1 --la_ns 0.3 --la_sn 0.5 --la_ss 1.5 --psi 0.25 --p 0.5 \ +--phi 2.5 --upsilon 0.2 --max_notified_partners 1 \ +--nwk tree.nwk --log params.csv ``` -To seee detailed options, run: +To see detailed options, run: ```bash generate_bdss --help ``` -## User-defined MTBD model +#### User-defined MTBD and MTBD-PN models The following command simulates a tree with 200-500 tips under a generic MTBD model, with two states A and B, with μaa=0.5, μab=0.6, μba=0.7, μbb=0.8, λaa=0.1, λab=0.2, λba=0.3, λbb=0.4, ψa=0.05, ψb=0.08, p=a0.15, p=b0.65, -and saves it to a file tree.nwk, while saving the parameters to a comma-separated file params.csv: +and saves it to the file tree.nwk, while saving the parameters to the comma-separated file params.csv: ```bash -generate_mtbd --min_tips 200 --max_tips 500 --nwk tree.nwk --log params.csv \ +generate_mtbd --min_tips 200 --max_tips 500 \ --states A B \ --transition_rates 0.5 0.6 0.7 0.8 \ --transmission_rates 0.1 0.2 0.3 0.4 \ --removal_rates 0.05 0.08 \ ---sampling_probabilities 0.15 0.65 +--sampling_probabilities 0.15 0.65 \ +--nwk tree.nwk --log params.csv ``` -To seee detailed options, run: +The following command simulates a tree with 200-500 tips under a generic MTBD model, with two states A and B, +with μaa=0.5, μab=0.6, μba=0.7, μbb=0.8, +λaa=0.1, λab=0.2, λba=0.3, λbb=0.4, +ψa=0.05, ψb=0.08, +p=a0.15, p=b0.65, +φ=2.5, υ=0.2, +and allowing to notify only the most recent partner of each sampled index case. +The simulated tree is saved to the file tree.nwk, while the model parameters are saved to the comma-separated file params.csv: +```bash +generate_mtbd --min_tips 200 --max_tips 500 \ +--states A B \ +--transition_rates 0.5 0.6 0.7 0.8 \ +--transmission_rates 0.1 0.2 0.3 0.4 \ +--removal_rates 0.05 0.08 \ +--sampling_probabilities 0.15 0.65 \ +--phi 2.5 --upsilon 0.2 --max_notified_partners 1 \ +--nwk tree.nwk --log params.csv +``` +To see detailed options, run: ```bash generate_mtbd --help ``` -### Python3 +#### Basic usage in Python3 To simulate trees with 200-500 tips under the above models and settings: -```python +```python3 from treesimulator.generator import generate from treesimulator import save_forest -from treesimulator.mtbd_models import Model, BirthDeathModel, BirthDeathExposedInfectiousModel, BirthDeathWithSuperSpreadingModel +from treesimulator.mtbd_models import Model, BirthDeathModel, BirthDeathExposedInfectiousModel, \ + BirthDeathWithSuperSpreadingModel, PNModel +# BD and BD-PN bd_model = BirthDeathModel(p=0.5, la=0.5, psi=0.25) print(bd_model.get_epidemiological_parameters()) -[bd_tree], (bd_total_tips, _, bd_total_time) = generate(bd_model, min_tips=200, max_tips=500) +[bd_tree], _, _ = generate(bd_model, min_tips=200, max_tips=500) save_forest([bd_tree], 'BD_tree.nwk') +bdpn_model = PNModel(model=bd_model, upsilon=0.2, partner_removal_rate=2.5) +[bdpn_tree], _, _ = generate(bdpn_model, min_tips=200, max_tips=500) +save_forest([bdpn_tree], 'BDPN_tree.nwk') +# BDEI and BDEI-PN bdei_model = BirthDeathExposedInfectiousModel(p=0.5, mu=1, la=0.5, psi=0.25) print(bdei_model.get_epidemiological_parameters()) -[bdei_tree], (bdei_total_tips, _, bdei_total_time) = generate(bdei_model, min_tips=200, max_tips=500) +[bdei_tree], _, _ = generate(bdei_model, min_tips=200, max_tips=500) save_forest([bdei_tree], 'BDEI_tree.nwk') +bdeipn_model = PNModel(model=bdei_model, upsilon=0.2, partner_removal_rate=2.5) +[bdeipn_tree], _, _ = generate(bdeipn_model, min_tips=200, max_tips=500) +save_forest([bdeipn_tree], 'BDEIPN_tree.nwk') +# BDSS and BDSS-PN bdss_model = BirthDeathWithSuperSpreadingModel(p=0.5, la_nn=0.1, la_ns=0.3, la_sn=0.5, la_ss=1.5, psi=0.25) print(bdss_model.get_epidemiological_parameters()) -[bdss_tree], (bdss_total_tips, _, bdss_total_time) = generate(bdss_model, min_tips=200, max_tips=500) +[bdss_tree], _, _ = generate(bdss_model, min_tips=200, max_tips=500) save_forest([bdss_tree], 'BDSS_tree.nwk') +bdsspn_model = PNModel(model=bdss_model, upsilon=0.2, partner_removal_rate=2.5) +[bdsspn_tree], _, _ = generate(bdsspn_model, min_tips=200, max_tips=500) +save_forest([bdsspn_tree], 'BDSSPN_tree.nwk') +# MTBD and MTBD-PN mtbd_model = Model(states=['A', 'B'], transition_rates=[[0.5, 0.6], [0.7, 0.8]], transmission_rates=[[0.1, 0.2], [0.3, 0.4]], removal_rates=[0.05, 0.08], ps=[0.15, 0.65]) -[mtbd_tree], (mtbd_total_tips, _, mtbd_total_time) = generate(mtbd_model, min_tips=200, max_tips=500) +[mtbd_tree], _, _ = generate(mtbd_model, min_tips=200, max_tips=500) save_forest([mtbd_tree], 'MTBD_tree.nwk') -``` \ No newline at end of file +mtbdpn_model = PNModel(model=mtbd_model, upsilon=0.2, partner_removal_rate=2.5) +[mtbdpn_tree], _, _ = generate(mtbdpn_model, min_tips=200, max_tips=500) +save_forest([mtbdpn_tree], 'MTBDPN_tree.nwk') +``` + +### Run with apptainer + +Once [apptainer](https://apptainer.org/docs/user/latest/quick_start.html#installation) is installed, +run the following command: + +```bash +apptainer run docker://evolbioinfo/treesimlator +``` + +This will launch a terminal session within the container, +in which you can run treesimulator following the instructions for the command line ("Basic usage in a command line") above. + + + + diff --git a/setup.py b/setup.py index e1e07f2..7dc7121 100755 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ 'Topic :: Software Development', 'Topic :: Software Development :: Libraries :: Python Modules', ], - version='0.1.22', + version='0.2.0', description='Simulation of rooted phylogenetic trees under a given Multitype Birth–Death model.', author='Anna Zhukova', author_email='anna.zhukova@pasteur.fr', diff --git a/treesimulator/__init__.py b/treesimulator/__init__.py index 2d9ad31..c72e900 100644 --- a/treesimulator/__init__.py +++ b/treesimulator/__init__.py @@ -1,7 +1,7 @@ import os STATE = 'state' -DIST_TO_START ='D' +DIST_TO_START = 'D' TIME_TILL_NOW = 'T' diff --git a/treesimulator/generator.py b/treesimulator/generator.py index a968633..b75b208 100755 --- a/treesimulator/generator.py +++ b/treesimulator/generator.py @@ -1,6 +1,6 @@ import logging import random -from collections import Counter, defaultdict +from collections import Counter import numpy as np from ete3 import TreeNode