V.PhyloMaker是一款应用于R的资源包,存储了数以万计的维管束植物的系统发生信息。V.PhyloMaker由贵州师范大学生命科学学院金毅教授等人开发,涵盖了74533种维管束植物的基本信息,为想要避免繁琐地查找基因/蛋白质数据的用户构建系统发生树提供了便利。
V.PhyloMaker的代码在github上以源代码的形式公开(jinyizju/V.PhyloMaker),本文接下来的代码部分中的注释,对代码中的函数cluster(cluster.R)和ancestor(ancestor.R)进行了解析。
cluster.R:
# cluster.R
# 返回一个与data的length相同的向量n,这个向量中的项是不减的(也就是说,较靠后的项)
# --是大于等于较为靠前的项的。
cluster <-
function(data)
{
n <- 1
for (i in 1 : (length(data) - 1))
{
# 如果连续的两个数据相等,那么n里面对应项的值要比上一项多1
if (data[i] != data[i + 1])
{
n[i + 1] <- n[i] + 1
}
# 如果连续的两个数据不相等,那么n里面对应项的值与上一项相等
else
{
n[i + 1] <- n[i]
}
}
return(n)
}
# 例如,myData = c(1, 3, 2, 2, 4)
# 那么该cluster(myData)会返回(1, 1, 1, 2, 2)
ancestor.R
# ancestor.R
# 返回两个结点在树中的、最近的公共父节点(或者叫祖先节点)
ancestor <-
function(tree, tip1, tip2)
{
# tree$edge中存储着树的“边信息”,每行有两个数据,第一个数据是一条边的起始节点,另一个
# --则是这条边的结束节点(对应的标号)
# 找到结束于tip1的那条边,并找到这条边的起始位置(也就是找到tip1的父节点)
ance1 <- tree$edge[which(tree$edge[, 2] == tip1), 1]
# 找到结束于tip2的那条边,并找到这条边的起始位置(也就是找到tip2的父节点)
ance2 <- tree$edge[which(tree$edge[, 2] == tip2), 1]
# mi是树的根,因为树的根对应的标号是最小的
mi <- min(tree$edge[, 1])
for (i in 1 : (tree$Nnode - 1))
{
# ance1[2]是ance1[1]的父节点,然后ance1[3]是ance1[2]的父节点,以此类推,直到找到根
if (ance1[i] > mi) ance1[i + 1] <- tree$edge[which(tree$edge[,2] == ance1[i]), 1]
else break()
}
for (j in 1 : (tree$Nnode - 1))
{
# ance2[2]是ance2[1]的父节点,然后ance2[3]是ance2[2]的父节点,以此类推,直到找到根
if (ance2[j] > mi) ance2[j + 1] <- tree$edge[which(tree$edge[,2] == ance2[j]), 1]
else break()
}
# 找到ance1和ance2中公共部分的最大的那个,也就是两个结点在树中的、最近的公
# --共父节点(或者叫祖先节点)
node <- max(intersect(ance1, ance2))
# 返回该节点。注意,此节点不可能是树的根,也不会是tip1或tip2。也就是说,如果
# --tip1与tip2中有一个直接连接在根上,那么该函数不会有返回值;如果tip1是tip2
# --的祖先(或者反之),那么只会返回tip1的父节点而不会返回tip1本身。当然,在
# --这个包中不会产生这样的问题,因为调用函数时tip1和tip2必定都是“叶节点”,位
# --于树的末端
return(node)
}