knitr::opts_chunk$set(echo = FALSE)

treeswithintrees: an R package for exact discrete-event simulation of virus phylogenies

Garway T Ng and Art Poon
Western University, Canada Department of Pathology and Laboratory Medicine

Phylodynamics and simulation

State of the art

Unmet needs

Proposed workflow

Object classes

Model specification with YAML

InitialConditions:
  originTime: 10.0  # time frame of simulation
  size:
    host: 100  # number of hosts
  indexType: 'host'
CompartmentTypes:
  'host':
    branching.rates: (host=0.01)  # transmission rate
    migration.rates: ()  ## not in use
    transition.rates: ()  ## not in use
    effective.size: 100.0  # of virus pop'n within host
    generation.time: 0.01
    bottleneck.size: 1  # on either transmission or migration
Compartments:
  'I':
    type: host
    replicates: 10  # number of sampled hosts
Lineages:
  'I':
    type: 'virus'
    sampling.time: 0  # this can be varied per Lineage
    location: I
    replicates: 3  # per sampled host

Example

require(twt)
path <- system.file('extdata', 'structSI.yaml', package='twt')
mod <- Model$new(yaml.load_file(path)); mod

Outer tree

set.seed(1); run <- sim.outer.tree(mod)
par(mfrow=c(1,2)); plot(run, 's'); plot(run)

Time heterogeneity

```r

m2 <- Model$new(yaml.load_file('../tests/testthat/epoch.yaml'))

set.seed(1); run2 <- sim.outer.tree(m2)

par(mfrow=c(1,2)); plot(run2, 's', mar=c(5,5,0,2)); abline(v=3, lty=2, lwd=2); plot(run2, segments.lwd=3)

```

Resolving within-host events

where $N$ = eff. pop. size and $K$ = num. extant lineages.

Piece-wise linear coalescent model

Inner tree

set.seed(3); eventlog <- sim.inner.tree(run)
plot(eventlog, cex.lab=0.6)
par(xpd=NA); legend(x=0, y=0, legend=c('transmission', 'migration'), pch=c(16, 21), bg=c(NA, 'white'), horiz=T); text(x=9, y=52, label='Default labels {Compartment}__{Lineage}, where I1_4 is 4th Compartment of type I1', cex=0.8); par(xpd=FALSE)

Colouring inner tree by host type

L <- tree.layout(as.phylo(eventlog, transmissions=T, migrations=T))
plot(L, type='n', cex.lab=0.5); lines(L, col=ifelse(grepl("host1|I1", L$edges$compartment1), 'blue', 'red'), lwd=1.5)

Computing time

x <- c(10, 50, 100, 200, 300, 500)
y <- c(10.691, 17.636, 34.294, 93.058, 192.254, 626.171) / 10

par(mar=c(5,5,2,1), mfrow=c(1,2))

plot(x,y, type='l', col='cadetblue', xlab='Number of sampled hosts', ylab='Average time per tree (seconds)', lwd=2, cex.lab=1.2)
title(main="Host population 1000", adj=0, font.main=1, cex=1)
points(x, y, pch=21, col='cadetblue', bg='white', lwd=2.5, cex=1.5)

x <- c(100, 200, 500, 1000, 2000, 5000, 7500, 1e4)
y <- c(2.118, 2.858, 5.631, 10.691, 19.551, 45.405, 69.069, 107.805)
plot(x, y, type='l', col='salmon', xlab='Host population size', ylab='Average time per tree (seconds)', lwd=2, cex.lab=1.2)
title(main="10 sampled hosts", adj=0, font.main=1, cex=1)
points(x, y, pch=21, col='salmon', bg='white', lwd=2.5, cex=1.5)

Availability

Acknowledgements



PoonLab/twt documentation built on Nov. 7, 2024, 4:18 a.m.