... | ... |
@@ -1,5 +1,7 @@ |
1 | 1 |
CHANGES IN VERSION 1.7.4 |
2 | 2 |
------------------------ |
3 |
+ o allow yscale to use data stored in phylo4d object <2016-11-24, Thu> |
|
4 |
+ + https://github.com/GuangchuangYu/ggtree/issues/98 |
|
3 | 5 |
o groupOTU method now accept 'overlap = c("overwrite", "origin", "abandon")' parameter <2016-11-16, Wed> |
4 | 6 |
+ https://groups.google.com/forum/#!topic/bioc-ggtree/Q4LnwoTf1DM |
5 | 7 |
|
... | ... |
@@ -18,7 +18,7 @@ as.binary.phylo <- function(tree, ...) { |
18 | 18 |
cat("The input tree is already binary...\n") |
19 | 19 |
invisible(tree) |
20 | 20 |
} |
21 |
- |
|
21 |
+ |
|
22 | 22 |
polyNode <- tree$edge[,1] %>% table %>% '>'(2) %>% |
23 | 23 |
which %>% names %>% as.numeric |
24 | 24 |
|
... | ... |
@@ -35,7 +35,7 @@ as.binary.phylo <- function(tree, ...) { |
35 | 35 |
idx <- idx[-1] |
36 | 36 |
} |
37 | 37 |
} |
38 |
- |
|
38 |
+ |
|
39 | 39 |
tree$Nnode <- tree$Nnode+ii |
40 | 40 |
tree$edge.length <- c(tree$edge.length, rep(0, ii)) |
41 | 41 |
return(tree) |
... | ... |
@@ -44,23 +44,23 @@ as.binary.phylo <- function(tree, ...) { |
44 | 44 |
|
45 | 45 |
##' remove singleton |
46 | 46 |
##' |
47 |
-##' |
|
47 |
+##' |
|
48 | 48 |
##' @title rm.singleton.newick |
49 | 49 |
##' @param nwk newick file |
50 |
-##' @param outfile output newick file |
|
50 |
+##' @param outfile output newick file |
|
51 | 51 |
##' @return tree text |
52 | 52 |
##' @importFrom magrittr %<>% |
53 | 53 |
##' @importFrom magrittr add |
54 | 54 |
##' @importFrom ape write.tree |
55 | 55 |
##' @author Guangchuang Yu \url{http://ygc.name} |
56 |
-rm.singleton.newick <- function(nwk, outfile = NULL) { |
|
56 |
+rm.singleton.newick <- function(nwk, outfile = NULL) { |
|
57 | 57 |
tree <- readLines(nwk) |
58 | 58 |
|
59 | 59 |
## remove singleton of tips |
60 | 60 |
nodePattern <- "\\w+:[\\.0-9Ee\\+\\-]+" |
61 | 61 |
singletonPattern.with.nodename <- paste0(".*(\\(", nodePattern, "\\)\\w+:[\\.0-9Ee\\+\\-]+).*") |
62 | 62 |
singletonPattern.wo.nodename <- paste0(".*(\\(", nodePattern, "\\):[\\.0-9Ee\\+\\-]+).*") |
63 |
- |
|
63 |
+ |
|
64 | 64 |
while(length(grep("\\([^,]+\\)", tree)) > 0) { |
65 | 65 |
singleton <- gsub(singletonPattern.with.nodename, "\\1", tree) |
66 | 66 |
if (singleton == tree) { |
... | ... |
@@ -71,11 +71,11 @@ rm.singleton.newick <- function(nwk, outfile = NULL) { |
71 | 71 |
} |
72 | 72 |
|
73 | 73 |
tip <- gsub("\\((\\w+).*", "\\1", singleton) |
74 |
- |
|
74 |
+ |
|
75 | 75 |
len1 <- gsub(".*[^\\.0-9Ee\\+\\-]+([\\.0-9Ee\\+\\-]+)", "\\1", singleton) |
76 | 76 |
len2 <- gsub(".*:([\\.0-9Ee\\+\\-]+)\\).*", "\\1", singleton) |
77 | 77 |
len <- as.numeric(len1) + as.numeric(len2) |
78 |
- |
|
78 |
+ |
|
79 | 79 |
tree <- gsub(singleton, paste0(tip, ":", len), tree, fixed = TRUE) |
80 | 80 |
} |
81 | 81 |
|
... | ... |
@@ -95,7 +95,7 @@ rm.singleton.newick <- function(nwk, outfile = NULL) { |
95 | 95 |
tree$edge.length[sidx] %<>% add(., tree$edge.length[idx]) |
96 | 96 |
tree$edge.length <- tree$edge.length[-idx] |
97 | 97 |
} |
98 |
- |
|
98 |
+ |
|
99 | 99 |
if (!is.null(outfile)) { |
100 | 100 |
write.tree(tree, file=outfile) |
101 | 101 |
} |
... | ... |
@@ -117,12 +117,12 @@ fortify.beast <- function(model, data, |
117 | 117 |
|
118 | 118 |
df <- fortify(phylo, layout=layout, branch.length=branch.length, |
119 | 119 |
ladderize=ladderize, right=right, mrsd = mrsd, ...) |
120 |
- |
|
120 |
+ |
|
121 | 121 |
stats <- model@stats |
122 | 122 |
|
123 | 123 |
scn <- colnames(stats) |
124 | 124 |
scn <- scn[scn != 'node'] |
125 |
- |
|
125 |
+ |
|
126 | 126 |
for (cn in scn) { |
127 | 127 |
if (cn %in% colnames(df)) { |
128 | 128 |
colnames(stats)[colnames(stats) == cn] <- paste0(cn, "_") |
... | ... |
@@ -151,7 +151,7 @@ fortify.beast <- function(model, data, |
151 | 151 |
} |
152 | 152 |
next |
153 | 153 |
} |
154 |
- |
|
154 |
+ |
|
155 | 155 |
len <- sapply(stats[,ii], length) |
156 | 156 |
if ( all(len == 1) ) { |
157 | 157 |
stats[, ii] %<>% unlist %>% as.character %>% as.numeric |
... | ... |
@@ -181,31 +181,31 @@ fortify.beast <- function(model, data, |
181 | 181 |
} else { |
182 | 182 |
return(paste0('{', paste0(y, collapse = ','), '}')) |
183 | 183 |
} |
184 |
- }) |
|
184 |
+ }) |
|
185 | 185 |
} |
186 | 186 |
} |
187 |
- |
|
188 |
- |
|
187 |
+ |
|
188 |
+ |
|
189 | 189 |
cn <- colnames(stats) |
190 | 190 |
lo <- cn[grep("_lower", cn)] |
191 | 191 |
hi <- gsub("lower$", "upper", lo) |
192 | 192 |
rid <- gsub("_lower$", "", lo) |
193 |
- |
|
193 |
+ |
|
194 | 194 |
for (i in seq_along(rid)) { |
195 | 195 |
stats[, rid[i]] <- paste0("[", stats[, lo[i]], ",", stats[, hi[i]], "]") |
196 | 196 |
stats[is.na(stats[, lo[i]]), rid[i]] <- NA |
197 | 197 |
} |
198 |
- |
|
198 |
+ |
|
199 | 199 |
idx <- match(df$node, stats$node) |
200 | 200 |
stats <- stats[idx,] |
201 | 201 |
cn_stats <- colnames(stats) |
202 | 202 |
stats <- stats[, cn_stats != "node"] |
203 |
- |
|
203 |
+ |
|
204 | 204 |
df <- cbind(df, stats) |
205 | 205 |
if (is(stats, "data.frame") == FALSE) { |
206 | 206 |
colnames(df)[colnames(df) == "stats"] <- cn_stats[cn_stats != "node"] |
207 | 207 |
} |
208 |
- |
|
208 |
+ |
|
209 | 209 |
df <- scaleY(phylo, df, yscale, layout, ...) |
210 | 210 |
|
211 | 211 |
append_extraInfo(df, model) |
... | ... |
@@ -235,7 +235,7 @@ fortify.codeml <- function(model, data, |
235 | 235 |
"rst.branch.length", |
236 | 236 |
colnames(dNdS)[-c(1,2)]) |
237 | 237 |
) |
238 |
- |
|
238 |
+ |
|
239 | 239 |
if (length == "rst.branch.length") { |
240 | 240 |
phylo <- get.tree(model@rst) |
241 | 241 |
} else { |
... | ... |
@@ -244,14 +244,14 @@ fortify.codeml <- function(model, data, |
244 | 244 |
} |
245 | 245 |
phylo <- set_branch_length(model@mlc, length) |
246 | 246 |
} |
247 |
- |
|
247 |
+ |
|
248 | 248 |
df <- fortify(phylo, data, layout, ladderize, right, |
249 | 249 |
branch.length=length, mrsd=mrsd, ...) |
250 |
- |
|
250 |
+ |
|
251 | 251 |
res <- merge_phylo_anno.codeml_mlc(df, dNdS, ndigits) |
252 | 252 |
df <- merge_phylo_anno.paml_rst(res, model@rst) |
253 | 253 |
df <- scaleY(phylo, df, yscale, layout, ...) |
254 |
- |
|
254 |
+ |
|
255 | 255 |
append_extraInfo(df, model) |
256 | 256 |
} |
257 | 257 |
|
... | ... |
@@ -269,10 +269,10 @@ fortify.codeml_mlc <- function(model, data, |
269 | 269 |
...) { |
270 | 270 |
|
271 | 271 |
phylo <- set_branch_length(model, branch.length) |
272 |
- |
|
272 |
+ |
|
273 | 273 |
df <- fortify(phylo, data, layout, ladderize, right, |
274 | 274 |
branch.length=branch.length, mrsd=mrsd, ...) |
275 |
- |
|
275 |
+ |
|
276 | 276 |
dNdS <- model@dNdS |
277 | 277 |
|
278 | 278 |
df <- merge_phylo_anno.codeml_mlc(df, dNdS, ndigits) |
... | ... |
@@ -290,12 +290,12 @@ merge_phylo_anno.codeml_mlc <- function(df, dNdS, ndigits = NULL) { |
290 | 290 |
} |
291 | 291 |
} |
292 | 292 |
} |
293 |
- |
|
293 |
+ |
|
294 | 294 |
res <- merge(df, dNdS, |
295 | 295 |
by.x = c("node", "parent"), |
296 | 296 |
by.y = c("node", "parent"), |
297 | 297 |
all.x = TRUE) |
298 |
- |
|
298 |
+ |
|
299 | 299 |
res[match(df$node, res$node),] |
300 | 300 |
} |
301 | 301 |
|
... | ... |
@@ -309,7 +309,7 @@ fortify.codeml_mlc_ <- function(model, data, |
309 | 309 |
} |
310 | 310 |
|
311 | 311 |
|
312 |
- |
|
312 |
+ |
|
313 | 313 |
##' @method fortify paml_rst |
314 | 314 |
##' @export |
315 | 315 |
fortify.paml_rst <- function(model, data, layout = "rectangular", yscale="none", |
... | ... |
@@ -354,13 +354,13 @@ fortify.jplace <- function(model, data, |
354 | 354 |
|
355 | 355 |
df <- scaleY(model@phylo, df, yscale, layout, ...) |
356 | 356 |
|
357 |
- append_extraInfo(df, model) |
|
357 |
+ append_extraInfo(df, model) |
|
358 | 358 |
} |
359 | 359 |
|
360 | 360 |
scaleY <- function(phylo, df, yscale, layout, ...) { |
361 | 361 |
if (yscale == "none") { |
362 | 362 |
return(df) |
363 |
- } |
|
363 |
+ } |
|
364 | 364 |
if (! yscale %in% colnames(df)) { |
365 | 365 |
warning("yscale is not available...\n") |
366 | 366 |
return(df) |
... | ... |
@@ -375,7 +375,7 @@ scaleY <- function(phylo, df, yscale, layout, ...) { |
375 | 375 |
} else { |
376 | 376 |
y <- getYcoord_scale_category(phylo, df, yscale, ...) |
377 | 377 |
} |
378 |
- |
|
378 |
+ |
|
379 | 379 |
df[, "y"] <- y |
380 | 380 |
|
381 | 381 |
return(df) |
... | ... |
@@ -396,9 +396,10 @@ fortify.phylo4 <- function(model, data, layout="rectangular", yscale="none", |
396 | 396 |
##' @export |
397 | 397 |
fortify.phylo4d <- function(model, data, layout="rectangular", yscale="none", |
398 | 398 |
ladderize=TRUE, right=FALSE, mrsd=NULL, ...) { |
399 |
- res <- fortify.phylo4(model, data, layout, yscale, ladderize, right, mrsd, ...) |
|
399 |
+ res <- fortify.phylo4(model, data, layout, yscale="none", ladderize, right, mrsd, ...) # not apply yscale at this moment |
|
400 | 400 |
tdata <- model@data[match(res$node, rownames(model@data)), , drop=FALSE] |
401 |
- cbind(res, tdata) |
|
401 |
+ df <- cbind(res, tdata) |
|
402 |
+ scaleY(as.phylo.phylo4(model), df, yscale, layout, ...) |
|
402 | 403 |
} |
403 | 404 |
|
404 | 405 |
as.phylo.phylo4 <- function(phylo4) { |
... | ... |
@@ -411,7 +412,7 @@ as.phylo.phylo4 <- function(phylo4) { |
411 | 412 |
phylo <- list(edge = edge, |
412 | 413 |
edge.length = edge.length, |
413 | 414 |
tip.label = tip.label) |
414 |
- |
|
415 |
+ |
|
415 | 416 |
node.id <- sort(unique(edge[,1])) |
416 | 417 |
node.id <- node.id[node.id != 0] |
417 | 418 |
node.label <- phylo4@label[node.id] |
... | ... |
@@ -425,7 +426,7 @@ as.phylo.phylo4 <- function(phylo4) { |
425 | 426 |
|
426 | 427 |
##' fortify a phylo to data.frame |
427 | 428 |
##' |
428 |
-##' |
|
429 |
+##' |
|
429 | 430 |
##' @rdname fortify |
430 | 431 |
##' @title fortify |
431 | 432 |
##' @param model phylo object |
... | ... |
@@ -442,7 +443,7 @@ as.phylo.phylo4 <- function(phylo4) { |
442 | 443 |
##' @method fortify phylo |
443 | 444 |
##' @export |
444 | 445 |
##' @author Yu Guangchuang |
445 |
-fortify.phylo <- function(model, data, layout="rectangular", |
|
446 |
+fortify.phylo <- function(model, data, layout="rectangular", |
|
446 | 447 |
ladderize=TRUE, right=FALSE, mrsd=NULL, as.Date=FALSE, ...) { |
447 | 448 |
if (ladderize == TRUE) { |
448 | 449 |
tree <- ladderize(model, right=right) |
... | ... |
@@ -456,7 +457,7 @@ fortify.phylo <- function(model, data, layout="rectangular", |
456 | 457 |
tree$edge.length <- NULL |
457 | 458 |
} |
458 | 459 |
} |
459 |
- |
|
460 |
+ |
|
460 | 461 |
df <- as.data.frame(tree, layout=layout, ...) |
461 | 462 |
idx <- is.na(df$parent) |
462 | 463 |
df$parent[idx] <- df$node[idx] |
... | ... |
@@ -477,7 +478,7 @@ fortify.phylo <- function(model, data, layout="rectangular", |
477 | 478 |
} |
478 | 479 |
} |
479 | 480 |
} |
480 |
- |
|
481 |
+ |
|
481 | 482 |
if (!is.null(mrsd)) { |
482 | 483 |
df <- scaleX_by_time_from_mrsd(df, mrsd, as.Date) |
483 | 484 |
} |
... | ... |
@@ -486,7 +487,7 @@ fortify.phylo <- function(model, data, layout="rectangular", |
486 | 487 |
|
487 | 488 |
##' convert phylo to data.frame |
488 | 489 |
##' |
489 |
-##' |
|
490 |
+##' |
|
490 | 491 |
##' @title as.data.frame |
491 | 492 |
##' @param x phylo object |
492 | 493 |
##' @param row.names omitted here |
... | ... |
@@ -501,7 +502,7 @@ as.data.frame.phylo <- function(x, row.names, optional, |
501 | 502 |
layout="rectangular", ...) { |
502 | 503 |
if (layout == "unrooted") { |
503 | 504 |
return(layout.unrooted(x)) |
504 |
- } |
|
505 |
+ } |
|
505 | 506 |
as.data.frame.phylo_(x, layout, ...) |
506 | 507 |
} |
507 | 508 |
|
... | ... |
@@ -510,14 +511,14 @@ as.data.frame.phylo_ <- function(x, layout="rectangular", |
510 | 511 |
if (branch.length != 'none') { |
511 | 512 |
branch.length = "branch.length" |
512 | 513 |
} |
513 |
- |
|
514 |
+ |
|
514 | 515 |
tip.label <- x[["tip.label"]] |
515 | 516 |
Ntip <- length(tip.label) |
516 | 517 |
N <- getNodeNum(x) |
517 |
- |
|
518 |
+ |
|
518 | 519 |
edge <- as.data.frame(x[["edge"]]) |
519 | 520 |
colnames(edge) <- c("parent", "node") |
520 |
- |
|
521 |
+ |
|
521 | 522 |
if (! is.null(x$edge.length)) { |
522 | 523 |
edge$length <- x$edge.length |
523 | 524 |
if (branch.length == "none") { |
... | ... |
@@ -540,7 +541,7 @@ as.data.frame.phylo_ <- function(x, layout="rectangular", |
540 | 541 |
xpos <- getXcoord_no_length(x) |
541 | 542 |
ypos <- getYcoord(x) |
542 | 543 |
} |
543 |
- |
|
544 |
+ |
|
544 | 545 |
xypos <- data.frame(node=1:N, x=xpos, y=ypos) |
545 | 546 |
|
546 | 547 |
res <- merge(edge, xypos, by.x="node", by.y="node", all.y=TRUE) |
... | ... |
@@ -588,7 +589,7 @@ fortify.apeBootstrap <- fortify.raxml |
588 | 589 |
|
589 | 590 |
##' @method fortify multiPhylo |
590 | 591 |
##' @export |
591 |
-fortify.multiPhylo <- function(model, data, layout="rectangular", |
|
592 |
+fortify.multiPhylo <- function(model, data, layout="rectangular", |
|
592 | 593 |
ladderize=TRUE, right=FALSE, mrsd=NULL, ...) { |
593 | 594 |
|
594 | 595 |
df.list <- lapply(model, function(x) fortify(x, layout=layout, ladderize=ladderize, right=right, mrsd=mrsd, ...)) |
... | ... |
@@ -600,9 +601,9 @@ fortify.multiPhylo <- function(model, data, layout="rectangular", |
600 | 601 |
df <- do.call("rbind", df.list) |
601 | 602 |
df$.id <- rep(names(df.list), times=sapply(df.list, nrow)) |
602 | 603 |
df$.id <- factor(df$.id, levels=names(df.list)) |
603 |
- |
|
604 |
+ |
|
604 | 605 |
## nNode <- sapply(df.list, nrow) |
605 |
- ## nNode2 <- cumsum(c(0, nNode[-length(nNode)])) |
|
606 |
+ ## nNode2 <- cumsum(c(0, nNode[-length(nNode)])) |
|
606 | 607 |
## df$parent <- df$parent + rep(nNode2, times=nNode) |
607 | 608 |
return(df) |
608 | 609 |
} |
... | ... |
@@ -615,7 +616,7 @@ fortify.phylip <- function(model, data, layout="rectangular", |
615 | 616 |
trees <- get.tree(model) |
616 | 617 |
fortify(trees, layout=layout, ladderize = ladderize, right=right, mrsd=mrsd, ...) |
617 | 618 |
} |
618 |
- |
|
619 |
+ |
|
619 | 620 |
##' @method fortify r8s |
620 | 621 |
##' @export |
621 | 622 |
fortify.r8s <- function(model, data, layout="rectangular", |
... | ... |
@@ -659,7 +660,7 @@ fortify.phyloseq <- function(model, data, layout="rectangular", |
659 | 660 |
if ('Abundance' %in% colnames(dd)) { |
660 | 661 |
dd <- dd[dd$Abundance > 0, ] |
661 | 662 |
} |
662 |
- |
|
663 |
+ |
|
663 | 664 |
data <- merge(df, dd, by.x="label", by.y="OTU", all.x=TRUE) |
664 | 665 |
spacing <- 0.02 |
665 | 666 |
idx <- with(data, sapply(table(node)[unique(node)], function(i) 1:i)) %>% unlist |
... | ... |
@@ -669,7 +670,7 @@ fortify.phyloseq <- function(model, data, layout="rectangular", |
669 | 670 |
data[order(data$node, decreasing = FALSE), ] |
670 | 671 |
} |
671 | 672 |
|
672 |
- |
|
673 |
+ |
|
673 | 674 |
## fortify.cophylo <- function(model, data, layout="rectangular", |
674 | 675 |
## ladderize=TRUE, right=FALSE, mrsd = NULL, ...) { |
675 | 676 |
## trees <- model$trees |
... | ... |
@@ -2,9 +2,9 @@ |
2 | 2 |
ggtree: an R package for visualization and annotation of phylogenetic trees with their covariates and other associated data |
3 | 3 |
=========================================================================================================================== |
4 | 4 |
|
5 |
-[](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) <img src="logo.png" align="right" /> |
|
5 |
+[](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) <img src="logo.png" align="right" /> |
|
6 | 6 |
|
7 |
-[](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) |
|
7 |
+[](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) |
|
8 | 8 |
|
9 | 9 |
[](https://www.bioconductor.org/packages/devel/bioc/html/ggtree.html#archives) [](https://bioconductor.org/checkResults/devel/bioc-LATEST/ggtree/) [](https://travis-ci.org/GuangchuangYu/ggtree) [](https://ci.appveyor.com/project/GuangchuangYu/ggtree) [](http://bioconda.github.io/recipes/bioconductor-ggtree/README.html) |
10 | 10 |
|
... | ... |
@@ -18,7 +18,7 @@ Please cite the following article when using `ggtree`: |
18 | 18 |
|
19 | 19 |
**G Yu**, DK Smith, H Zhu, Y Guan, TTY Lam<sup>\*</sup>. ggtree: an R package for visualization and annotation of phylogenetic trees with their covariates and other associated data. ***Methods in Ecology and Evolution***. *accepted* |
20 | 20 |
|
21 |
-[](http://dx.doi.org/10.1111/2041-210X.12628) [](https://scholar.google.com.hk/scholar?oi=bibs&hl=en&cites=7268358477862164627) [](https://www.altmetric.com/details/10533079) |
|
21 |
+[](http://dx.doi.org/10.1111/2041-210X.12628) [](https://scholar.google.com.hk/scholar?oi=bibs&hl=en&cites=7268358477862164627) [](https://www.altmetric.com/details/10533079) |
|
22 | 22 |
|
23 | 23 |
------------------------------------------------------------------------ |
24 | 24 |
|
... | ... |
@@ -51,7 +51,7 @@ For details, please visit our project website, <https://guangchuangyu.github.io/ |
51 | 51 |
|
52 | 52 |
### Download stats |
53 | 53 |
|
54 |
-[](https://bioconductor.org/packages/stats/bioc/ggtree) [](https://bioconductor.org/packages/stats/bioc/ggtree) [](https://bioconductor.org/packages/stats/bioc/ggtree) |
|
54 |
+[](https://bioconductor.org/packages/stats/bioc/ggtree) [](https://bioconductor.org/packages/stats/bioc/ggtree) [](https://bioconductor.org/packages/stats/bioc/ggtree) |
|
55 | 55 |
|
56 | 56 |
+------------------------+-----------------------+-----------------------+--------------------+ |
57 | 57 |
| * | |