Как добавить загрузочные значения узлов кластера (дерева) в формате NEWICK в R

Я хочу создать дерево (кластер) с помощью веб-инструмента Interactive Tree of Life (iTOL). В качестве входного файла (или строки) этот инструмент использует формат Ньюика, который является способом представления графика -теоретические деревья с длинами ребер, используя круглые скобки и запятые. Кроме того, может поддерживаться дополнительная информация, такая как начальные значения узлов кластера.

Например, здесь я создал набор данных для кластерного анализа с помощью пакета clusterGeneration:

library(clusterGeneration)
set.seed(1)    
tmp1 <- genRandomClust(numClust=3, sepVal=0.3, numNonNoisy=5,
        numNoisy=3, numOutlier=5, numReplicate=2, fileName="chk1")
data <- tmp1$datList[[2]]

После этого я выполнил анализ кластера и оценил поддержку узлов кластера с помощью начальной загрузки с использованием пакета pvclust:

set.seed(2)    
y <- pvclust(data=data,method.hclust="average",method.dist="correlation",nboot=100)
plot(y)  

Вот значения кластера и начальной загрузки: кластер и значения начальной загрузки

Чтобы создать файл Newick, я использовал пакет ape:

library(ape)
yy<-as.phylo(y$hclust)
write.tree(yy,digits=2)

Функция write.tree напечатает дерево в формате Ньюика:

((x2:0.45,x6:0.45):0.043,((x7:0.26,(x4:0.14,(x1:0.14,x3:0.14):0.0064):0.12):0.22,(x5:0.28,x8:0.28):0.2):0.011);

Эти числа представляют собой длины ветвей (длины ребер кластера). Следуя инструкциям со страницы справки iTOL (раздел "Загрузка собственных деревьев и работа с ними" ) Я вручную добавил загрузочные значения в свой файл Newick (значения выделены жирным шрифтом ниже):

((x2:0,45,x6:0,45)74:0,043,((x7:0,26,(x4:0,14,(x1:0,14,x3:0,14))55: 0,0064)68:0,12)100:0,22,(x5:0,28,x8:0,28)100:0,2)63:0,011);

Он отлично работает, когда я загружаю строку в iTOL. Однако у меня огромный кластер, и делать это вручную кажется утомительным...

ВОПРОС: Какой код может выполнять это вместо ручного ввода?

Значения начальной загрузки можно получить:

(round(y$edges,2)*100)[,1:2]

Длина ветвей, используемая для формирования файла Ньюика, может быть получена следующим образом:

yy$edge.length

Я попытался понять, как работает функция write.tree после ее отладки. Однако я заметил, что он внутри вызывает функцию .write.tree2, и я не мог понять, как эффективно изменить исходный код и получить загрузочные значения в соответствующей позиции в файле Newick.

Любое предложение приветствуется.


person Newbie_R    schedule 30.03.2014    source источник


Ответы (1)


Вот одно из решений: объекты класса phylo имеют доступный слот с именем node.label, который, соответственно, дает вам метку узла. Вы можете использовать его для хранения значений начальной загрузки. В вашем файле Newick File в соответствующем месте будет записано, как вы можете видеть в коде .write.tree2:

> .write.tree2
function (phy, digits = 10, tree.prefix = "") 
{
    brl <- !is.null(phy$edge.length)
    nodelab <- !is.null(phy$node.label)

...

    if (is.null(phy$root.edge)) {
        cp(")")
        if (nodelab) 
            cp(phy$node.label[1])
        cp(";")
    }
    else {
        cp(")")
        if (nodelab) 
            cp(phy$node.label[1])
        cp(":")
        cp(sprintf(f.d, phy$root.edge))
        cp(";")
    }

...

Настоящая трудность состоит в том, чтобы найти правильный порядок узлов. Я искал и искал, но не смог найти способ найти правильный порядок апостериори.... так что это означает, что мы должны будем получить эту информацию во время преобразования из объект класса hclust в объект класса phylo.

И, к счастью, если вы посмотрите на функцию as.phylo.hclust, там есть вектор, содержащий индексы узлов в их правильном порядке по отношению к предыдущему объекту hclust:

> as.phylo.hclust
function (x, ...) 
{
    N <- dim(x$merge)[1]
    edge <- matrix(0L, 2 * N, 2)
    edge.length <- numeric(2 * N)
    node <- integer(N)              #<-This one
...

Это означает, что мы можем сделать наш собственный as.phylo.hclust с параметром nodenames, если он находится в том же порядке, что и узлы в объекте hclust (что имеет место в вашем примере, поскольку pvclust поддерживает согласованный внутренний порядок, т.е. порядок узлов в hclust такое же, как и в таблице, в которой вы ковыряли бутстрапы):

# NB: in the following function definition I only modified the commented lines
as.phylo.hclust.with.nodenames <- function (x, nodenames, ...) #We add a nodenames argument
{
    N <- dim(x$merge)[1]
    edge <- matrix(0L, 2 * N, 2)
    edge.length <- numeric(2 * N)
    node <- integer(N)
    node[N] <- N + 2L
    cur.nod <- N + 3L
    j <- 1L
    for (i in N:1) {
        edge[j:(j + 1), 1] <- node[i]
        for (l in 1:2) {
            k <- j + l - 1L
            y <- x$merge[i, l]
            if (y > 0) {
                edge[k, 2] <- node[y] <- cur.nod
                cur.nod <- cur.nod + 1L
                edge.length[k] <- x$height[i] - x$height[y]
            }
            else {
                edge[k, 2] <- -y
                edge.length[k] <- x$height[i]
            }
        }
        j <- j + 2L
    }
    if (is.null(x$labels)) 
        x$labels <- as.character(1:(N + 1))
    node.lab <- nodenames[order(node)] #Here we define our node labels
    obj <- list(edge = edge, edge.length = edge.length/2, tip.label = x$labels, 
        Nnode = N, node.label = node.lab) #And you put them in the final object
    class(obj) <- "phylo"
    reorder(obj)
}

В конце концов, вот как вы могли бы использовать эту новую функцию в своем тематическом исследовании:

bootstraps <- (round(y$edges,2)*100)[,1:2]
yy<-as.phylo.hclust.with.nodenames(y$hclust, nodenames=bootstraps[,2])
write.tree(yy,tree.names=TRUE,digits=2)
[1] "((x5:0.27,x8:0.27)100:0.24,((x7:0.25,(x4:0.14,(x1:0.13,x3:0.13)61:0.014)99:0.11)100:0.23,(x2:0.46,x6:0.46)56:0.022)61:0.027)100;"
#See the bootstraps    ^^^ here for instance
plot(yy,show.node.label=TRUE) #To show that the order is correct
plot(y) #To compare with (here I used the yellow value)

введите здесь описание изображениявведите здесь описание изображения

person plannapus    schedule 31.03.2014
comment
Большое спасибо за быстрый и развернутый ответ!!! Прекрасная работа! Я попробую это на своем собственном кластере как можно скорее. - person Newbie_R; 31.03.2014