From 96cc11e5339a42eba89f5969551de00380aa0b3d Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Thu, 26 Sep 2024 18:24:13 -0700 Subject: [PATCH 01/14] Function to create scale bar --- R/scale.bar.R | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 R/scale.bar.R diff --git a/R/scale.bar.R b/R/scale.bar.R new file mode 100644 index 00000000..49075992 --- /dev/null +++ b/R/scale.bar.R @@ -0,0 +1,68 @@ +create.scale.bar <- function( + main, + visual.length, + scale.length, + left.x, + top.y, + edge.col, + edge.width, + edge.type + ) { + + if (is.numeric(edge.width)) { + edge.width <- unit(edge.width, "points"); + } + + title.fontsize = unit(14, "points"); + title <- textGrob( + label = main, + x = left.x + (visual.length / 2), + y = top.y, + hjust = 0.5, + vjust = 1, + gp = gpar( + fontsize = title.fontsize + ) + ); + + scale.bar.y <- convertY(top.y - (title.fontsize * 2), "npc"); + scale.line <- segmentsGrob( + x0 = left.x, + x1 = left.x + visual.length, + y0 = scale.bar.y, + y1 = scale.bar.y, + gp = gpar( + col = edge.col, + lwd = edge.width, + lineend = "butt" + ) + ); + + tick.label.fontsize = unit(12, "points"); + tick.length <- edge.width + (tick.label.fontsize / 4); + ticks <- segmentsGrob( + x0 = c(left.x, left.x + visual.length), + x1 = c(left.x, left.x + visual.length), + y0 = scale.bar.y + (edge.width / 2.5), + y1 = scale.bar.y - tick.length, + gp = gpar( + lineend = "butt" + ) + ); + + tick.labels <- textGrob( + label = c(0, scale.length), + x = c(left.x, left.x + visual.length), + y = scale.bar.y - tick.length - tick.label.fontsize, + gp = gpar( + fontsize = tick.label.fontsize + ) + ); + + return(gList( + title, + scale.line, + ticks, + tick.labels + )); + } \ No newline at end of file From e5b76b0536d6336424885fa163298ff77ead2bc1 Mon Sep 17 00:00:00 2001 From: whelena Date: Fri, 27 Sep 2024 17:29:03 -0700 Subject: [PATCH 02/14] save before cleaning up --- R/SRCGrob.R | 12 +- R/make.clone.tree.grobs.R | 269 ++++++++++++++++++++------------------ R/scale.bar.R | 139 ++++++++++++++++---- 3 files changed, 269 insertions(+), 151 deletions(-) diff --git a/R/SRCGrob.R b/R/SRCGrob.R index 832f127b..2838f84b 100644 --- a/R/SRCGrob.R +++ b/R/SRCGrob.R @@ -26,7 +26,11 @@ SRCGrob <- function( label.nodes = TRUE, disable.polygons = FALSE, length.from.node.edge = TRUE, - size.units = 'npc' + size.units = 'npc', + scale.bar = FALSE, + scale.bar.coords = c(0.1, 0.9) + # scale.bar.padding = 0.5, + # scale.bar.label.padding = 0.5 ) { add.node.text <- !is.null(node.text); @@ -107,7 +111,11 @@ SRCGrob <- function( main = main, main.cex = main.cex, main.y = main.y, - size.units = size.units + size.units = size.units, + scale.bar = scale.bar, + scale.bar.coords = scale.bar.coords + # scale.bar.padding = scale.bar.padding, + # scale.bar.label.padding = scale.bar.label.padding ); out.tree <- gTree( diff --git a/R/make.clone.tree.grobs.R b/R/make.clone.tree.grobs.R index 0ccee07d..5a0079c9 100644 --- a/R/make.clone.tree.grobs.R +++ b/R/make.clone.tree.grobs.R @@ -37,42 +37,44 @@ make.clone.tree.grobs <- function( main.cex, main.y, size.units, + scale.bar, + scale.bar.coords, ... ) { - #initializing dataframe for subclones - if ('excluded' %in% colnames(ccf.df)) { - v <- ccf.df[!ccf.df$excluded,]; - } else { - v <- ccf.df; - v$excluded <- FALSE; - } - - v <- v[order(v$id), ]; - no.ccf <- FALSE; - - if (!('ccf' %in% colnames(ccf.df)) || all(is.na(ccf.df$ccf)) || add.polygons == FALSE) { - v$vaf <- NULL; - v$vaf[v$parent == -1] <- 1; - no.ccf <- TRUE; - } else { - v <- v[order(v$id),] - v$vaf[!v$excluded] <- v$ccf[!v$excluded] / max(v$ccf[!v$excluded]); - } - - if (all(is.null(ccf.df$colour))) { - v$colour <- node.col - } + #initializing dataframe for subclones + if ('excluded' %in% colnames(ccf.df)) { + v <- ccf.df[!ccf.df$excluded,]; + } else { + v <- ccf.df; + v$excluded <- FALSE; + } + + v <- v[order(v$id), ]; + no.ccf <- FALSE; + + if (!('ccf' %in% colnames(ccf.df)) || all(is.na(ccf.df$ccf)) || add.polygons == FALSE) { + v$vaf <- NULL; + v$vaf[v$parent == -1] <- 1; + no.ccf <- TRUE; + } else { + v <- v[order(v$id),] + v$vaf[!v$excluded] <- v$ccf[!v$excluded] / max(v$ccf[!v$excluded]); + } + + if (all(is.null(ccf.df$colour))) { + v$colour <- node.col + } extra.len <- if (no.ccf) node.radius else node.radius * 4; - v$x <- v$y <- v$len <- v$x.mid <- numeric(length(nrow(v))); - v <- v[order(v$tier, v$parent), ]; + v$x <- v$y <- v$len <- v$x.mid <- numeric(length(nrow(v))); + v <- v[order(v$tier, v$parent), ]; - #initializing line segment dataframe and adjusting lengths to accomodate the node circles - tree$angle <- numeric(length = nrow(tree)); - tree$angle[tree$parent == -1] <- 0; - if ('length2' %in% colnames(tree)) { + #initializing line segment dataframe and adjusting lengths to accomodate the node circles + tree$angle <- numeric(length = nrow(tree)); + tree$angle[tree$parent == -1] <- 0; + if ('length2' %in% colnames(tree)) { tree$length2.c <- tree$length2 / scale1 * scale2; tree$length <- apply( @@ -82,103 +84,120 @@ make.clone.tree.grobs <- function( max(x[c(3, 6)]); } ); - } else { - tree$length <- tree$length1; - } - - if (length.from.node.edge == TRUE) { - tree <- adjust.branch.lengths(v, tree, node.radius, scale1); - } - - extra.len <- extra.len * (1 / scale1); - - clone.out <- make.clone.polygons( - v, - tree, - wid, - scale1, - scale2, - extra.len, - node.col, - spread = spread, - sig.shape = sig.shape, - fixed.angle = fixed.angle, - add.polygons = add.polygons, - no.ccf = no.ccf - ); - - clone.out$no.ccf <- no.ccf; - plot.size <- calculate.main.plot.size( - clone.out, - scale1, - wid, - min.width, - node.radius - ); - - if (!no.ccf) { - get.CP.polygons(clone.out); - } - - add.tree.segs(clone.out, node.radius, default.branch.width, scale1, seg1.col, seg2.col); - - if (!is.null(cluster.list)) { - message(paste( - 'Clustered pie nodes will be supported in a future version.', - 'Plain nodes will be used.' - )); - # TODO Implement pie nodes - # add.pie.nodes(clone.out, node.radius, cluster.list); - } + } else { + tree$length <- tree$length1; + } + + if (length.from.node.edge == TRUE) { + tree <- adjust.branch.lengths(v, tree, node.radius, scale1); + } + + extra.len <- extra.len * (1 / scale1); + + clone.out <- make.clone.polygons( + v, + tree, + wid, + scale1, + scale2, + extra.len, + node.col, + spread = spread, + sig.shape = sig.shape, + fixed.angle = fixed.angle, + add.polygons = add.polygons, + no.ccf = no.ccf + ); + + clone.out$no.ccf <- no.ccf; + plot.size <- calculate.main.plot.size( + clone.out, + scale1, + wid, + min.width, + node.radius + ); + + if (!no.ccf) { + get.CP.polygons(clone.out); + } + + add.tree.segs(clone.out, node.radius, default.branch.width, scale1, seg1.col, seg2.col); + + if (!is.null(cluster.list)) { + message(paste( + 'Clustered pie nodes will be supported in a future version.', + 'Plain nodes will be used.' + )); + # TODO Implement pie nodes + # add.pie.nodes(clone.out, node.radius, cluster.list); + } add.node.ellipse(clone.out,node.radius, label.nodes, label.cex, scale1); - if (add.normal == TRUE) { - add.normal(clone.out,node.radius,label.cex, normal.cex) - } - - if (yaxis.position != 'none') { - add.axes( - clone.out, - yaxis.position, - scale1 = scale1, - scale2 = scale2, - yat = yat, - axis.label.cex = axis.label.cex, - axis.cex = axis.cex, - no.ccf = no.ccf, - xaxis.label = xaxis.label, - yaxis1.label = yaxis1.label, - yaxis2.label = yaxis2.label - ); - } - - if (add.node.text == TRUE & !is.null(text.df)) { - node.text.grobs <- add.text2( - clone.out$tree, - text.df, - label.nodes = text.on.nodes, - line.dist = node.text.line.dist, - main.y = clone.out$height, - panel.height = clone.out$height, - panel.width = clone.out$width, - xlims = clone.out$xlims, - ymax = clone.out$ymax, - cex = node.text.cex, - v = clone.out$v, - axis.type = yaxis.position, - node.radius = node.radius, - scale = scale1, - clone.out = clone.out, - alternating = FALSE - ); - - clone.out$grobs <- c(clone.out$grobs, list(node.text.grobs)); - } - - if (!is.null(main)) { - add.main(clone.out, main, main.cex, main.y, size.units); - } - - return(clone.out); + if (add.normal == TRUE) { + add.normal(clone.out,node.radius,label.cex, normal.cex) + } + + if (yaxis.position != 'none' & scale.bar == FALSE) { + add.axes( + clone.out, + yaxis.position, + scale1 = scale1, + scale2 = scale2, + yat = yat, + axis.label.cex = axis.label.cex, + axis.cex = axis.cex, + no.ccf = no.ccf, + xaxis.label = xaxis.label, + yaxis1.label = yaxis1.label, + yaxis2.label = yaxis2.label + ); + } + + if (scale.bar) { + add.scale.bar( + clone.out, + scale1, + scale2, + yaxis1.label = yaxis1.label, + yaxis2.label = yaxis2.label, + scale.length = c( + median(tree$length1[tree$length1 > 0], na.rm = TRUE), + median(tree$length2[tree$length2 > 0], na.rm = TRUE) + ), + main.cex = axis.label.cex$y, + label.cex = axis.cex$y, + pos = scale.bar.coords + ); + } + + if (add.node.text == TRUE & !is.null(text.df)) { + node.text.grobs <- add.text2( + clone.out$tree, + text.df, + label.nodes = text.on.nodes, + line.dist = node.text.line.dist, + main.y = clone.out$height, + panel.height = clone.out$height, + panel.width = clone.out$width, + xlims = clone.out$xlims, + ymax = clone.out$ymax, + cex = node.text.cex, + v = clone.out$v, + axis.type = yaxis.position, + node.radius = node.radius, + scale = scale1, + clone.out = clone.out, + alternating = FALSE + ); + + clone.out$grobs <- c(clone.out$grobs, list(node.text.grobs)); + } + + if (!is.null(main)) { + add.main(clone.out, main, main.cex, main.y, size.units); + } + + return(clone.out); } diff --git a/R/scale.bar.R b/R/scale.bar.R index 49075992..be3ffbd1 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -1,3 +1,79 @@ +add.scale.bar <- function( + clone.out, + scale.length, + scale1, + scale2, + yaxis1.label, + yaxis2.label, + pos, + ... + ) { + + # Necessary to make sure scale.length corresponds to tree + vp.unclipped <- make.plot.viewport(clone.out, clip = 'off'); + # Generate the first scale bar + scale.bar1.glist <- create.scale.bar( + main = yaxis1.label, + visual.length = 0.5, + scale.length = get.scale.bar.length(scale.length[1]), + edge.col = most.common.value(clone.out$v$edge.colour.1), + edge.width = most.common.value(clone.out$v$edge.width.1), + edge.type = most.common.value(clone.out$v$edge.type.1), + left.x = pos[1], + top.y = pos[2], + ... + ); + clone.out$grobs <- c(clone.out$grobs, scale.bar1.glist); + # clone.out$grobs <- c(clone.out$grobs, list( + # gTree( + # children = scale.bar1.glist, + # vp = vp.unclipped + # ) + # )); + + # Create second scalebar if specified + if (!is.null(yaxis2.label)) { + scale.bar2.glist <- create.scale.bar( + main = yaxis2.label, + visual.length = 0.5, + scale.length = get.scale.bar.length(scale.length[2], scale1 / scale2), + edge.col = most.common.value(clone.out$v$edge.colour.2), + edge.width = most.common.value(clone.out$v$edge.width.2), + edge.type = most.common.value(clone.out$v$edge.type.2), + left.x = pos[1], + top.y = pos[2] + 0.1, + ... + ); + clone.out$grobs <- c(clone.out$grobs, scale.bar2.glist); + # clone.out$grobs <- c(clone.out$grobs, list( + # gTree( + # children = scale.bar2.glist + # vp = vp.unclipped + # ) + # )); + } + } + +get.scale.bar.length <- function( + scale.length, + conversion.factor = 1 + ) { + + adjusted.length <- 10 ** floor(log10(as.numeric(scale.length))); + return(list( + label = adjusted.length, + length = adjusted.length / conversion.factor + )); + } + +most.common.value <- function(x) { + if (is.null(x)) { + return(NULL); + } + n.table <- table(x); + return(names(n.table)[which.max(n.table)]); + } + create.scale.bar <- function( main, visual.length, @@ -6,59 +82,74 @@ create.scale.bar <- function( top.y, edge.col, edge.width, - edge.type - ) { - - if (is.numeric(edge.width)) { - edge.width <- unit(edge.width, "points"); - } + edge.type, + main.cex, + label.cex + ) { - title.fontsize = unit(14, "points"); + # do unit stuff internally + print('ran title'); + edge.width <- unit(edge.width, "points"); + # xat <- unit(left.x, "npc") + c(0, convertUnit(scale.length$length, 'npc', valueOnly = TRUE)); + # visual.length <- convertUnit(scale.length$length, 'npc'); + visual.length <- unit(scale.length$length, 'native'); + # visual.length <- unit(as.numeric(visual.length), "npc"); + left.x <- unit(left.x - 1, "npc"); + top.y <- unit(top.y, "npc"); + xat <- left.x + unit(c(0, scale.length$length), 'native'); + # main.cex <- unit(14, "points"); title <- textGrob( label = main, - x = left.x + (visual.length / 2), + x = xat[1], y = top.y, hjust = 0.5, vjust = 1, gp = gpar( - fontsize = title.fontsize + cex = main.cex ) ); - - scale.bar.y <- convertY(top.y - (title.fontsize * 2), "npc"); + print('ran title'); + # scale.bar.y <- convertY(top.y - (main.cex * 2), "npc"); + scale.bar.y <- top.y - unit(0.05, 'npc'); scale.line <- segmentsGrob( - x0 = left.x, - x1 = left.x + visual.length, + x0 = xat[1], + # x1 = left.x + visual.length, + x1 = xat[2], y0 = scale.bar.y, y1 = scale.bar.y, gp = gpar( col = edge.col, lwd = edge.width, + lty = edge.type, lineend = "butt" ) ); - - tick.label.fontsize = unit(12, "points"); - tick.length <- edge.width + (tick.label.fontsize / 4); + print('ran scale.line'); + # label.cex = unit(12, "points"); + tick.length <- edge.width + unit(label.cex / 100, 'npc'); ticks <- segmentsGrob( - x0 = c(left.x, left.x + visual.length), - x1 = c(left.x, left.x + visual.length), + # x0 = c(left.x, left.x + visual.length), + # x1 = c(left.x, left.x + visual.length), + x0 = xat, + x1 = xat, y0 = scale.bar.y + (edge.width / 2.5), y1 = scale.bar.y - tick.length, + default.units = 'native', gp = gpar( lineend = "butt" ) ); - + print('ran tick.length'); tick.labels <- textGrob( - label = c(0, scale.length), - x = c(left.x, left.x + visual.length), - y = scale.bar.y - tick.length - tick.label.fontsize, + label = c(0, scale.length$label), + # x = c(left.x, left.x + visual.length), + x = xat, + y = scale.bar.y - tick.length * 2, gp = gpar( - fontsize = tick.label.fontsize + cex = label.cex ) ); - + print('ran tick.labels'); return(gList( title, scale.line, From 3da6a484d9896da82b35f09dfb53e05f1310b2d3 Mon Sep 17 00:00:00 2001 From: whelena Date: Fri, 27 Sep 2024 17:46:21 -0700 Subject: [PATCH 03/14] cleaned up version --- R/scale.bar.R | 41 ++++++----------------------------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/R/scale.bar.R b/R/scale.bar.R index be3ffbd1..dc3853a0 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -9,12 +9,9 @@ add.scale.bar <- function( ... ) { - # Necessary to make sure scale.length corresponds to tree - vp.unclipped <- make.plot.viewport(clone.out, clip = 'off'); # Generate the first scale bar scale.bar1.glist <- create.scale.bar( main = yaxis1.label, - visual.length = 0.5, scale.length = get.scale.bar.length(scale.length[1]), edge.col = most.common.value(clone.out$v$edge.colour.1), edge.width = most.common.value(clone.out$v$edge.width.1), @@ -24,18 +21,11 @@ add.scale.bar <- function( ... ); clone.out$grobs <- c(clone.out$grobs, scale.bar1.glist); - # clone.out$grobs <- c(clone.out$grobs, list( - # gTree( - # children = scale.bar1.glist, - # vp = vp.unclipped - # ) - # )); # Create second scalebar if specified if (!is.null(yaxis2.label)) { scale.bar2.glist <- create.scale.bar( main = yaxis2.label, - visual.length = 0.5, scale.length = get.scale.bar.length(scale.length[2], scale1 / scale2), edge.col = most.common.value(clone.out$v$edge.colour.2), edge.width = most.common.value(clone.out$v$edge.width.2), @@ -45,12 +35,6 @@ add.scale.bar <- function( ... ); clone.out$grobs <- c(clone.out$grobs, scale.bar2.glist); - # clone.out$grobs <- c(clone.out$grobs, list( - # gTree( - # children = scale.bar2.glist - # vp = vp.unclipped - # ) - # )); } } @@ -76,7 +60,6 @@ most.common.value <- function(x) { create.scale.bar <- function( main, - visual.length, scale.length, left.x, top.y, @@ -87,17 +70,11 @@ create.scale.bar <- function( label.cex ) { - # do unit stuff internally - print('ran title'); edge.width <- unit(edge.width, "points"); - # xat <- unit(left.x, "npc") + c(0, convertUnit(scale.length$length, 'npc', valueOnly = TRUE)); - # visual.length <- convertUnit(scale.length$length, 'npc'); - visual.length <- unit(scale.length$length, 'native'); - # visual.length <- unit(as.numeric(visual.length), "npc"); left.x <- unit(left.x - 1, "npc"); top.y <- unit(top.y, "npc"); xat <- left.x + unit(c(0, scale.length$length), 'native'); - # main.cex <- unit(14, "points"); + title <- textGrob( label = main, x = xat[1], @@ -108,12 +85,10 @@ create.scale.bar <- function( cex = main.cex ) ); - print('ran title'); - # scale.bar.y <- convertY(top.y - (main.cex * 2), "npc"); - scale.bar.y <- top.y - unit(0.05, 'npc'); + + scale.bar.y <- top.y - unit(0.03, 'npc'); scale.line <- segmentsGrob( x0 = xat[1], - # x1 = left.x + visual.length, x1 = xat[2], y0 = scale.bar.y, y1 = scale.bar.y, @@ -124,12 +99,9 @@ create.scale.bar <- function( lineend = "butt" ) ); - print('ran scale.line'); - # label.cex = unit(12, "points"); + tick.length <- edge.width + unit(label.cex / 100, 'npc'); ticks <- segmentsGrob( - # x0 = c(left.x, left.x + visual.length), - # x1 = c(left.x, left.x + visual.length), x0 = xat, x1 = xat, y0 = scale.bar.y + (edge.width / 2.5), @@ -139,17 +111,16 @@ create.scale.bar <- function( lineend = "butt" ) ); - print('ran tick.length'); + tick.labels <- textGrob( label = c(0, scale.length$label), - # x = c(left.x, left.x + visual.length), x = xat, y = scale.bar.y - tick.length * 2, gp = gpar( cex = label.cex ) ); - print('ran tick.labels'); + return(gList( title, scale.line, From 8041794605001fa7a2d6a5bb0e91d4b7d50ce730 Mon Sep 17 00:00:00 2001 From: whelena Date: Mon, 30 Sep 2024 22:55:43 -0700 Subject: [PATCH 04/14] better placement of scalebar components --- R/SRCGrob.R | 4 +--- R/scale.bar.R | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/R/SRCGrob.R b/R/SRCGrob.R index 2838f84b..258f967e 100644 --- a/R/SRCGrob.R +++ b/R/SRCGrob.R @@ -28,9 +28,7 @@ SRCGrob <- function( length.from.node.edge = TRUE, size.units = 'npc', scale.bar = FALSE, - scale.bar.coords = c(0.1, 0.9) - # scale.bar.padding = 0.5, - # scale.bar.label.padding = 0.5 + scale.bar.coords = c(0.5, 0.9) ) { add.node.text <- !is.null(node.text); diff --git a/R/scale.bar.R b/R/scale.bar.R index dc3853a0..ac2774bf 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -77,7 +77,7 @@ create.scale.bar <- function( title <- textGrob( label = main, - x = xat[1], + x = left.x + unit(scale.length$length / 2, 'native'), y = top.y, hjust = 0.5, vjust = 1, @@ -86,7 +86,7 @@ create.scale.bar <- function( ) ); - scale.bar.y <- top.y - unit(0.03, 'npc'); + scale.bar.y <- top.y - unit(label.cex / 10, 'npc'); scale.line <- segmentsGrob( x0 = xat[1], x1 = xat[2], From ba2215ab820587c5f4d1656f7aa30ce76fb39498 Mon Sep 17 00:00:00 2001 From: whelena Date: Tue, 1 Oct 2024 16:16:12 -0700 Subject: [PATCH 05/14] add param for scale.bar size in addition to auto.scale.bars --- R/SRCGrob.R | 10 ++++---- R/calculate.clone.polygons.R | 1 - R/make.clone.tree.grobs.R | 13 ++++++---- R/scale.bar.R | 46 +++++++++++++++++++++++++----------- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/R/SRCGrob.R b/R/SRCGrob.R index 258f967e..3caca04e 100644 --- a/R/SRCGrob.R +++ b/R/SRCGrob.R @@ -28,7 +28,9 @@ SRCGrob <- function( length.from.node.edge = TRUE, size.units = 'npc', scale.bar = FALSE, - scale.bar.coords = c(0.5, 0.9) + scale.bar.coords = c(0.5, 0.9), + scale.size.1 = NA, + scale.size.2 = NA ) { add.node.text <- !is.null(node.text); @@ -111,9 +113,9 @@ SRCGrob <- function( main.y = main.y, size.units = size.units, scale.bar = scale.bar, - scale.bar.coords = scale.bar.coords - # scale.bar.padding = scale.bar.padding, - # scale.bar.label.padding = scale.bar.label.padding + scale.bar.coords = scale.bar.coords, + scale.size.1 = scale.size.1, + scale.size.2 = scale.size.2 ); out.tree <- gTree( diff --git a/R/calculate.clone.polygons.R b/R/calculate.clone.polygons.R index 1caed888..7ef90618 100644 --- a/R/calculate.clone.polygons.R +++ b/R/calculate.clone.polygons.R @@ -331,7 +331,6 @@ compute.clones <- function( v <- v[is.na(v$parent) | v$parent != -1, ]; v <- rbind(root, v); v <- count.leaves.per.node(v); - if (no.ccf) { tree$angle <- if ((is.null(fixed.angle) && nrow(v) > 6) || any(table(v$parent) > 2)) { tau <- -(pi / 2.5); diff --git a/R/make.clone.tree.grobs.R b/R/make.clone.tree.grobs.R index 5a0079c9..219225c9 100644 --- a/R/make.clone.tree.grobs.R +++ b/R/make.clone.tree.grobs.R @@ -39,6 +39,8 @@ make.clone.tree.grobs <- function( size.units, scale.bar, scale.bar.coords, + scale.size.1, + scale.size.2, ... ) { @@ -156,16 +158,19 @@ make.clone.tree.grobs <- function( } if (scale.bar) { + scale.lengths <- prep.scale.length( + tree, + scale.size.1, + scale.size.2 + ); + add.scale.bar( clone.out, scale1, scale2, yaxis1.label = yaxis1.label, yaxis2.label = yaxis2.label, - scale.length = c( - median(tree$length1[tree$length1 > 0], na.rm = TRUE), - median(tree$length2[tree$length2 > 0], na.rm = TRUE) - ), + scale.length = scale.lengths, main.cex = axis.label.cex$y, label.cex = axis.cex$y, pos = scale.bar.coords diff --git a/R/scale.bar.R b/R/scale.bar.R index ac2774bf..a00e4851 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -1,3 +1,27 @@ +prep.scale.length <- function( + tree, + scale.size.1, + scale.size.2 + ) { + + scale.lengths <- c(scale.size.1, scale.size.2); + tree.lengths <- c( + auto.scale.length(tree$length1), + if ('length2' %in% names(tree)) auto.scale.length(tree$length2) else NA + ); + + # if scale.length is NA, replace with tree.lengths + scale.lengths[is.na(scale.lengths)] <- tree.lengths[is.na(scale.lengths)]; + + return(scale.lengths); + } + +auto.scale.length <- function(edge.lengths) { + scale.length <- median(edge.lengths[edge.lengths > 0], na.rm = TRUE); + adjusted.length <- 10 ** floor(log10(as.numeric(scale.length))); + return(adjusted.length); + } + add.scale.bar <- function( clone.out, scale.length, @@ -12,7 +36,10 @@ add.scale.bar <- function( # Generate the first scale bar scale.bar1.glist <- create.scale.bar( main = yaxis1.label, - scale.length = get.scale.bar.length(scale.length[1]), + scale.length = list( + label = scale.length[1], + length = scale.length[1] + ), edge.col = most.common.value(clone.out$v$edge.colour.1), edge.width = most.common.value(clone.out$v$edge.width.1), edge.type = most.common.value(clone.out$v$edge.type.1), @@ -26,7 +53,10 @@ add.scale.bar <- function( if (!is.null(yaxis2.label)) { scale.bar2.glist <- create.scale.bar( main = yaxis2.label, - scale.length = get.scale.bar.length(scale.length[2], scale1 / scale2), + scale.length = list( + label = scale.length[2], + length = scale.length[2] * scale1 / scale2 + ), edge.col = most.common.value(clone.out$v$edge.colour.2), edge.width = most.common.value(clone.out$v$edge.width.2), edge.type = most.common.value(clone.out$v$edge.type.2), @@ -38,18 +68,6 @@ add.scale.bar <- function( } } -get.scale.bar.length <- function( - scale.length, - conversion.factor = 1 - ) { - - adjusted.length <- 10 ** floor(log10(as.numeric(scale.length))); - return(list( - label = adjusted.length, - length = adjusted.length / conversion.factor - )); - } - most.common.value <- function(x) { if (is.null(x)) { return(NULL); From b16070388a95a7522d39e178025410c21a60f45c Mon Sep 17 00:00:00 2001 From: whelena Date: Tue, 1 Oct 2024 16:17:41 -0700 Subject: [PATCH 06/14] conver label.cex and main.cex to points for calculating spacing between components --- R/scale.bar.R | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/R/scale.bar.R b/R/scale.bar.R index a00e4851..00d307f4 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -92,6 +92,8 @@ create.scale.bar <- function( left.x <- unit(left.x - 1, "npc"); top.y <- unit(top.y, "npc"); xat <- left.x + unit(c(0, scale.length$length), 'native'); + main.size <- unit(main.cex * 12, 'points'); + label.size <- unit(label.cex * 12, 'points'); title <- textGrob( label = main, @@ -104,7 +106,7 @@ create.scale.bar <- function( ) ); - scale.bar.y <- top.y - unit(label.cex / 10, 'npc'); + scale.bar.y <- convertY(top.y - (label.font.size * 2), 'npc'); scale.line <- segmentsGrob( x0 = xat[1], x1 = xat[2], @@ -118,7 +120,7 @@ create.scale.bar <- function( ) ); - tick.length <- edge.width + unit(label.cex / 100, 'npc'); + tick.length <- edge.width + (label.size / 4); ticks <- segmentsGrob( x0 = xat, x1 = xat, From 3570293e5aadc4eb99541a5aebcae773ad45e984 Mon Sep 17 00:00:00 2001 From: whelena Date: Wed, 2 Oct 2024 11:11:18 -0700 Subject: [PATCH 07/14] tweak spacing and cahange default scalebar coordinates --- R/SRCGrob.R | 2 +- R/scale.bar.R | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/SRCGrob.R b/R/SRCGrob.R index 3caca04e..38d86533 100644 --- a/R/SRCGrob.R +++ b/R/SRCGrob.R @@ -28,7 +28,7 @@ SRCGrob <- function( length.from.node.edge = TRUE, size.units = 'npc', scale.bar = FALSE, - scale.bar.coords = c(0.5, 0.9), + scale.bar.coords = c(0.5, 1), scale.size.1 = NA, scale.size.2 = NA ) { diff --git a/R/scale.bar.R b/R/scale.bar.R index 00d307f4..071239b5 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -106,7 +106,7 @@ create.scale.bar <- function( ) ); - scale.bar.y <- convertY(top.y - (label.font.size * 2), 'npc'); + scale.bar.y <- top.y - (main.size * 2) scale.line <- segmentsGrob( x0 = xat[1], x1 = xat[2], From 890c2bdc0ad9b613420fd7b28dfb1057056d4d4a Mon Sep 17 00:00:00 2001 From: whelena Date: Tue, 29 Oct 2024 21:46:57 -0700 Subject: [PATCH 08/14] before adding viewport --- R/scale.bar.R | 54 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/R/scale.bar.R b/R/scale.bar.R index 071239b5..ed2025f2 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -55,7 +55,7 @@ add.scale.bar <- function( main = yaxis2.label, scale.length = list( label = scale.length[2], - length = scale.length[2] * scale1 / scale2 + length = scale.length[2] / scale1 * scale2 ), edge.col = most.common.value(clone.out$v$edge.colour.2), edge.width = most.common.value(clone.out$v$edge.width.2), @@ -77,27 +77,43 @@ most.common.value <- function(x) { } create.scale.bar <- function( - main, - scale.length, - left.x, - top.y, - edge.col, - edge.width, - edge.type, - main.cex, - label.cex - ) { - - edge.width <- unit(edge.width, "points"); - left.x <- unit(left.x - 1, "npc"); - top.y <- unit(top.y, "npc"); - xat <- left.x + unit(c(0, scale.length$length), 'native'); + main, + scale.length, + left.x, + top.y, + edge.col, + edge.width, + edge.type, + main.cex, + label.cex + ) { + + + edge.width <- unit(edge.width, 'points'); + left.x <- unit(left.x, 'npc'); + print(scale.length) + # xat <- unit(c(-1, 1) * scale.length$length, 'native'); + # print(xat) + top.y <- unit(top.y, 'npc'); main.size <- unit(main.cex * 12, 'points'); label.size <- unit(label.cex * 12, 'points'); + # left.x <- convertUnit(left.x, 'native'); + # # Calculate the x-coordinates for the scale bar, centered around left.x + # xat <- left.x + unit(c(-1, 1) * (scale.length$length / 2), 'native'); + # # xat <- convertUnit(xat, 'native'); + left.x; + + # Convert scale.length$length to npc units + scale.length$length <- unit(scale.length$length, 'native') + scale.length$length <- convertUnit(scale.length$length, 'npc', valueOnly = TRUE) + + # Calculate the x-coordinates for the scale bar, centered around left.x + xat <- left.x + unit(c(-1, 1) * (scale.length$length / 2), 'npc'); + + print(xat) title <- textGrob( label = main, - x = left.x + unit(scale.length$length / 2, 'native'), + x = left.x, #+ unit(scale.length$length / 2, 'native'), y = top.y, hjust = 0.5, vjust = 1, @@ -116,7 +132,7 @@ create.scale.bar <- function( col = edge.col, lwd = edge.width, lty = edge.type, - lineend = "butt" + lineend = 'butt' ) ); @@ -128,7 +144,7 @@ create.scale.bar <- function( y1 = scale.bar.y - tick.length, default.units = 'native', gp = gpar( - lineend = "butt" + lineend = 'butt' ) ); From c5e757a72a1f9eefde11cfc24bbab82e38cb86fd Mon Sep 17 00:00:00 2001 From: whelena Date: Tue, 29 Oct 2024 22:23:44 -0700 Subject: [PATCH 09/14] this works, but needs cleanup --- R/scale.bar.R | 69 +++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/R/scale.bar.R b/R/scale.bar.R index ed2025f2..b24ce85f 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -33,9 +33,13 @@ add.scale.bar <- function( ... ) { + # Necessary to get the right positioning + vp.unclipped <- make.plot.viewport(clone.out, clip = 'off'); + # Generate the first scale bar scale.bar1.glist <- create.scale.bar( main = yaxis1.label, + # vp = vp.unclipped, scale.length = list( label = scale.length[1], length = scale.length[1] @@ -47,12 +51,17 @@ add.scale.bar <- function( top.y = pos[2], ... ); - clone.out$grobs <- c(clone.out$grobs, scale.bar1.glist); + + clone.out$grobs <- c( + clone.out$grobs, + list(gTree(children = gList(scale.bar1.glist), vp = vp.unclipped)) + ); # Create second scalebar if specified if (!is.null(yaxis2.label)) { scale.bar2.glist <- create.scale.bar( main = yaxis2.label, + # vp = vp.unclipped, scale.length = list( label = scale.length[2], length = scale.length[2] / scale1 * scale2 @@ -64,7 +73,11 @@ add.scale.bar <- function( top.y = pos[2] + 0.1, ... ); - clone.out$grobs <- c(clone.out$grobs, scale.bar2.glist); + clone.out$grobs <- c( + clone.out$grobs, + list(gTree(children = gList(scale.bar2.glist), vp = vp.unclipped)) + ); + # clone.out$grobs <- c(clone.out$grobs, list(scale.bar2.glist)); } } @@ -78,6 +91,7 @@ most.common.value <- function(x) { create.scale.bar <- function( main, + vp = NULL, scale.length, left.x, top.y, @@ -88,33 +102,26 @@ create.scale.bar <- function( label.cex ) { + scale.vp <- viewport( + x = unit(left.x, "npc"), # Centered in the parent viewport + y = unit(top.y, "npc"), # Adjust y-position based on parent viewport + width = unit(1, "native"), # Native units for scale length + height = unit(1, "native"), # Matches native scaling + just = "center" + ); edge.width <- unit(edge.width, 'points'); - left.x <- unit(left.x, 'npc'); - print(scale.length) - # xat <- unit(c(-1, 1) * scale.length$length, 'native'); - # print(xat) - top.y <- unit(top.y, 'npc'); main.size <- unit(main.cex * 12, 'points'); label.size <- unit(label.cex * 12, 'points'); - # left.x <- convertUnit(left.x, 'native'); - # # Calculate the x-coordinates for the scale bar, centered around left.x - # xat <- left.x + unit(c(-1, 1) * (scale.length$length / 2), 'native'); - # # xat <- convertUnit(xat, 'native'); + left.x; + x0 <- unit(0.5, "npc"); + y0 <- unit(1, "npc"); + xat <- x0 + unit(c(-1, 1) * (scale.length$length / 2), 'native'); - # Convert scale.length$length to npc units - scale.length$length <- unit(scale.length$length, 'native') - scale.length$length <- convertUnit(scale.length$length, 'npc', valueOnly = TRUE) - - # Calculate the x-coordinates for the scale bar, centered around left.x - xat <- left.x + unit(c(-1, 1) * (scale.length$length / 2), 'npc'); - - print(xat) title <- textGrob( label = main, - x = left.x, #+ unit(scale.length$length / 2, 'native'), - y = top.y, + x = x0, #+ unit(scale.length$length / 2, 'native'), + y = y0, hjust = 0.5, vjust = 1, gp = gpar( @@ -122,7 +129,7 @@ create.scale.bar <- function( ) ); - scale.bar.y <- top.y - (main.size * 2) + scale.bar.y <- unit(1, "npc") - (main.size * 2) scale.line <- segmentsGrob( x0 = xat[1], x1 = xat[2], @@ -156,11 +163,13 @@ create.scale.bar <- function( cex = label.cex ) ); - - return(gList( - title, - scale.line, - ticks, - tick.labels - )); - } \ No newline at end of file + print('done') + scale.gTree <- gTree( + children = gList(title, scale.line, ticks, tick.labels), + vp = scale.vp + ); + # return(gTree( + # children = gList(scale.gTree), + # vp = vp + # )); + } From c6a37d29c9e055575c87577f40ff9bd048b597db Mon Sep 17 00:00:00 2001 From: whelena Date: Tue, 29 Oct 2024 22:40:22 -0700 Subject: [PATCH 10/14] cleaned up scale.bar.R --- R/scale.bar.R | 47 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/R/scale.bar.R b/R/scale.bar.R index b24ce85f..cbcf6c71 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -37,9 +37,8 @@ add.scale.bar <- function( vp.unclipped <- make.plot.viewport(clone.out, clip = 'off'); # Generate the first scale bar - scale.bar1.glist <- create.scale.bar( + scale.bar1 <- create.scale.bar( main = yaxis1.label, - # vp = vp.unclipped, scale.length = list( label = scale.length[1], length = scale.length[1] @@ -54,14 +53,13 @@ add.scale.bar <- function( clone.out$grobs <- c( clone.out$grobs, - list(gTree(children = gList(scale.bar1.glist), vp = vp.unclipped)) + list(gTree(children = gList(scale.bar1), vp = vp.unclipped)) ); # Create second scalebar if specified if (!is.null(yaxis2.label)) { - scale.bar2.glist <- create.scale.bar( + scale.bar2 <- create.scale.bar( main = yaxis2.label, - # vp = vp.unclipped, scale.length = list( label = scale.length[2], length = scale.length[2] / scale1 * scale2 @@ -75,9 +73,8 @@ add.scale.bar <- function( ); clone.out$grobs <- c( clone.out$grobs, - list(gTree(children = gList(scale.bar2.glist), vp = vp.unclipped)) + list(gTree(children = gList(scale.bar2), vp = vp.unclipped)) ); - # clone.out$grobs <- c(clone.out$grobs, list(scale.bar2.glist)); } } @@ -91,7 +88,6 @@ most.common.value <- function(x) { create.scale.bar <- function( main, - vp = NULL, scale.length, left.x, top.y, @@ -102,6 +98,7 @@ create.scale.bar <- function( label.cex ) { + # Viewport for the scale bar that centers it without scaling distortion scale.vp <- viewport( x = unit(left.x, "npc"), # Centered in the parent viewport y = unit(top.y, "npc"), # Adjust y-position based on parent viewport @@ -114,27 +111,25 @@ create.scale.bar <- function( main.size <- unit(main.cex * 12, 'points'); label.size <- unit(label.cex * 12, 'points'); - x0 <- unit(0.5, "npc"); - y0 <- unit(1, "npc"); - xat <- x0 + unit(c(-1, 1) * (scale.length$length / 2), 'native'); + # Define coordinates within scale.vp + vp.x <- unit(0.5, "npc"); + vp.y <- unit(0.5, "npc"); + xat <- vp.x + unit(c(-1, 1) * (scale.length$length / 2), 'native'); title <- textGrob( label = main, - x = x0, #+ unit(scale.length$length / 2, 'native'), - y = y0, - hjust = 0.5, - vjust = 1, + x = vp.x, + y = vp.y + main.size, gp = gpar( cex = main.cex ) ); - scale.bar.y <- unit(1, "npc") - (main.size * 2) scale.line <- segmentsGrob( x0 = xat[1], x1 = xat[2], - y0 = scale.bar.y, - y1 = scale.bar.y, + y0 = vp.y, + y1 = vp.y, gp = gpar( col = edge.col, lwd = edge.width, @@ -147,8 +142,8 @@ create.scale.bar <- function( ticks <- segmentsGrob( x0 = xat, x1 = xat, - y0 = scale.bar.y + (edge.width / 2.5), - y1 = scale.bar.y - tick.length, + y0 = vp.y + (edge.width / 2.5), + y1 = vp.y - tick.length, default.units = 'native', gp = gpar( lineend = 'butt' @@ -158,18 +153,14 @@ create.scale.bar <- function( tick.labels <- textGrob( label = c(0, scale.length$label), x = xat, - y = scale.bar.y - tick.length * 2, + y = vp.y - tick.length * 2, gp = gpar( cex = label.cex ) ); - print('done') - scale.gTree <- gTree( + + return(gTree( children = gList(title, scale.line, ticks, tick.labels), vp = scale.vp - ); - # return(gTree( - # children = gList(scale.gTree), - # vp = vp - # )); + )); } From 52dbd68d3d89a8dcf5f568c36a195fb2bcbe610c Mon Sep 17 00:00:00 2001 From: whelena Date: Tue, 29 Oct 2024 23:21:24 -0700 Subject: [PATCH 11/14] add parameter to control spacing between scalebars --- R/SRCGrob.R | 6 ++++-- R/make.clone.tree.grobs.R | 4 +++- R/scale.bar.R | 5 +++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/R/SRCGrob.R b/R/SRCGrob.R index 1b343835..9cd46b34 100644 --- a/R/SRCGrob.R +++ b/R/SRCGrob.R @@ -31,7 +31,8 @@ SRCGrob <- function( scale.bar = FALSE, scale.bar.coords = c(0.5, 1), scale.size.1 = NA, - scale.size.2 = NA + scale.size.2 = NA, + scale.padding = 1 ) { add.node.text <- !is.null(node.text); @@ -118,7 +119,8 @@ SRCGrob <- function( scale.bar = scale.bar, scale.bar.coords = scale.bar.coords, scale.size.1 = scale.size.1, - scale.size.2 = scale.size.2 + scale.size.2 = scale.size.2, + scale.padding = scale.padding ); out.tree <- gTree( diff --git a/R/make.clone.tree.grobs.R b/R/make.clone.tree.grobs.R index 219225c9..ec4d8ead 100644 --- a/R/make.clone.tree.grobs.R +++ b/R/make.clone.tree.grobs.R @@ -41,6 +41,7 @@ make.clone.tree.grobs <- function( scale.bar.coords, scale.size.1, scale.size.2, + scale.padding, ... ) { @@ -173,7 +174,8 @@ make.clone.tree.grobs <- function( scale.length = scale.lengths, main.cex = axis.label.cex$y, label.cex = axis.cex$y, - pos = scale.bar.coords + pos = scale.bar.coords, + padding = scale.padding ); } diff --git a/R/scale.bar.R b/R/scale.bar.R index cbcf6c71..8a2ca21c 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -30,6 +30,7 @@ add.scale.bar <- function( yaxis1.label, yaxis2.label, pos, + padding, ... ) { @@ -68,7 +69,7 @@ add.scale.bar <- function( edge.width = most.common.value(clone.out$v$edge.width.2), edge.type = most.common.value(clone.out$v$edge.type.2), left.x = pos[1], - top.y = pos[2] + 0.1, + top.y = pos[2] + (padding / 10), ... ); clone.out$grobs <- c( @@ -153,7 +154,7 @@ create.scale.bar <- function( tick.labels <- textGrob( label = c(0, scale.length$label), x = xat, - y = vp.y - tick.length * 2, + y = vp.y - tick.length * 2.5, gp = gpar( cex = label.cex ) From a2b71187b107fd120ffb8e28d7394a6a8ec5ac83 Mon Sep 17 00:00:00 2001 From: whelena Date: Wed, 30 Oct 2024 14:18:07 -0700 Subject: [PATCH 12/14] document scale.bar functions --- R/scale.bar.R | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/R/scale.bar.R b/R/scale.bar.R index 8a2ca21c..2fc26fee 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -1,3 +1,18 @@ +################################################################################################### +# prep.scale.length +# +# Description: +# - Prepares the scale lengths for the tree plot based on the provided tree object and scale sizes. +# +# Arguments: +# - tree Tree data frame containing 'length1' and optionally 'length2' elements. +# - scale.size.1 The desireds size for the first scale bar. +# - scale.size.2 The desireds size for the second scale bar (optional). +# +# Returns: +# - A vector of length 2 containing the prepared scale lengths. +# - If 'scale.size.1' or 'scale.size.2' is NA, the corresponding tree length is used. + prep.scale.length <- function( tree, scale.size.1, @@ -16,12 +31,46 @@ prep.scale.length <- function( return(scale.lengths); } +################################################################################################### +# auto.scale.length +# +# Description: +# - Automatically determines an appropriate scale length based on the provided edge lengths. +# +# Arguments: +# - edge.lengths A vector of edge lengths. +# +# Returns: +# - The adjusted scale length, which is the median of the non-zero edge lengths rounded down to the nearest power of 10. + auto.scale.length <- function(edge.lengths) { scale.length <- median(edge.lengths[edge.lengths > 0], na.rm = TRUE); adjusted.length <- 10 ** floor(log10(as.numeric(scale.length))); return(adjusted.length); } +################################################################################################### +# add.scale.bar +# +# Description: +# - Adds a scale bar to the 'clone.out' object. +# - Can add one or two scale bars based on the provided arguments. +# - Utilizes the 'create.scale.bar' and 'most.common.value' helper functions. +# +# Arguments: +# - clone.out The plot object to which the scale bar(s) will be added. +# - scale.length A vector of length 2 specifying the scale lengths for the two scale bars. +# - scale1 The scale value for the first scale bar. +# - scale2 The scale value for the second scale bar. +# - yaxis1.label The label for the first scale bar. +# - yaxis2.label The label for the second scale bar (optional). +# - pos A vector of length 2 specifying the position (x, y) of the scale bar(s). +# - padding The padding between the two scale bars (if both are present). +# - ... Additional arguments passed to 'create.scale.bar'. +# +# Returns: +# - The modified 'clone.out' object with the added scale bar(s). + add.scale.bar <- function( clone.out, scale.length, @@ -79,6 +128,18 @@ add.scale.bar <- function( } } +################################################################################################### +# most.common.value +# +# Description: +# - Finds the most common value in a vector. +# +# Arguments: +# - x The input vector. +# +# Returns: +# - The most common value in the input vector, or NULL if the input is NULL. + most.common.value <- function(x) { if (is.null(x)) { return(NULL); @@ -87,6 +148,30 @@ most.common.value <- function(x) { return(names(n.table)[which.max(n.table)]); } +################################################################################################### +# create.scale.bar +# +# Description: +# - Creates a scale bar grob (graphical object) with a title, scale line, ticks, and labels. +# +# Arguments: +# - main The title of the scale bar. +# - scale.length A list containing the length of the scale bar and its label. +# - left.x The left x-coordinate of the scale bar viewport in normalized parent coordinates (npc). +# - top.y The top y-coordinate of the scale bar viewport in normalized parent coordinates (npc). +# - edge.col The color of the scale bar line and ticks. +# - edge.width The width of the scale bar line and ticks in points. +# - edge.type The line type of the scale bar line (e.g., "solid", "dashed", "dotted"). +# - main.cex The character expansion factor for the scale bar title. +# - label.cex The character expansion factor for the scale bar labels. +# +# Returns: +# - A gTree object representing the scale bar and label. +# +# Details: +# - The function creates a viewport (scale.vp) to place the scale bar within a parent vp without scaling distortion. +# - It defines the coordinates and sizes of the scale bar elements (title, scale line, ticks, and labels) + create.scale.bar <- function( main, scale.length, From df4bb8a04846517746a1b5f7957f173e0674cc6d Mon Sep 17 00:00:00 2001 From: whelena Date: Wed, 30 Oct 2024 14:18:50 -0700 Subject: [PATCH 13/14] update SRCGRob documentation --- R/scale.bar.R | 16 +++---- man/SRCGrob.Rd | 119 ++++++++++++++++++++++++++++--------------------- 2 files changed, 77 insertions(+), 58 deletions(-) diff --git a/R/scale.bar.R b/R/scale.bar.R index 2fc26fee..b2bba1bb 100644 --- a/R/scale.bar.R +++ b/R/scale.bar.R @@ -161,7 +161,7 @@ most.common.value <- function(x) { # - top.y The top y-coordinate of the scale bar viewport in normalized parent coordinates (npc). # - edge.col The color of the scale bar line and ticks. # - edge.width The width of the scale bar line and ticks in points. -# - edge.type The line type of the scale bar line (e.g., "solid", "dashed", "dotted"). +# - edge.type The line type of the scale bar line (e.g., 'solid', 'dashed', 'dotted'). # - main.cex The character expansion factor for the scale bar title. # - label.cex The character expansion factor for the scale bar labels. # @@ -186,11 +186,11 @@ create.scale.bar <- function( # Viewport for the scale bar that centers it without scaling distortion scale.vp <- viewport( - x = unit(left.x, "npc"), # Centered in the parent viewport - y = unit(top.y, "npc"), # Adjust y-position based on parent viewport - width = unit(1, "native"), # Native units for scale length - height = unit(1, "native"), # Matches native scaling - just = "center" + x = unit(left.x, 'npc'), # Centered in the parent viewport + y = unit(top.y, 'npc'), # Adjust y-position based on parent viewport + width = unit(1, 'native'), # Native units for scale length + height = unit(1, 'native'), # Matches native scaling + just = 'center' ); edge.width <- unit(edge.width, 'points'); @@ -198,8 +198,8 @@ create.scale.bar <- function( label.size <- unit(label.cex * 12, 'points'); # Define coordinates within scale.vp - vp.x <- unit(0.5, "npc"); - vp.y <- unit(0.5, "npc"); + vp.x <- unit(0.5, 'npc'); + vp.y <- unit(0.5, 'npc'); xat <- vp.x + unit(c(-1, 1) * (scale.length$length / 2), 'native'); title <- textGrob( diff --git a/man/SRCGrob.Rd b/man/SRCGrob.Rd index 70a2fea7..85ac961d 100644 --- a/man/SRCGrob.Rd +++ b/man/SRCGrob.Rd @@ -20,13 +20,13 @@ SRCGrob( ylab.cex = 1.55, xaxis.cex = 1.45, yaxis.cex = 1.45, - xaxis.label = "CP", + xaxis.label = 'CP', label.cex = NA, node.text.cex = 0.85, main.y = NULL, main.cex = 1.7, node.text.line.dist = 0.1, - colour.scheme = "grey", + colour.scheme = 'grey', add.normal = FALSE, use.radians = FALSE, normal.cex = 1, @@ -35,58 +35,69 @@ SRCGrob( polygon.shape = 3, polygon.width = 1.2, length.from.node.edge = TRUE, - size.units = "npc" + size.units = 'npc', + scale.bar = FALSE, + scale.bar.coords = c(0.5, 1), + scale.size.1 = NA, + scale.size.2 = NA, + scale.padding = 1 + ); } \arguments{ - \item{tree}{Tree structure data.frame} - \item{node.text}{Dataframe for text labels to be displayed next to nodes} - \item{main}{Main plot title} - \item{horizontal.padding}{ - Increase/reduce the plot's horizontal padding proportionally. - A positive value will expand the padding, and a negative value will reduce it. - } - \item{scale1}{ - Proportionally scale the values of the first branch length column in the tree input. - } - \item{scale2}{ - Proportionally scale the values of the second branch length column in the tree input. - } - \item{yat}{ - Specific values to be used for the y-axis ticks. A list is required, with each element - corresponding to an axis. - } - \item{yaxis1.label}{Text label for the first, leftmost y-axis} - \item{yaxis2.label}{Text label for the second, rightmost y-axis} - \item{xlab.cex}{Font size for the x-axis label} - \item{ylab.cex}{Font size for the y-axis labels} - \item{xaxis.cex}{Font size for the x-axis tick labels} - \item{yaxis.cex}{Font size for the y-axis tick labels} - \item{xaxis.label}{Text label for the x-axis} - \item{label.cex}{Font size for the node labels} - \item{node.text.cex}{Font size for the node text} - \item{main.y}{Move the main plot title position up or down} - \item{main.cex}{Font size for the main plot title} - \item{node.text.line.dist}{ - Distance between node text and tree branches (as a value between 0 and 1) - } - \item{colour.scheme}{Vector of colour values to be used for CP polygons} - \item{add.normal}{Adds a normal} - \item{use.radians}{Unit to be used for "angle" column (degrees or radians)} - \item{normal.cex}{Font size within the normal "box"} - \item{label.nodes}{Enable/disable node labels} - \item{disable.polygons}{Disables CP polygon drawing (even when CP values are provided)} - \item{polygon.shape}{ - Changes the shape of the CP shading. - Lower values are smoother. - } -\item{polygon.width}{Width of the CP shading} - \item{length.from.node.edge}{ - Sets the branch length to be calculated from the edge of the node instead of the centre - } - \item{size.units}{Grid units to be used for all specific size/length parameters} + \item{tree}{Tree structure data.frame} + \item{node.text}{Dataframe for text labels to be displayed next to nodes} + \item{main}{Main plot title} + \item{horizontal.padding}{ + Increase/reduce the plot's horizontal padding proportionally. + A positive value will expand the padding, and a negative value will reduce it. + } + \item{scale1}{ + Proportionally scale the values of the first branch length column in the tree input. + } + \item{scale2}{ + Proportionally scale the values of the second branch length column in the tree input. + } + \item{yat}{ + Specific values to be used for the y-axis ticks. A list is required, with each element + corresponding to an axis. + } + \item{yaxis1.label}{Text label for the first, leftmost y-axis} + \item{yaxis2.label}{Text label for the second, rightmost y-axis} + \item{xlab.cex}{Font size for the x-axis label} + \item{ylab.cex}{Font size for the y-axis labels} + \item{xaxis.cex}{Font size for the x-axis tick labels} + \item{yaxis.cex}{Font size for the y-axis tick labels} + \item{xaxis.label}{Text label for the x-axis} + \item{label.cex}{Font size for the node labels} + \item{node.text.cex}{Font size for the node text} + \item{main.y}{Move the main plot title position up or down} + \item{main.cex}{Font size for the main plot title} + \item{node.text.line.dist}{ + Distance between node text and tree branches (as a value between 0 and 1) + } + \item{colour.scheme}{Vector of colour values to be used for CP polygons} + \item{add.normal}{Adds a normal} + \item{use.radians}{Unit to be used for 'angle' column (degrees or radians)} + \item{normal.cex}{Font size within the normal 'box'} + \item{label.nodes}{Enable/disable node labels} + \item{disable.polygons}{Disables CP polygon drawing (even when CP values are provided)} + \item{polygon.shape}{ + Changes the shape of the CP shading. + Lower values are smoother. + } + \item{polygon.width}{Width of the CP shading} + \item{length.from.node.edge}{ + Sets the branch length to be calculated from the edge of the node instead of the centre + } + \item{size.units}{Grid units to be used for all specific size/length parameters} + \item{scale.bar}{Set to \code{TRUE} to add a scale bar instead of y-axis} + \item{scale.bar.coords}{Coordinates for the scale bar placement \code{c(x.pos, y.pos)}} + \item{scale.size.1}{Overide size of the first scale bar} + \item{scale.size.2}{Overide size of the second scale bar} + \item{scale.padding}{Padding between scale bars if more than 1 is present} } -\value{A `grob` of class "SRCGrob"} +\value{A `grob` of class 'SRCGrob'} \author{Dan Knight} \examples{ # Simple Tree Plot @@ -166,6 +177,14 @@ SRCGrob( ); +# Scale Bar +SRCGrob( + branch.lengths.tree, + yaxis1.label = 'SNVs', + scale.bar = TRUE + ); + + # Normal SRCGrob( simple.tree, From 282c8235d76c0567fefaecaa5defe475a3f5582d Mon Sep 17 00:00:00 2001 From: whelena Date: Wed, 30 Oct 2024 14:20:03 -0700 Subject: [PATCH 14/14] update NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 08b3c84f..7d57c0b5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,7 @@ * Node-by-node control of node size * Aesthetic changes for heatmap and clone-genome distribution plot * Add parameters to specify polygon shape and width. +* Add option to use scale bars instead of y-axes. ## Update * Fixed angle calculation bug where child angles do not follow