Networks
Inferred transmission networks from time calibrated phylogenies
Transmission Networks
Serotype A
Load time-calibrated MCC tree.
Hide code
<- read.nexus(here("local/beast/a_1/sero_a.mcc.tre")) sero_A.tree
Read Beast log file for the tree
Hide code
<- get_tracer_stats(here("local/beast/a_1/sero_a.log.txt")) get_A_stats
Loading required package: coda
Hide code
<- get_A_stats %>%
root_age filter(Parameter == "age.root.") %>%
select(Median) %>%
pull()
<- get_A_stats %>%
tree_mrsd filter(Parameter == "treeModel.rootHeight") %>%
select(Median) %>%
pull() + root_age
<- ptreeFromPhylo(sero_A.tree,
sero_A.tree.p dateLastSample = tree_mrsd)
Choose prior
Constructing a gamma distribution that reflects FMDV generation time, ballpark 5-15 days, with 7-10 days being more likely.
Hide code
<- get_gamma_params(7, c(5, 15))
gam_params
<- gam_params$shape
w.shape <- gam_params$scale
w.scale
set.seed(1976)
<- rgamma(1000, w.shape, ) check_gamma
Hide code
plot_density(check_gamma, max_x = 20)
The dateT
parameter is the date when observation stopped. Used 2017.5 due that being the most recent sample across the A, Asia1, and O serotypes in the study.
Hide code
<- inferTTree(sero_A.tree.p,
tt_sero_A mcmcIterations=10000,
w.shape=w.shape,
w.scale=w.scale,
dateT=2017.5)
saveRDS(tt_sero_A, here("local/assets/tt_sero_A.rds"))
Serotype Asia1
Hide code
<- read.nexus(here("local/beast/asia1_1/sero_asia1.mcc.tre"))
sero_Asia1.tree <- get_tracer_stats(here("local/beast/asia1_1/sero_asia1.log.txt")) Asia1_stats
Hide code
<- infer_ttree(sero_Asia1.tree,
tt_sero_Asia1
Asia1_stats,w.shape=w.shape,
w.scale=w.scale,
dateT = 2017.5)
saveRDS(tt_sero_Asia1, here("local/assets/tt_sero_Asia1.rds"))
Serotype O
Hide code
<- read.nexus(here("local/beast/o_1/sero_o.mcc.tre"))
sero_O.tree <- get_tracer_stats(here("local/beast/o_1/sero_o.log.txt")) O_stats
Hide code
<- infer_ttree(sero_O.tree,
tt_sero_O
O_stats,w.shape=w.shape,
w.scale=w.scale,
dateT = 2017.5)
saveRDS(tt_sero_O, here("local/assets/tt_sero_O.rds"))
Get Networks
Hide code
<- extract_transmission_network(tt_sero_A) %>%
A_net mutate(Serotype = "A")
<- extract_transmission_network(tt_sero_Asia1) %>%
Asia1_net mutate(Serotype = "Asia1")
<- extract_transmission_network(tt_sero_O) %>%
O_net mutate(Serotype = "O")
<- rbind(A_net, Asia1_net, O_net) all_networks
Match Metadata
Hide code
<- readRDS(here("local/assets/sero_df.rds")) # from preprocessing
sero_df
<- sero_df %>%
animal_codes filter(status == "Subclinical") %>%
mutate(Status = status,
host_id = label) %>%
select(host_id, animal, farm_code, Status)
<-left_join(all_networks, animal_codes, by = "host_id") %>%
all_networks mutate(animal = as.character(animal),
Status = if_else(is.na(Status), "Clinical", Status),
infected_ani = if_else(Status == "Subclinical", animal, host_id))
$infector_match <- with(animal_codes,
all_networksmatch(
animal[$infector,
all_networks
host_id)])
<- all_networks %>%
all_networks mutate(infector_match = as.character(infector_match),
infector_ani = if_else(is.na(infector_match), infector, infector_match),
infection_date = as.Date(infection_date))
Set Vertices and Nodes
Hide code
<- data.frame(from = all_networks$infector_ani, to = all_networks$infected_ani)
edges
<- graph_from_data_frame(edges, directed = TRUE)
g
V(g)$Status <- "Unknown"
V(g)$Status[V(g)$name %in% all_networks$infected_ani] <- all_networks$Status[match(V(g)$name[V(g)$name %in% all_networks$infected_ani], all_networks$infected_ani)]
V(g)$Serotype <- "Origin"
V(g)$Serotype[V(g)$name %in% all_networks$infected_ani] <-
$Serotype[match(V(g)$name[V(g)$name %in% all_networks$infected_ani], all_networks$infected_ani)]
all_networks
V(g)$infection_date <- as.Date("1995-07-10")
V(g)$infection_date[V(g)$name %in% all_networks$infected_ani] <-
$infection_date[match(V(g)$name[V(g)$name %in% all_networks$infected_ani], all_networks$infected_ani)]
all_networks
V(g)$infection_date <- as.Date(V(g)$infection_date)
V(g)$infection_steps <- as.integer(as.factor(V(g)$infection_date))
Tree network showing descent
Hide code
<- ggraph(g, layout = 'tree') +
p geom_edge_diagonal(start_cap = circle(2, 'mm'), end_cap = circle(2, 'mm'),
color = 'gray20', alpha=0.9,
arrow = arrow(type = "closed", length = unit(2, "mm"))) +
geom_node_point(aes(color = Status, shape = Serotype), size = 4, alpha = 0.6) +
scale_color_manual(values = c("Subclinical" = "orange",
"Clinical" = "steelblue",
"Unknown" = "gray50")) +
#geom_node_label(aes(label = name), repel = TRUE) +
theme_void() +
labs(title = "FMDV Transmission Network",
subtitle = "Nodes are animals, arrows extend from infector to infectee")
p
Showing individuals with multiple infections (red color)
Hide code
set.seed(1976)
<- as_tbl_graph(g)
tg
<- tg %>%
tg activate(nodes) %>%
mutate(in_degree = centrality_degree(mode = "in"),
multiple_incoming = ifelse(in_degree > 1, "multiple", "single"))
<- tg %>%
tg mutate(alpha = ifelse(multiple_incoming == "multiple", 1, 0.6))
<- layout_with_fr(as.igraph(tg), niter = 5000)
layout
<- as.data.frame(layout)
layout_df colnames(layout_df) <- c("x", "y")
<- 25
spread_factor $x <- layout_df$x * spread_factor
layout_df$y <- layout_df$y * spread_factor
layout_df
<- tg %>%
tg mutate(x = layout_df$x, y = layout_df$y)
<- ggraph(tg, x = x, y = y) +
p geom_edge_diagonal(aes(color = as.factor(from), alpha = 0.9),
start_cap = circle(3, 'mm'), end_cap = circle(3, 'mm'),
arrow = arrow(type = "closed", length = unit(2, "mm")),
show.legend = FALSE) +
geom_node_point(aes(color = Status, shape = Serotype,
fill = multiple_incoming, alpha = alpha),
size = 3, stroke=1.5) +
scale_shape_manual(values = c("A" = 21,
"Asia1" = 22,
"O" = 24,
"Origin" = 13)) +
scale_color_manual(values = c("Subclinical" = "orange",
"Clinical" = "steelblue",
"Unknown" = "gray50")) +
scale_fill_manual(values = c("multiple" = "red", "single" = NA), guide = "none") +
scale_alpha_identity() +
theme_void() +
labs(title = "FMDV Transmission Network",
subtitle = "Nodes are animals. Red indicates multiple infections")
p
Animated version
Hide code
<- ggraph(tg, x = x, y = y) +
p geom_edge_diagonal(aes(color = as.factor(from), alpha = 0.9),
start_cap = circle(3, 'mm'), end_cap = circle(3, 'mm'),
arrow = arrow(type = "closed", length = unit(2, "mm")),
show.legend = FALSE) +
geom_node_point(aes(color = Status, shape = Serotype,
fill = multiple_incoming, alpha = alpha),
size = 3, stroke=1.5) +
scale_shape_manual(values = c("A" = 21,
"Asia1" = 22,
"O" = 24,
"Origin" = 13)) +
scale_color_manual(values = c("Subclinical" = "orange",
"Clinical" = "steelblue",
"Unknown" = "gray50")) +
scale_fill_manual(values = c("multiple" = "red", "single" = NA), guide = "none") +
scale_alpha_identity() +
theme_void() +
labs(title = "FMDV Transmission Network",
subtitle = "Nodes are animals. Red indicates multiple infections") +
transition_time(infection_steps) +
labs(subtitle = 'Date: {frame_time}') +
shadow_mark(alpha = alpha / 2)
<- animate(p, width = 800, height = 800,
ani_net fps = 10, end_pause = 20,
renderer = gifski_renderer())
anim_save(here("local/assets/coinfect_network_animation.gif"), ani_net)
Hide code
::include_graphics(here("local/assets/coinfect_network_animation.gif")) knitr