... | ... |
@@ -2,7 +2,7 @@ Package: ggtree |
2 | 2 |
Type: Package |
3 | 3 |
Title: an R package for visualization and annotation of phylogenetic trees with |
4 | 4 |
their covariates and other associated data |
5 |
-Version: 1.11.3 |
|
5 |
+Version: 1.11.4 |
|
6 | 6 |
Authors@R: c( |
7 | 7 |
person("Guangchuang", "Yu", email = "guangchuangyu@gmail.com", role = c("aut", "cre", "cph"), comment = c(ORCID = "0000-0002-6485-8781")), |
8 | 8 |
person("Tommy Tsan-Yuk", "Lam", email = "tylam.tommy@gmail.com", role = c("aut", "ths")), |
... | ... |
@@ -165,54 +165,54 @@ scaleY <- function(phylo, df, yscale, layout, ...) { |
165 | 165 |
## } |
166 | 166 |
|
167 | 167 |
|
168 |
-## used by layoutEqualAngle |
|
169 |
-## will change to tidytree::as_data_frame in future |
|
170 |
-as.data.frame.phylo_ <- function(x, layout="rectangular", |
|
171 |
- branch.length="branch.length", ...) { |
|
172 |
- if (branch.length != 'none') { |
|
173 |
- branch.length = "branch.length" |
|
174 |
- } |
|
175 |
- tip.label <- x[["tip.label"]] |
|
176 |
- Ntip <- length(tip.label) |
|
177 |
- N <- getNodeNum(x) |
|
178 |
- edge <- as.data.frame(x[["edge"]]) |
|
179 |
- colnames(edge) <- c("parent", "node") |
|
180 |
- if (! is.null(x$edge.length)) { |
|
181 |
- edge$length <- x$edge.length |
|
182 |
- if (branch.length == "none") { |
|
183 |
- xpos <- getXcoord_no_length(x) |
|
184 |
- ypos <- getYcoord(x) |
|
185 |
- } else { |
|
186 |
- xpos <- getXcoord(x) |
|
187 |
- ypos <- getYcoord(x) |
|
188 |
- } |
|
189 |
- ## } else if (layout != "cladogram") { |
|
190 |
- ## xpos <- getXcoord(x) |
|
191 |
- ## ypos <- getYcoord(x) |
|
192 |
- ## } else { |
|
193 |
- ## ## layout == "cladogram" && branch.length != "none" |
|
194 |
- ## xy <- getXYcoord_cladogram(x) |
|
195 |
- ## xpos <- xy$x |
|
196 |
- ## ypos <- xy$y |
|
197 |
- ## } |
|
198 |
- } else { |
|
199 |
- xpos <- getXcoord_no_length(x) |
|
200 |
- ypos <- getYcoord(x) |
|
201 |
- } |
|
202 |
- xypos <- data.frame(node=1:N, x=xpos, y=ypos) |
|
203 |
- res <- merge(edge, xypos, by.x="node", by.y="node", all.y=TRUE) |
|
204 |
- label <- rep(NA, N) |
|
205 |
- label[1:Ntip] <- tip.label |
|
206 |
- if ( !is.null(x$node.label) ) { |
|
207 |
- label[(Ntip+1):N] <- x$node.label |
|
208 |
- } |
|
209 |
- res$label <- label |
|
210 |
- isTip <- rep(FALSE, N) |
|
211 |
- isTip[1:Ntip] <- TRUE |
|
212 |
- res$isTip <- isTip |
|
213 |
- ## add branch mid position |
|
214 |
- res <- calculate_branch_mid(res) |
|
215 |
- ## ## angle for all layout, if 'rectangular', user use coord_polar, can still use angle |
|
216 |
- res <- calculate_angle(res) |
|
217 |
- return(res) |
|
218 |
-} |
|
168 |
+## ## used by layoutEqualAngle |
|
169 |
+## ## will change to tidytree::as_data_frame in future |
|
170 |
+## as.data.frame.phylo_ <- function(x, layout="rectangular", |
|
171 |
+## branch.length="branch.length", ...) { |
|
172 |
+## if (branch.length != 'none') { |
|
173 |
+## branch.length = "branch.length" |
|
174 |
+## } |
|
175 |
+## tip.label <- x[["tip.label"]] |
|
176 |
+## Ntip <- length(tip.label) |
|
177 |
+## N <- getNodeNum(x) |
|
178 |
+## edge <- as.data.frame(x[["edge"]]) |
|
179 |
+## colnames(edge) <- c("parent", "node") |
|
180 |
+## if (! is.null(x$edge.length)) { |
|
181 |
+## edge$length <- x$edge.length |
|
182 |
+## if (branch.length == "none") { |
|
183 |
+## xpos <- getXcoord_no_length(x) |
|
184 |
+## ypos <- getYcoord(x) |
|
185 |
+## } else { |
|
186 |
+## xpos <- getXcoord(x) |
|
187 |
+## ypos <- getYcoord(x) |
|
188 |
+## } |
|
189 |
+## ## } else if (layout != "cladogram") { |
|
190 |
+## ## xpos <- getXcoord(x) |
|
191 |
+## ## ypos <- getYcoord(x) |
|
192 |
+## ## } else { |
|
193 |
+## ## ## layout == "cladogram" && branch.length != "none" |
|
194 |
+## ## xy <- getXYcoord_cladogram(x) |
|
195 |
+## ## xpos <- xy$x |
|
196 |
+## ## ypos <- xy$y |
|
197 |
+## ## } |
|
198 |
+## } else { |
|
199 |
+## xpos <- getXcoord_no_length(x) |
|
200 |
+## ypos <- getYcoord(x) |
|
201 |
+## } |
|
202 |
+## xypos <- data.frame(node=1:N, x=xpos, y=ypos) |
|
203 |
+## res <- merge(edge, xypos, by.x="node", by.y="node", all.y=TRUE) |
|
204 |
+## label <- rep(NA, N) |
|
205 |
+## label[1:Ntip] <- tip.label |
|
206 |
+## if ( !is.null(x$node.label) ) { |
|
207 |
+## label[(Ntip+1):N] <- x$node.label |
|
208 |
+## } |
|
209 |
+## res$label <- label |
|
210 |
+## isTip <- rep(FALSE, N) |
|
211 |
+## isTip[1:Ntip] <- TRUE |
|
212 |
+## res$isTip <- isTip |
|
213 |
+## ## add branch mid position |
|
214 |
+## res <- calculate_branch_mid(res) |
|
215 |
+## ## ## angle for all layout, if 'rectangular', user use coord_polar, can still use angle |
|
216 |
+## res <- calculate_angle(res) |
|
217 |
+## return(res) |
|
218 |
+## } |
... | ... |
@@ -49,10 +49,6 @@ ggtree <- function(tr, |
49 | 49 |
message('"daylight" method was used as default layout for unrooted tree.') |
50 | 50 |
} |
51 | 51 |
|
52 |
- if (is(tr, "r8s") && branch.length == "branch.length") { |
|
53 |
- branch.length = "TREE" |
|
54 |
- } |
|
55 |
- |
|
56 | 52 |
if(yscale != "none") { |
57 | 53 |
## for 2d tree |
58 | 54 |
layout <- "slanted" |
... | ... |
@@ -29,20 +29,24 @@ fortify.phylo <- function(model, data, |
29 | 29 |
} |
30 | 30 |
} |
31 | 31 |
|
32 |
- if (is.null(x$edge.length) || branch.length == "none") { |
|
33 |
- xpos <- getXcoord_no_length(x) |
|
32 |
+ if (layout %in% c("equal_angle", "daylight")) { |
|
33 |
+ res <- layout.unrooted(x, layout.method = layout, branch.length = branch.length, ...) |
|
34 | 34 |
} else { |
35 |
- xpos <- getXcoord(x) |
|
36 |
- } |
|
35 |
+ if (is.null(x$edge.length) || branch.length == "none") { |
|
36 |
+ xpos <- getXcoord_no_length(x) |
|
37 |
+ } else { |
|
38 |
+ xpos <- getXcoord(x) |
|
39 |
+ } |
|
37 | 40 |
|
38 |
- ypos <- getYcoord(x) |
|
39 |
- N <- Nnode(x, internal.only=FALSE) |
|
40 |
- xypos <- data_frame(node=1:N, x=xpos, y=ypos) |
|
41 |
+ ypos <- getYcoord(x) |
|
42 |
+ N <- Nnode(x, internal.only=FALSE) |
|
43 |
+ xypos <- data_frame(node=1:N, x=xpos, y=ypos) |
|
41 | 44 |
|
42 |
- df <- as_data_frame(model) %>% |
|
43 |
- mutate_(isTip = ~(! node %in% parent)) |
|
45 |
+ df <- as_data_frame(model) %>% |
|
46 |
+ mutate_(isTip = ~(! node %in% parent)) |
|
44 | 47 |
|
45 |
- res <- full_join(df, xypos, by = "node") |
|
48 |
+ res <- full_join(df, xypos, by = "node") |
|
49 |
+ } |
|
46 | 50 |
|
47 | 51 |
## add branch mid position |
48 | 52 |
res <- calculate_branch_mid(res) |
... | ... |
@@ -1,12 +1,5 @@ |
1 | 1 |
|
2 | 2 |
|
3 |
- |
|
4 |
- |
|
5 |
- |
|
6 |
- |
|
7 |
- |
|
8 |
- |
|
9 |
- |
|
10 | 3 |
##' @importFrom ape reorder.phylo |
11 | 4 |
layout.unrooted <- function(tree, branch.length="branch.length", layout.method="equal_angle", ...) { |
12 | 5 |
|
... | ... |
@@ -18,6 +11,21 @@ layout.unrooted <- function(tree, branch.length="branch.length", layout.method=" |
18 | 11 |
return(df) |
19 | 12 |
} |
20 | 13 |
|
14 |
+set_branch_length_cladogram <- function(tree) { |
|
15 |
+ phylo <- as.phylo(tree) |
|
16 |
+ edge <- phylo$edge |
|
17 |
+ xpos <- getXcoord_no_length(phylo) |
|
18 |
+ phylo$edge.length <- xpos[edge[,2]] - xpos[edge[,1]] |
|
19 |
+ |
|
20 |
+ if (is(tree, "phylo")) { |
|
21 |
+ return(phylo) |
|
22 |
+ } else if (is(tree, "treedata")) { |
|
23 |
+ tree@phylo <- phylo |
|
24 |
+ return(tree) |
|
25 |
+ } |
|
26 |
+ message("unknown tree object, fail to set branch length for cladogram...") |
|
27 |
+ return(tree) |
|
28 |
+} |
|
21 | 29 |
|
22 | 30 |
##' 'Equal-angle layout algorithm for unrooted trees' |
23 | 31 |
##' |
... | ... |
@@ -29,9 +37,15 @@ layout.unrooted <- function(tree, branch.length="branch.length", layout.method=" |
29 | 37 |
##' @param branch.length set to 'none' for edge length of 1. Otherwise the phylogenetic tree edge length is used. |
30 | 38 |
##' @return tree as data.frame with equal angle layout. |
31 | 39 |
layoutEqualAngle <- function(tree, branch.length ){ |
40 |
+ if (branch.length == "none") { |
|
41 |
+ tree <- set_branch_length_cladogram(tree) |
|
42 |
+ } |
|
43 |
+ |
|
32 | 44 |
root <- getRoot(tree) |
33 | 45 |
## Convert Phylo tree to data.frame. |
34 |
- df <- as.data.frame.phylo_(tree) |
|
46 |
+ ## df <- as.data.frame.phylo_(tree) |
|
47 |
+ df <- as_data_frame(tree) %>% |
|
48 |
+ mutate_(isTip = ~(! node %in% parent)) |
|
35 | 49 |
|
36 | 50 |
## NOTE: Angles (start, end, angle) are in half-rotation units (radians/pi or degrees/180) |
37 | 51 |
|
... | ... |
@@ -82,11 +96,11 @@ layoutEqualAngle <- function(tree, branch.length ){ |
82 | 96 |
## beta = angle of line from parent node to i-th child. |
83 | 97 |
beta <- start + alpha / 2 |
84 | 98 |
|
85 |
- if (branch.length == "none") { |
|
86 |
- length.child <- 1 |
|
87 |
- } else { |
|
88 |
- length.child <- df[child, "length"] |
|
89 |
- } |
|
99 |
+ ## if (branch.length == "none") { |
|
100 |
+ ## length.child <- 1 |
|
101 |
+ ## } else { |
|
102 |
+ length.child <- df[child, "branch.length"] |
|
103 |
+ ##} |
|
90 | 104 |
|
91 | 105 |
## update geometry of data.frame. |
92 | 106 |
## Calculate (x,y) position of the i-th child node from current node. |
... | ... |
@@ -169,7 +183,7 @@ layoutDaylight <- function( tree, branch.length ){ |
169 | 183 |
# Calculate the running average of angle changes. |
170 | 184 |
ave_change <- total_max / length(nodes) * length(i) |
171 | 185 |
|
172 |
- cat('Average angle change [',i,']', ave_change,'\n') |
|
186 |
+ message('Average angle change [',i,'] ', ave_change) |
|
173 | 187 |
|
174 | 188 |
i <- i + 1 |
175 | 189 |
} |
... | ... |
@@ -237,19 +251,19 @@ applyLayoutDaylight <- function(df, node_id){ |
237 | 251 |
# Find start and end angles for each subtree. |
238 | 252 |
# subtrees = get subtrees of node |
239 | 253 |
# for i-th subtree in subtrees { |
240 |
- for (i in seq_along(subtrees) ) { |
|
241 |
- subtree <- subtrees[[i]] |
|
242 |
- # [end, start] = get start and end angles of tree. |
|
243 |
- |
|
244 |
- angles <- getTreeArcAngles(df, node_id, subtree) |
|
245 |
- angle_list[ i, 'subtree_id'] <- i |
|
246 |
- angle_list[ i, 'left'] <- angles['left'] |
|
247 |
- angle_list[ i, 'beta'] <- angles['left'] - angles['right'] # subtree arc angle |
|
248 |
- # If subtree arc angle is -ve, then + 2 (360). |
|
249 |
- if(angle_list[ i, 'beta'] < 0 ){ |
|
250 |
- angle_list[ i, 'beta'] <- angle_list[ i, 'beta'] + 2 |
|
254 |
+ for (i in seq_along(subtrees) ) { |
|
255 |
+ subtree <- subtrees[[i]] |
|
256 |
+ # [end, start] = get start and end angles of tree. |
|
257 |
+ |
|
258 |
+ angles <- getTreeArcAngles(df, node_id, subtree) |
|
259 |
+ angle_list[ i, 'subtree_id'] <- i |
|
260 |
+ angle_list[ i, 'left'] <- angles['left'] |
|
261 |
+ angle_list[ i, 'beta'] <- angles['left'] - angles['right'] # subtree arc angle |
|
262 |
+ # If subtree arc angle is -ve, then + 2 (360). |
|
263 |
+ if(angle_list[ i, 'beta'] < 0 ){ |
|
264 |
+ angle_list[ i, 'beta'] <- angle_list[ i, 'beta'] + 2 |
|
265 |
+ } |
|
251 | 266 |
} |
252 |
- } |
|
253 | 267 |
# sort angle_list by 'left angle' column in ascending order. |
254 | 268 |
angle_list <- angle_list[with(angle_list, order(left)), ] |
255 | 269 |
# D = 360 - sum( angle_list['beta'] ) # total day |
... | ... |
@@ -293,59 +307,59 @@ applyLayoutDaylight <- function(df, node_id){ |
293 | 307 |
##' @param subtree named list of root id of subtree (node) and list of node ids for given subtree (subtree). |
294 | 308 |
##' @return named list with right and left angles in range [0,2] i.e 1 = 180 degrees, 1.5 = 270 degrees. |
295 | 309 |
getTreeArcAngles <- function(df, origin_id, subtree) { |
296 |
- # Initialise variables |
|
297 |
- theta_child <- 0.0 |
|
298 |
- subtree_root_id <- subtree$node |
|
299 |
- subtree_node_ids <- subtree$subtree |
|
300 |
- |
|
301 |
- # Initialise angle from origin node to parent node. |
|
302 |
- # If subtree_root_id is child of origin_id |
|
303 |
- if( any(subtree_root_id == getChild.df(df, origin_id)) ){ |
|
304 |
- # get angle from original node to parent of subtree. |
|
305 |
- theta_left <- getNodeAngle.df(df, origin_id, subtree_root_id) |
|
306 |
- theta_right <- theta_left |
|
307 |
- }else if( subtree_root_id == origin_id){ |
|
308 |
- # Special case. |
|
309 |
- # get angle from parent of subtree to children |
|
310 |
- children_ids <- getChild.df(df, subtree_root_id) |
|
311 |
- |
|
312 |
- if(length(children_ids) == 2){ |
|
313 |
- # get angles from parent to it's two children. |
|
314 |
- theta1 <- getNodeAngle.df(df, origin_id, children_ids[1]) |
|
315 |
- theta2 <- getNodeAngle.df(df, origin_id, children_ids[2]) |
|
316 |
- |
|
317 |
- delta <- theta1 - theta2 |
|
318 |
- |
|
319 |
- |
|
320 |
- # correct delta for points crossing 180/-180 quadrant. |
|
321 |
- if(delta > 1){ |
|
322 |
- delta_adj = delta - 2 |
|
323 |
- }else if(delta < -1){ |
|
324 |
- delta_adj = delta + 2 |
|
325 |
- }else{ |
|
326 |
- delta_adj <- delta |
|
327 |
- } |
|
310 |
+ ## Initialise variables |
|
311 |
+ theta_child <- 0.0 |
|
312 |
+ subtree_root_id <- subtree$node |
|
313 |
+ subtree_node_ids <- subtree$subtree |
|
314 |
+ |
|
315 |
+ ## Initialise angle from origin node to parent node. |
|
316 |
+ ## If subtree_root_id is child of origin_id |
|
317 |
+ if( any(subtree_root_id == getChild.df(df, origin_id)) ){ |
|
318 |
+ ## get angle from original node to parent of subtree. |
|
319 |
+ theta_left <- getNodeAngle.df(df, origin_id, subtree_root_id) |
|
320 |
+ theta_right <- theta_left |
|
321 |
+ } else if( subtree_root_id == origin_id ){ |
|
322 |
+ ## Special case. |
|
323 |
+ ## get angle from parent of subtree to children |
|
324 |
+ children_ids <- getChild.df(df, subtree_root_id) |
|
325 |
+ |
|
326 |
+ if(length(children_ids) == 2){ |
|
327 |
+ ## get angles from parent to it's two children. |
|
328 |
+ theta1 <- getNodeAngle.df(df, origin_id, children_ids[1]) |
|
329 |
+ theta2 <- getNodeAngle.df(df, origin_id, children_ids[2]) |
|
330 |
+ |
|
331 |
+ delta <- theta1 - theta2 |
|
332 |
+ |
|
333 |
+ |
|
334 |
+ ## correct delta for points crossing 180/-180 quadrant. |
|
335 |
+ if(delta > 1){ |
|
336 |
+ delta_adj = delta - 2 |
|
337 |
+ } else if(delta < -1){ |
|
338 |
+ delta_adj = delta + 2 |
|
339 |
+ } else{ |
|
340 |
+ delta_adj <- delta |
|
341 |
+ } |
|
328 | 342 |
|
329 |
- if(delta_adj >= 0){ |
|
330 |
- theta_left = theta1 |
|
331 |
- theta_right = theta2 |
|
332 |
- }else if(delta_adj < 0){ |
|
333 |
- theta_left = theta2 |
|
334 |
- theta_right = theta1 |
|
335 |
- } |
|
336 |
- }else{ |
|
337 |
- # subtree only has one child node. |
|
338 |
- theta_left <- getNodeAngle.df(df, origin_id, children_ids[1]) |
|
339 |
- theta_right <- theta_left |
|
340 |
- } |
|
343 |
+ if(delta_adj >= 0){ |
|
344 |
+ theta_left = theta1 |
|
345 |
+ theta_right = theta2 |
|
346 |
+ } else if(delta_adj < 0){ |
|
347 |
+ theta_left = theta2 |
|
348 |
+ theta_right = theta1 |
|
349 |
+ } |
|
350 |
+ }else{ |
|
351 |
+ ## subtree only has one child node. |
|
352 |
+ theta_left <- getNodeAngle.df(df, origin_id, children_ids[1]) |
|
353 |
+ theta_right <- theta_left |
|
354 |
+ } |
|
341 | 355 |
|
342 |
- }else{ |
|
343 |
- # get the real root of df tree to initialise left and right angles. |
|
344 |
- tree_root <- getRoot.df(df) |
|
345 |
- if( !is.na(tree_root) & is.numeric(tree_root) ){ |
|
346 |
- theta_left <- getNodeAngle.df(df, origin_id, tree_root) |
|
347 |
- theta_right <- theta_left |
|
348 |
- }else{ |
|
356 |
+ } else { |
|
357 |
+ ## get the real root of df tree to initialise left and right angles. |
|
358 |
+ tree_root <- getRoot.df(df) |
|
359 |
+ if( !is.na(tree_root) & is.numeric(tree_root) ){ |
|
360 |
+ theta_left <- getNodeAngle.df(df, origin_id, tree_root) |
|
361 |
+ theta_right <- theta_left |
|
362 |
+ } else{ |
|
349 | 363 |
print('ERROR: no root found!') |
350 | 364 |
theta_left <- NA |
351 | 365 |
} |
... | ... |
@@ -526,8 +540,8 @@ rotateTreePoints.df <- function(df, pivot_node, nodes, angle){ |
526 | 540 |
##' @return angle in range [-1, 1], i.e. degrees/180, radians/pi |
527 | 541 |
getNodeAngle.df <- function(df, origin_node_id, node_id){ |
528 | 542 |
if( (origin_node_id != node_id) & any(origin_node_id %in% df$node) & any(node_id %in% df$node) ){ |
529 |
- delta_x <- df[node_id, 'x'] - df[origin_node_id, 'x'] |
|
530 |
- delta_y <- df[node_id, 'y'] - df[origin_node_id, 'y'] |
|
543 |
+ delta_x <- df$x[node_id] - df$x[origin_node_id] |
|
544 |
+ delta_y <- df$y[node_id] - df$y[origin_node_id] |
|
531 | 545 |
angle <- atan2(delta_y, delta_x) / pi |
532 | 546 |
return( angle ) |
533 | 547 |
}else{ |
... | ... |
@@ -681,8 +695,9 @@ getRoot.df <- function(df, node){ |
681 | 695 |
root <- which(is.na(df$parent)) |
682 | 696 |
# Check if root was found. |
683 | 697 |
if(length(root) == 0){ |
684 |
- # Alternatively, root can self reference, eg node = 10, parent = 10 |
|
685 |
- root <- unlist(apply(df, 1, function(x){ if(x['node'] == x['parent']){ x['node'] } })) |
|
698 |
+ ## Alternatively, root can self reference, eg node = 10, parent = 10 |
|
699 |
+ root <- df$node[df$parent == df$node] |
|
700 |
+ ## root <- unlist(apply(df, 1, function(x){ if(x['node'] == x['parent']){ x['node'] } })) |
|
686 | 701 |
} |
687 | 702 |
return(root) |
688 | 703 |
} |
... | ... |
@@ -4,7 +4,7 @@ ggtree: an R package for visualization and annotation of phylogenetic trees with |
4 | 4 |
|
5 | 5 |
<img src="https://raw.githubusercontent.com/Bioconductor/BiocStickers/master/ggtree/ggtree.png" height="200" align="right" /> |
6 | 6 |
|
7 |
-[](https://bioconductor.org/packages/ggtree) [](https://github.com/guangchuangyu/ggtree) [](https://www.bioconductor.org/packages/devel/bioc/html/ggtree.html#since) [](https://bioconductor.org/packages/stats/bioc/ggtree) [](https://bioconductor.org/packages/stats/bioc/ggtree) |
|
7 |
+[](https://bioconductor.org/packages/ggtree) [](https://github.com/guangchuangyu/ggtree) [](https://www.bioconductor.org/packages/devel/bioc/html/ggtree.html#since) [](https://bioconductor.org/packages/stats/bioc/ggtree) [](https://bioconductor.org/packages/stats/bioc/ggtree) |
|
8 | 8 |
|
9 | 9 |
[](http://www.repostatus.org/#active) [](https://codecov.io/gh/GuangchuangYu/ggtree) [](https://github.com/GuangchuangYu/ggtree/commits/master) [](https://github.com/GuangchuangYu/ggtree/network) [](https://github.com/GuangchuangYu/ggtree/stargazers) [](https://awesome-r.com/#awesome-r-graphic-displays) |
10 | 10 |
|
... | ... |
@@ -14,7 +14,7 @@ output: |
14 | 14 |
pdf_document: |
15 | 15 |
toc: true |
16 | 16 |
vignette: > |
17 |
- %\VignetteIndexEntry{00 ggtree introduction} |
|
17 |
+ %\VignetteIndexEntry{01 ggtree Introduction} |
|
18 | 18 |
%\VignetteEngine{knitr::rmarkdown} |
19 | 19 |
%\usepackage[utf8]{inputenc} |
20 | 20 |
--- |
... | ... |
@@ -124,14 +124,29 @@ and *daylight* for *unrooted* layout, time-scaled and two dimentional |
124 | 124 |
phylogenies. [Tree Visualization](treeVisualization.html) vignette describes |
125 | 125 |
these feature in details. |
126 | 126 |
|
127 |
-We implement several functions to manipulate a phylogenetic tree. |
|
127 |
+We implement several functions to manipulate a phylogenetic tree visually, |
|
128 |
+including viewing selected clade to explore large tree, taxa clustering, |
|
129 |
+rotating clade or tree, zoom out or collapsing clades *etc.*. |
|
128 | 130 |
|
129 |
-+ taxa can be clustered together using `groupClade` or `groupOTU` functions |
|
130 |
-+ clades can be collapsed via `collapse` function |
|
131 |
-+ collapsed clade can be expanded by using `expand` function |
|
132 |
-+ clade can be re-scale to zoom in or zoom out by `scaleClade` function |
|
133 |
-+ selected clade can be rotated by 180 degree using `rotate` function |
|
134 |
-+ position of two selected clades (should share a same parent) can be exchanged by `flip` function |
|
131 |
+ |
|
132 |
+ |
|
133 |
+```{r treeman, echo=FALSE, out.extra='', message=FALSE} |
|
134 |
+treeman <- matrix(c( |
|
135 |
+ "collapse", "collapse a selecting clade", |
|
136 |
+ "expand", "expand collapsed clade", |
|
137 |
+ "flip", "exchange position of 2 clades that share a parent node", |
|
138 |
+ "groupClade", "grouping clades", |
|
139 |
+ "groupOTU", "grouping OTUs by tracing back to most recent common ancestor", |
|
140 |
+ "identify", "interactive tree manipulation", |
|
141 |
+ "rotate", "rotating a selected clade by 180 degree", |
|
142 |
+ "rotate_tree", "rotating circular layout tree by specific angle", |
|
143 |
+ "scaleClade", "zoom in or zoom out selecting clade", |
|
144 |
+ "open_tree", "convert a tree to fan layout by specific open angle" |
|
145 |
+), ncol=2, byrow=TRUE) |
|
146 |
+treeman <- as.data.frame(treeman) |
|
147 |
+colnames(treeman) <- c("Function", "Descriptiotn") |
|
148 |
+knitr::kable(treeman, caption = "Tree manipulation functions.", booktabs = T) |
|
149 |
+``` |
|
135 | 150 |
|
136 | 151 |
|
137 | 152 |
Details and examples can be found in [Tree Manipulation](treeManipulation.html) vignette. |
... | ... |
@@ -5,7 +5,7 @@ author: "Guangchuang Yu and Tommy Tsan-Yuk Lam\\ |
5 | 5 |
School of Public Health, The University of Hong Kong" |
6 | 6 |
date: "`r Sys.Date()`" |
7 | 7 |
bibliography: ggtree.bib |
8 |
-csl: nature.csl |
|
8 |
+biblio-style: apalike |
|
9 | 9 |
output: |
10 | 10 |
prettydoc::html_pretty: |
11 | 11 |
toc: true |
... | ... |
@@ -28,41 +28,62 @@ knitr::opts_chunk$set(tidy = FALSE, |
28 | 28 |
```{r echo=FALSE, results="hide", message=FALSE} |
29 | 29 |
library("ape") |
30 | 30 |
library("ggplot2") |
31 |
+library("cowplot") |
|
32 |
+library("treeio") |
|
31 | 33 |
library("ggtree") |
34 |
+ |
|
35 |
+ |
|
36 |
+CRANpkg <- function (pkg) { |
|
37 |
+ cran <- "https://CRAN.R-project.org/package" |
|
38 |
+ fmt <- "[%s](%s=%s)" |
|
39 |
+ sprintf(fmt, pkg, cran, pkg) |
|
40 |
+} |
|
41 |
+ |
|
42 |
+Biocpkg <- function (pkg) { |
|
43 |
+ sprintf("[%s](http://bioconductor.org/packages/%s)", pkg, pkg) |
|
44 |
+} |
|
32 | 45 |
``` |
33 | 46 |
|
34 | 47 |
|
35 |
-To view a phylogenetic tree, we first need to parse the tree file into `R`. The `ggtree` package supports many file formats including output files of commonly used software packages in evolutionary biology. For more details, plase refer to the [Tree Data Import](treeImport.html) vignette. |
|
48 |
+To view a phylogenetic tree, we first need to parse the tree file into *R*. The |
|
49 |
+`r Biocpkg('ggtree')` package supports many file formats via the `r |
|
50 |
+Biocpkg('treeio')` package, including output files of commonly used software |
|
51 |
+packages in evolutionary biology. For more details, plase refer to |
|
52 |
+the [treeio vignette](https://bioconductor.org/packages/devel/bioc/vignettes/treeio/inst/doc/Importer.html). |
|
36 | 53 |
|
37 | 54 |
```{r} |
55 |
+library("treeio") |
|
38 | 56 |
library("ggtree") |
57 |
+ |
|
39 | 58 |
nwk <- system.file("extdata", "sample.nwk", package="treeio") |
40 | 59 |
tree <- read.tree(nwk) |
41 | 60 |
``` |
42 | 61 |
|
43 |
-# Viewing a phylogenetic tree with `ggtree` |
|
62 |
+# Viewing a phylogenetic tree with *ggtree* |
|
44 | 63 |
|
45 |
-The `ggtree` package extends _`ggplot2`_ package to support viewing phylogenetic tree. |
|
46 |
-It implements _`geom_tree`_ layer for displaying phylogenetic tree, as shown below: |
|
64 |
+The `r Biocpkg('ggtree')` package extends `r CRANpkg('ggplot2')` package to support viewing phylogenetic tree. |
|
65 |
+It implements `geom_tree` layer for displaying phylogenetic tree, as shown below: |
|
47 | 66 |
|
48 | 67 |
|
49 | 68 |
```{r fig.width=3, fig.height=3, fig.align="center"} |
50 | 69 |
ggplot(tree, aes(x, y)) + geom_tree() + theme_tree() |
51 | 70 |
``` |
52 | 71 |
|
53 |
-The function, _`ggtree`_, was implemented as a short cut to visualize a tree, and it works exactly the same as shown above. |
|
72 |
+The function, `ggtree`, was implemented as a short cut to visualize a tree, and it works exactly the same as shown above. |
|
73 |
+ |
|
74 |
+`r Biocpkg('ggtree')` takes all the advantages of `r CRANpkg('ggplot2')`. For example, we can change the color, size and type of the lines as we do with `r CRANpkg('ggplot2')`. |
|
54 | 75 |
|
55 |
-_`ggtree`_ takes all the advantages of _`ggplot2`_. For example, we can change the color, size and type of the lines as we do with _`ggplot2`_. |
|
56 | 76 |
```{r fig.width=3, fig.height=3, fig.align="center"} |
57 | 77 |
ggtree(tree, color="firebrick", size=1, linetype="dotted") |
58 | 78 |
``` |
59 | 79 |
|
60 |
-By default, the tree is viewed in ladderize form, user can set the parameter _`ladderize = FALSE`_ to disable it. |
|
80 |
+By default, the tree is viewed in ladderize form, user can set the parameter *ladderize = FALSE* to disable it. |
|
81 |
+ |
|
61 | 82 |
```{r fig.width=3, fig.height=3, fig.align="center"} |
62 | 83 |
ggtree(tree, ladderize=FALSE) |
63 | 84 |
``` |
64 | 85 |
|
65 |
-The _`branch.length`_ is used to scale the edge, user can set the parameter _`branch.length = "none"`_ to only view the tree topology (cladogram) or other numerical variable to scale the tree (e.g. _dN/dS_, see also in [Tree Annotation](treeAnnotation.html) vignette). |
|
86 |
+The *branch.length* is used to scale the edge, user can set the parameter *branch.length = "none"* to only view the tree topology (cladogram) or other numerical variable to scale the tree (*e.g.* _d~N~/d~S~_, see also in [Tree Annotation](treeAnnotation.html) vignette). |
|
66 | 87 |
|
67 | 88 |
```{r fig.width=3, fig.height=3, fig.align="center"} |
68 | 89 |
ggtree(tree, branch.length="none") |
... | ... |
@@ -70,79 +91,54 @@ ggtree(tree, branch.length="none") |
70 | 91 |
|
71 | 92 |
# Layout |
72 | 93 |
|
73 |
-Currently, _`ggtree`_ supports several layouts, including: |
|
74 |
- |
|
75 |
-+ `rectangular` (by default) |
|
76 |
-+ `slanted` |
|
77 |
-+ `circular` |
|
78 |
-+ `fan` |
|
79 |
- |
|
80 |
-for `Phylogram` (by default) and `Cladogram` if user explicitly setting `branch.length='none'`. |
|
81 |
-`ggtree` also supports `unrooted` layout. |
|
82 |
- |
|
83 |
- |
|
84 |
-## Phylogram |
|
85 |
- |
|
86 |
-__`rectangular`__ |
|
87 |
- |
|
88 |
-```{r fig.height=4, fig.width=4, fig.align="center"} |
|
89 |
-ggtree(tree) + ggtitle("(Phylogram) rectangular layout") |
|
90 |
-``` |
|
91 |
- |
|
92 |
-__`slanted`__ |
|
93 |
- |
|
94 |
-```{r fig.height=4, fig.width=4, fig.align="center"} |
|
95 |
-ggtree(tree, layout="slanted") + ggtitle("(Phylogram) slanted layout") |
|
94 |
+Currently, `r Biocpkg('ggtree')` supports several layouts, including: |
|
95 |
+ |
|
96 |
++ rectangular (by default) |
|
97 |
++ slanted |
|
98 |
++ circular |
|
99 |
++ fan |
|
100 |
+ |
|
101 |
+for *phylogram* (by default) and *cladogram* if user explicitly setting |
|
102 |
+*branch.length='none'*. Unrooted (equal angle and daylight methods), time-scaled |
|
103 |
+and 2-dimensional layouts are also supported. |
|
104 |
+ |
|
105 |
+```{r eval=F} |
|
106 |
+library(ggtree) |
|
107 |
+set.seed(2017-02-16) |
|
108 |
+tr <- rtree(50) |
|
109 |
+ggtree(tr) |
|
110 |
+ggtree(tr, layout="slanted") |
|
111 |
+ggtree(tr, layout="circular") |
|
112 |
+ggtree(tr, layout="fan", open.angle=120) |
|
113 |
+ggtree(tr, layout="equal_angle") |
|
114 |
+ggtree(tr, layout="daylight") |
|
115 |
+ggtree(tr, branch.length='none') |
|
116 |
+ggtree(tr, branch.length='none', layout='circular') |
|
117 |
+ggtree(tr, layout="daylight", branch.length = 'none') |
|
118 |
+``` |
|
119 |
+ |
|
120 |
+```{r echo=F, fig.width=8, fig.height=8, message=FALSE} |
|
121 |
+library(ggtree) |
|
122 |
+set.seed(2017-02-16) |
|
123 |
+x <- rtree(50) |
|
124 |
+library(cowplot) |
|
125 |
+theme_layout <- theme(plot.title = element_text(hjust = 0.5)) |
|
126 |
+plot_grid( |
|
127 |
+ ggtree(x) + ggtitle("rectangular (phylogram)")+ theme_layout, |
|
128 |
+ ggtree(x, layout="slanted") + ggtitle("slanted (phylogram)")+theme_layout, |
|
129 |
+ ggtree(x, layout="circular") + ggtitle("circular (phylogram)")+theme_layout, |
|
130 |
+ ggtree(x, layout="fan", open.angle=120) + ggtitle("fan (phylogram)")+theme_layout, |
|
131 |
+ ggtree(x, layout="equal_angle")+ ggtitle("equal angle (unrooted)")+theme_layout, |
|
132 |
+ ggtree(x, layout="daylight")+ ggtitle("daylight (unrooted)")+theme_layout, |
|
133 |
+ ggtree(x, branch.length='none')+ ggtitle("rectangular (cladogram)")+theme_layout, |
|
134 |
+ ggtree(x, branch.length='none', layout='circular')+ ggtitle("circular (cladogram)")+theme_layout, |
|
135 |
+ ggtree(x, layout="daylight", branch.length = 'none')+ ggtitle("daylight (cladogram)")+theme_layout, |
|
136 |
+ ncol=3) |
|
96 | 137 |
``` |
97 | 138 |
|
98 |
-__`circular`__ |
|
99 | 139 |
|
100 |
-```{r fig.height=5, fig.width=5, fig.align="center"} |
|
101 |
-ggtree(tree, layout="circular") + ggtitle("(Phylogram) circular layout") |
|
102 |
-``` |
|
103 |
- |
|
104 |
-__`fan`__ |
|
105 |
- |
|
106 |
-```{r fig.height=5, fig.width=5, fig.align="center"} |
|
107 |
-ggtree(tree, layout="fan", open.angle=180) + ggtitle("(Phylogram) fan layout") |
|
108 |
-``` |
|
109 | 140 |
|
110 | 141 |
|
111 |
-## Cladogram |
|
112 |
- |
|
113 |
-__`rectangular`__ |
|
114 |
- |
|
115 |
-```{r fig.height=4, fig.width=4, fig.align="center"} |
|
116 |
-ggtree(tree, branch.length='none') + ggtitle("(Cladogram) rectangular layout") |
|
117 |
-``` |
|
118 |
- |
|
119 |
-__`slanted`__ |
|
120 |
- |
|
121 |
-```{r fig.height=4, fig.width=4, fig.align="center"} |
|
122 |
-ggtree(tree, layout="slanted", branch.length='none') + ggtitle("(Cladogram) slanted layout") |
|
123 |
-``` |
|
124 |
- |
|
125 |
-__`circular`__ |
|
126 |
- |
|
127 |
-```{r fig.height=5, fig.width=5, fig.align="center"} |
|
128 |
-ggtree(tree, layout="circular", branch.length="none") + ggtitle("(Cladogram) circular layout") |
|
129 |
-``` |
|
130 |
- |
|
131 |
-__`fan`__ |
|
132 |
- |
|
133 |
-```{r fig.height=5, fig.width=5, fig.align="center"} |
|
134 |
-ggtree(tree, layout="fan", open.angle=180, branch.length="none") + ggtitle("(Cladogram) circular layout") |
|
135 |
-``` |
|
136 |
- |
|
137 |
- |
|
138 |
-## Unrooted |
|
139 |
- |
|
140 |
-Unrooted layout was implemented by the _`equal-angle algorithm`_ that described in _Inferring Phylogenies_[@felsenstein_inferring_2003 pp.578-580]. |
|
141 |
- |
|
142 |
-```{r fig.height=4, fig.width=4, fig.align="center"} |
|
143 |
-ggtree(tree, layout="unrooted") + ggtitle("unrooted layout") |
|
144 |
-``` |
|
145 |
- |
|
146 | 142 |
## Time-scaled tree |
147 | 143 |
|
148 | 144 |
A phylogenetic tree can be scaled by time (time-scaled tree) by specifying the parameter, `mrsd` (most recent sampling date). |