美文网首页
深入ggtree:ggtree()源码解读

深入ggtree:ggtree()源码解读

作者: iBioinformatics | 来源:发表于2022-10-09 09:45 被阅读0次

    https://blog.csdn.net/u012110870/article/details/102804075

    GGTREE的快速使用函数就是ggtree,源码如下,

    function (tr, mapping = NULL, layout = "rectangular", open.angle = 0,
    mrsd = NULL, as.Date = FALSE, yscale = "none", yscale_mapping = NULL,
    ladderize = TRUE, right = FALSE, branch.length = "branch.length",
    ndigits = NULL, ...)
    {
    layout %<>% match.arg(c("rectangular", "slanted", "fan",
    "circular", "radial", "unrooted", "equal_angle", "daylight"))
    if (layout == "unrooted") {
    layout <- "daylight"
    message(""daylight" method was used as default layout for unrooted tree.")
    }
    if (is(tr, "r8s") && branch.length == "branch.length") {
    branch.length = "TREE"
    }
    if (yscale != "none") {
    layout <- "slanted"
    }
    if (is.null(mapping)) {
    mapping <- aes_(~x, ~y)
    }
    else {
    mapping <- modifyList(aes_(~x, ~y), mapping)
    }
    p <- ggplot(tr, mapping = mapping, layout = layout, mrsd = mrsd,
    as.Date = as.Date, yscale = yscale, yscale_mapping = yscale_mapping,
    ladderize = ladderize, right = right, branch.length = branch.length,
    ndigits = ndigits, ...)
    if (is(tr, "multiPhylo")) {
    multiPhylo <- TRUE
    }
    else {
    multiPhylo <- FALSE
    }
    p <- p + geom_tree(layout = layout, multiPhylo = multiPhylo,
    ...)
    p <- p + theme_tree()
    if (layout == "circular" || layout == "radial") {
    p <- layout_circular(p)
    p <- p + ylim(0, NA)
    }
    else if (layout == "fan") {
    p <- layout_fan(p, open.angle)
    }
    class(p) <- c("ggtree", class(p))
    return(p)
    }

    先有一个大致印象,然后看下面我的解读。

    设置布局
    layout %<>% match.arg(c("rectangular", "slanted", "fan",
    "circular", "radial", "unrooted", "equal_angle", "daylight"))
    match.args(arg, choices, several.ok = FALSE): 将传入的arg与choice的选项进行匹配。比如说match.args("A",c("ABC","BC","DE")), 返回的结果是"ABC"。
    '%<>'操作符来自于magrittr包,一种管道操作符,用操作符后跟的函数更新操作符前的数据,比如说

    a <- c(1,4,9,16)
    a %<>% sqrt
    a
    1,2,3,4
    所以这行的代码,保证了我们在输入时可以偷懒,比如说ggtree(tree, 're'),等于是说定义layout为rectangular,也限定了输入。我只是一般都是条件语句,实现这个功能, 不太优雅。

    if (layout == "unrooted") {
        layout <- "daylight"
        message("\"daylight\" method was used as default layout for unrooted tree.")
    }
    

    这一行表明,'unrooted'的布局和'daylight'(日光?)一样,下面的做的图是一样的,果然像太阳光。message()用于返回提示信息。

    library("ggtree")
    nwk <- system.file("extdata", "sample.nwk", package="treeio")
    tree <- read.tree(nwk)
    ggtree(tree, 'da')
    ggtree(tree, 'un')

    'daylight
    if (is(tr, "r8s") && branch.length == "branch.length") {
    branch.length = "TREE"
    }
    用is()判断tree是不是'r8s'类,且 branch.length是“branch.length',则branch.length赋值为’TREE'。其中r8s文件通过read.r8s输入,r8s文件的内容长如下样子。

    "node 127 (YGSIV1526_SW_HK_1284_2012) age= 0 | anc 91 () age= 3.6 | dur= 3.6 len= 3 rate= 6.09 nodeReal= 0 age bounds=[0..0]"

    if (yscale != "none") {
    layout <- "slanted"
    }
    判断yscale是不是为”none",如果随便输入字符,结果layout就是“slanted".但是yscale的用途我还没有找到,还在努力寻找中。

    所以ggtree(tree, yscale = "ha")和ggtree(tree, layout = 'sl')结果是一致。

    slanted
    定义映射
    if (is.null(mapping)) {
    mapping <- aes_(~x, ~y)
    }
    else {
    mapping <- modifyList(aes_(~x, ~y), mapping)
    }
    这个就涉及到ggplot2的图形属性映射。如果没有特殊说明,就是用aes_()把传入的tree对象的x和y映射到position(x,y).或者是用modifyList修改之前的mapping。
    注modifyList设计到一个知识点,R语言的S3类的面向对象编程(OOP).S3类的结构如同堆在一起的卵石。一个类的实例是通过构建一个列表的方式来创建的,这个列表的组件是该类的成员变量。
    举例说明:

    mapping <- aes_(~mpg, ~wt, col= ~cyl)

    输出的时候调用了泛型函数,保证输出美观

    mapping

    • colour -> cyl
    • x -> mpg
    • y -> wt

    其实真实内容如下

    str(mapping)
    List of 3
    colour: symbol cyl x : symbol mpg
    $ y : symbol wt
    如果我要添加新的映射,如'shape=carb',操作如下

    modifyList(mapping, aes_(shape = ~ carb))

    • colour -> cyl
    • x -> mpg
    • y -> wt
    • shape -> carb
      而tree里面刚好也有x和y变量,

    data.frame(tree)
    node parent length x y label isTip branch angle
    1 1 20 4 48 1.000000 A TRUE 46.0 27.69231
    2 2 20 4 48 2.000000 B TRUE 46.0 55.38462
    3 3 19 5 43 3.000000 C TRUE 40.5 83.07692
    ....
    虽然目前还不知道x和y在read.tree是如何计算出来,正在努力读源码。但如果直接用ggplot作图ggplot(data.frame(tree), aes(x=x,y=y)) + geom_point()能隐约发现slanted的布局的模样。

    ggplot2
    生成ggplot实体
    p <- ggplot(tr, mapping = mapping, layout = layout, mrsd = mrsd,
    as.Date = as.Date, yscale = yscale, yscale_mapping = yscale_mapping,
    ladderize = ladderize, right = right, branch.length = branch.length,
    ndigits = ndigits, ...)
    这个部分就是Y叔为什么说自己的ggtree是完美支持图形语法的原因。ggplot()输入参数有一个'...',这里表示可以输入自己的额外参数,用于后续操作,比如说ggplot(tree, hello="world")中的hello参数可以没有任何作用。

    一些参数调整
    首先判断是否为multiPhylo类

    if (is(tr, "multiPhylo")) {
        multiPhylo <- TRUE
    }
    else {
        multiPhylo <- FALSE
    }
    

    这个就是判断tr是否为multiPhylo.multiphylo {ape}类能用被来操作tree的列表。

    在ggplot实体上加上图层
    p <- p + geom_tree(layout = layout, multiPhylo = multiPhylo,
    ...)
    p <- p + theme_tree()
    if (layout == "circular" || layout == "radial") {
    p <- layout_circular(p)
    p <- p + ylim(0, NA)
    }
    else if (layout == "fan") {
    p <- layout_fan(p, open.angle)
    }
    这里涉及到另外几个Y叔写的函数geom_tree和theme_tree,layout_circular和layout_fan分别用于添加作图层,修改主题,调整布局,限于篇幅,下次读。

    https://blog.csdn.net/u012110870/article/details/102804075

    定义ggtree类
    class(p) <- c("ggtree", class(p))
    S3类的OOP就是attr()或者class()手动设置。

    总结
    总结一下这次读源码学习到的一些函数,以及回顾到的知识点。

    message()
    match.arg()
    %<>%{magrittr}
    modifyList()
    ase_()
    ...的含义是储备变量,可以用..1,..2,..n来调用,或者是用变量名。
    面向对象编程OOP的基本概念重新回顾
    ————————————————
    版权声明:本文为CSDN博主「徐洲更hoptop」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/u012110870/article/details/102804075

    相关文章

      网友评论

          本文标题:深入ggtree:ggtree()源码解读

          本文链接:https://www.haomeiwen.com/subject/dpjgartx.html