#' @title read.nextstrain.json
#' @param x the json tree file of auspice from nextstrain.
#' @return treedata object
#' @export
#' @author Shuangbin Xu
#' @examples
#' file1 <- system.file("extdata/nextstrain.json", "minimal_v2.json", package="treeio")
#' tr <- read.nextstrain.json(file1)
#' tr
read.nextstrain.json <- function(x){
x <- jsonlite::read_json(x)
if (all(c('meta', 'tree') %in% names(x))){
dt <- parser_children(x$tree)
}else{
dt <- parser_children(x)
}
if ('branch.length' %in% colnames(dt)){
rmclnm <- c("parentID", "NodeID", "branch.length")
edgedf <- dt[, rmclnm]
}else{
rmclnm <- c("parentID", "NodeID")
edgedf <- dt[, rmclnm]
}
dd <- as.phylo(edgedf, "branch.length")
dt$label <- as.character(dt$NodeID)
dt <- dt[, !colnames(dt) %in% rmclnm, drop=FALSE]
dd <- dd |> tidytree::as_tibble() |> dplyr::full_join(dt, by='label')
if ("name" %in% colnames(dd)){
dd$label <- dd$name
dd$name <- NULL
}
tr <- dd |> as.treedata()
return(tr)
}
parser_children <- function(x, id=list2env(list(id = 0L)), parent = 1){
id[["id"]] <- id[["id"]] + 1L
id[["data"]][[id[["id"]]]] <- extract_node_attrs(x, id=id[["id"]], isTip=FALSE, parent=parent)
if ('div' %in% colnames(id[['data']][[id[['id']]]])){
parent.index <- id[['data']][[id[['id']]]][['parentID']]
id[['data']][[id[['id']]]][['branch.length']] <- as.numeric(id[['data']][[id[['id']]]][['div']]) -
as.numeric(id[['data']][[parent.index]][['div']])
}
if ('children' %in% names(x)){
lapply(x$children,
parser_children,
id = id,
parent = ifelse(id[['id']]>=2, id[["data"]][[id[["id"]]-1L]][["NodeID"]], 1)
)
}else{
id[["data"]][[id[["id"]]]][["isTip"]] <- TRUE
}
dat <- dplyr::bind_rows(as.list(id[["data"]])) %>% dplyr::mutate_if(check_num, as.numeric)
return(dat)
}
check_num <- function(x){
is_numeric(x) && is.character(x)
}
extract_node_attrs <- function(x, id, isTip, parent){
if ('node_attrs' %in% names(x)){
res <- build_node_attrs(x[['node_attrs']])
}else if('attr' %in% names(x)){
res <- build_node_attrs(x[['attr']])
}else{
res <- data.frame()
}
if ('name' %in% names(x)){
res$name <- x[['name']]
}else if('strain' %in% names(x)){
res$name <- x[['strain']]
}
res$parentID <- parent
res$NodeID <- id
res$isTip <- isTip
return(res)
}
build_node_attrs <- function(x){
x <- unlist(x)
index <- grepl('\\.value$', names(x))
names(x)[index] <- gsub('\\.value$', '', names(x)[index])
x <- tibble::as_tibble(t(x))
return(x)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.