From 3f0fbffc94e6689f0c13b7d64e8e446be5a442ea Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Tue, 14 Jan 2025 15:07:14 -0800 Subject: [PATCH 01/14] Prep plotting direction input --- R/SRCGrob.R | 1 + R/prep.tree.R | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/R/SRCGrob.R b/R/SRCGrob.R index 670e6a2..7eeab59 100644 --- a/R/SRCGrob.R +++ b/R/SRCGrob.R @@ -2,6 +2,7 @@ SRCGrob <- function( tree, node.text = NULL, main = NULL, + plotting.direction = 'down', horizontal.padding = 0.1, scale1 = 1, scale2 = 1, diff --git a/R/prep.tree.R b/R/prep.tree.R index b65f011..b7ba96f 100644 --- a/R/prep.tree.R +++ b/R/prep.tree.R @@ -654,6 +654,34 @@ prep.node.size <- function(tree.df) { return(node.size); } +prep.plotting.direction <- function(direction, radians = TRUE) { + if (length(direction) > 1) { + stop('"plotting.direction" must be a scalar value.'); + } + + if (is.character(direction)) { + direction <- switch( + direction, + 'down' = 0, + 'up' = pi, + 'left' = -pi / 2, + 'right' = pi / 2, + NA + ); + if (is.na(direction)) { + stop('A character value for "plotting.direction" must be one of "down", "up", "left", or "right".') + } + } else if (is.numeric(direction)) { + if (!radians) { + direction <- degrees.to.radians(direction); + } + direction <- direction %% (2 * pi); + } else { + stop('"plotting.direction" must be numeric or one of "down", "up", "left", or "right".'); + } + return(direction); + } + # default.values must be either a scalar or matching length of column.values. # A scalar will be applied to all NAs. # Otherwise, the corresponding value from default.values will be used. From 31d12bb2f1cc561df1c6799977a94346a5b498ad Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Tue, 14 Jan 2025 15:07:28 -0800 Subject: [PATCH 02/14] Unit tests for plotting direction --- tests/testthat/test-prep.tree.R | 87 +++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/tests/testthat/test-prep.tree.R b/tests/testthat/test-prep.tree.R index 07f7b11..4e49c10 100644 --- a/tests/testthat/test-prep.tree.R +++ b/tests/testthat/test-prep.tree.R @@ -1026,3 +1026,90 @@ test_that( expect_equal(result, expected.result); }); + +test_that( + 'prep.plotting.direction errors if value is not a scalar', { + direction <- 1:10; + expect_error( + { + prep.plotting.direction(direction); + }, + regexp = 'scalar' + ); + }); + +test_that( + 'prep.plotting.direction handles "down" plotting direction', { + direction <- 'down'; + result <- prep.plotting.direction(direction); + expected.result <- 0; + expect_equal(result, expected.result); + }); + +test_that( + 'prep.plotting.direction handles "up" plotting direction', { + direction <- 'up'; + result <- prep.plotting.direction(direction); + expected.result <- pi; + expect_equal(result, expected.result); + }); + +test_that( + 'prep.plotting.direction handles "left" plotting direction', { + direction <- 'left'; + result <- prep.plotting.direction(direction); + expected.result <- -pi / 2; + expect_equal(result, expected.result); + }); + +test_that( + 'prep.plotting.direction handles "right" plotting direction', { + direction <- 'right'; + result <- prep.plotting.direction(direction); + expected.result <- pi / 2; + expect_equal(result, expected.result); + }); + +test_that( + 'prep.plotting.direction handles numeric radian plotting direction', { + direction <- pi * 0.76; + result <- prep.plotting.direction(direction, radians = TRUE); + expect_equal(result, direction); + }); + +test_that( + 'prep.plotting.direction converts degrees plotting direction to radians', { + degrees <- 76; + result <- prep.plotting.direction(degrees, radians = FALSE); + expected.result <- degrees.to.radians(degrees) + expect_equal(result, expected.result); + }); + +test_that( + 'prep.plotting.direction simplifies numeric plotting direction larger than 360 degrees', { + true.angle <- pi / 3.5; + result <- prep.plotting.direction(true.angle + (2 * pi), radians = TRUE); + expect_equal(result, true.angle); + }); + +test_that( + 'prep.plotting.direction errors on invalid character direction', { + direction <- 'invalid'; + expect_error( + { + prep.plotting.direction(direction); + }, + regexp = 'direction' + ); + }); + +test_that( + 'prep.plotting.direction errors on non-character/numeric input', { + direction <- TRUE; + expect_error( + { + prep.plotting.direction(direction); + }, + regexp = 'numeric or one of' + ); + }); From a5665a46d506bc0936fe4a464a634837c61b6d78 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Fri, 17 Jan 2025 11:52:42 -0800 Subject: [PATCH 03/14] Include start angle in angle calculation --- R/angles.R | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/R/angles.R b/R/angles.R index b854d10..ba60234 100644 --- a/R/angles.R +++ b/R/angles.R @@ -1,4 +1,10 @@ -calculate.angles.radial <- function(v, tree, spread, total.angle) { +calculate.angles.radial <- function( + v, + tree, + spread, + total.angle, + start.angle + ) { root.node.id <- v$id[[1]]; node.ids <- c(root.node.id); @@ -13,7 +19,7 @@ calculate.angles.radial <- function(v, tree, spread, total.angle) { parent.id <- tree$parent[tree$tip == current.node.id]; if (parent.id == -1) { - tree$angle[tree$tip == current.node.id] <- 0; + tree$angle[tree$tip == current.node.id] <- start.angle; } child.ids <- as.numeric( @@ -140,7 +146,12 @@ split.equal.x.dist <- function( return(angles); } -calculate.angles.fixed <- function(v, tree, fixed.angle) { +calculate.angles.fixed <- function( + v, + tree, + fixed.angle, + start.angle + ) { angles <- v$angle; node.ids <- c(v$id[[1]]); @@ -151,7 +162,7 @@ calculate.angles.fixed <- function(v, tree, fixed.angle) { parent.angle <- angles[current.node.id]; if (is.na(parent.angle) || length(parent.angle) == 0) { - parent.angle <- 0; + parent.angle <- start.angle; angles[current.node.id] <- parent.angle; } From 6fce6123a6f79924b4a665164b371d1780ee04a6 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Fri, 17 Jan 2025 11:52:56 -0800 Subject: [PATCH 04/14] Update angle calculation unit tests --- tests/testthat/test-angles.R | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/tests/testthat/test-angles.R b/tests/testthat/test-angles.R index 12febcb..f08b312 100644 --- a/tests/testthat/test-angles.R +++ b/tests/testthat/test-angles.R @@ -1,5 +1,5 @@ test_that( - 'calculate.angles.fixed orders nodes correctly', { + 'calculate.angles.radial orders nodes correctly', { num.children <- 4; test.tree <- data.frame( parent = c(-1, rep(1, num.children)) @@ -19,7 +19,8 @@ test_that( test.v, test.tree, spread = 1, - total.angle = total.angle + total.angle = total.angle, + start.angle = 0 ); result.order <- order(result); child.ids <- as.numeric(test.tree$tip[test.tree$parent == 1]); @@ -50,7 +51,8 @@ test_that( test.v, test.tree, spread = 1, - total.angle = total.angle + total.angle = total.angle, + start.angle = 0 ); num.digits <- 6; @@ -93,7 +95,8 @@ test_that( test.v, test.tree, spread = spread, - total.angle = total.angle + total.angle = total.angle, + start.angle = 0 ); result.range <- range(result); @@ -127,7 +130,8 @@ test_that( test.v, test.tree, spread = 1, - total.angle = pi / 2.5 + total.angle = pi / 2.5, + start.angle = 0 ); expect_equal(result[angles.to.override], override.values); @@ -156,7 +160,8 @@ test_that( test.v, test.tree, spread = 1, - total.angle = pi / 2.5 + total.angle = pi / 2.5, + start.angle = 0 ); expect_equal(mean(result[-1]), new.angle); @@ -190,7 +195,8 @@ test_that( test.v, test.tree, spread = 1, - total.angle = total.angle + total.angle = total.angle, + start.angle = 0 ); result.angle.increments <- c( result[3] - result[2], @@ -233,7 +239,8 @@ test_that( test.v, test.tree, spread = 1, - total.angle = total.angle + total.angle = total.angle, + start.angle = 0 ); result.angle.increments <- c( result[3] - result[2], @@ -268,7 +275,8 @@ test_that( result <- calculate.angles.fixed( test.v, test.tree, - fixed.angle = angle + fixed.angle = angle, + start.angle = 0 ); expected.result <- c(0, -(angle), angle); @@ -298,7 +306,8 @@ test_that( result <- calculate.angles.fixed( test.v, test.tree, - fixed.angle = pi / 4 + fixed.angle = pi / 4, + start.angle = 0 ); expect_equal(result[angles.to.override], override.values); @@ -327,7 +336,8 @@ test_that( result <- calculate.angles.fixed( test.v, test.tree, - fixed.angle = fixed.angle + fixed.angle = fixed.angle, + start.angle = 0 ); result.angle.range <- result[3] - result[2]; expected.angle.range <- fixed.angle * 2 * spread; From 0a35e81e59a7d4f9d8dab2f74e2213ecb4573be0 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Fri, 17 Jan 2025 11:57:57 -0800 Subject: [PATCH 05/14] Integrate start angle with internal tree plotting functions --- R/SRCGrob.R | 5 +++++ R/calculate.clone.polygons.R | 16 ++++++++++++++-- R/make.clone.polygons.R | 2 ++ R/make.clone.tree.grobs.R | 4 +++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/R/SRCGrob.R b/R/SRCGrob.R index 7eeab59..430e2d5 100644 --- a/R/SRCGrob.R +++ b/R/SRCGrob.R @@ -59,6 +59,10 @@ SRCGrob <- function( default.node.colour = node.col ); + start.angle <- prep.plotting.direction( + plotting.direction, + radians = use.radians + ); fixed.angle <- pi / 6; min.width <- get.plot.width(horizontal.padding); spread <- 1; @@ -96,6 +100,7 @@ SRCGrob <- function( default.branch.width = 4, add.polygons = add.polygons, spread = spread, + start.angle = start.angle, fixed.angle = fixed.angle, add.node.text = add.node.text, text.on.nodes = text.on.nodes, diff --git a/R/calculate.clone.polygons.R b/R/calculate.clone.polygons.R index 3c73d1e..a52baec 100644 --- a/R/calculate.clone.polygons.R +++ b/R/calculate.clone.polygons.R @@ -315,6 +315,7 @@ compute.clones <- function( wid = 1.2, extra.len = 1, tree = NULL, + start.angle = 0, fixed.angle = NULL, beta.in = 3, branching = TRUE, @@ -331,9 +332,20 @@ compute.clones <- function( tree$angle <- if ((is.null(fixed.angle) && nrow(v) > 6) || any(table(v$parent) > 2) || any(v$mode == 'dendrogram')) { tau <- -(pi / 2.5); vi <- v[v$parent == -1, ]; - calculate.angles.radial(v, tree, spread, abs(tau)); + calculate.angles.radial( + v, + tree, + spread, + abs(tau), + start.angle = start.angle + ); } else { - calculate.angles.fixed(v, tree, fixed.angle); + calculate.angles.fixed( + v, + tree, + fixed.angle, + start.angle = start.angle + ); } tmp <- position.nodes(v, tree, extra.len); diff --git a/R/make.clone.polygons.R b/R/make.clone.polygons.R index e301326..55bdb1c 100644 --- a/R/make.clone.polygons.R +++ b/R/make.clone.polygons.R @@ -6,6 +6,7 @@ make.clone.polygons <- function( scale2, extra.len, node.col, + start.angle, spread = 1, fixed.angle = NULL, beta.in = 3, @@ -32,6 +33,7 @@ make.clone.polygons <- function( extra.len = extra.len, x = 0, y = tree$length[tree$parent == -1], + start.angle = start.angle, fixed.angle = fixed.angle, beta.in = beta.in, branching = branching, diff --git a/R/make.clone.tree.grobs.R b/R/make.clone.tree.grobs.R index 926796c..6fdecee 100644 --- a/R/make.clone.tree.grobs.R +++ b/R/make.clone.tree.grobs.R @@ -13,6 +13,7 @@ make.clone.tree.grobs <- function( cluster.list, add.polygons, spread, + start.angle, fixed.angle, add.node.text, text.df, @@ -75,7 +76,7 @@ make.clone.tree.grobs <- function( #initializing line segment dataframe and adjusting lengths to accomodate the node circles tree$angle <- numeric(length = nrow(tree)); - tree$angle[tree$parent == -1] <- 0; + tree$angle[tree$parent == -1] <- start.angle; if ('length2' %in% colnames(tree)) { tree$length2.c <- tree$length2 / scale1 * scale2; @@ -105,6 +106,7 @@ make.clone.tree.grobs <- function( extra.len, node.col, spread = spread, + start.angle = start.angle, fixed.angle = fixed.angle, add.polygons = add.polygons, no.ccf = no.ccf From ab45070c48173c179d83ce912f3913fadd277b74 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Fri, 17 Jan 2025 13:02:38 -0800 Subject: [PATCH 06/14] Fix bugs when specifying start angle in radial mode --- R/angles.R | 2 +- R/position.nodes.radial.R | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/R/angles.R b/R/angles.R index ba60234..6ce3f6e 100644 --- a/R/angles.R +++ b/R/angles.R @@ -30,7 +30,7 @@ calculate.angles.radial <- function( if (num.children > 0) { parent.angle <- angles[tree$tip == current.node.id]; if (is.na(parent.angle) || length(parent.angle) == 0) { - parent.angle <- 0; + parent.angle <- start.angle; angles[tree$tip == current.node.id] <- parent.angle; } diff --git a/R/position.nodes.radial.R b/R/position.nodes.radial.R index 2920ccb..c2f995f 100644 --- a/R/position.nodes.radial.R +++ b/R/position.nodes.radial.R @@ -56,8 +56,8 @@ position.nodes <- function(v, tree, extra.len) { v$x[v$id == vi$id] <<- v$x[v$id == vi$parent] + dx; v$y[v$id == vi$id] <<- v$y[v$id == vi$parent] + dy; } else { - v$x[v$id == vi$id] <<- 0; - v$y[v$id == vi$id] <<- distance; + v$x[v$id == vi$id] <<- dx; + v$y[v$id == vi$id] <<- dy; } for (child in v$id[v$parent == vi$id]) { From 7324939e518b369804f4890a7295742aa8d5bc4d Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Wed, 9 Apr 2025 15:16:08 -0700 Subject: [PATCH 07/14] Branching plotting direction regression test cases --- .../testthat/data/branching.radial.plots.Rda | Bin 5834 -> 16467 bytes tests/testthat/test-branching.R | 33 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/tests/testthat/data/branching.radial.plots.Rda b/tests/testthat/data/branching.radial.plots.Rda index fb9b828266504f5961922dbb4ccefdbb0d77ddcd..411233374c351889edb24b6d146c400c59549dfd 100644 GIT binary patch literal 16467 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 b10SNM!ndSfyX7}Fz~H!AkciXcV`uvhWsKnE diff --git a/tests/testthat/test-branching.R b/tests/testthat/test-branching.R index 6c79846..ec24193 100644 --- a/tests/testthat/test-branching.R +++ b/tests/testthat/test-branching.R @@ -23,3 +23,36 @@ test_that( )); } ); + + +test_that( + 'Radial branching "right" plotting direction case values', { + load('data/branching.radial.plots.Rda'); + load('data/branching.radial.data.Rda') + + result.tree <- SRCGrob( + branching.radial.test.data$tree, + plotting.direction = 'right' + ); + expect_true(compare.trees( + result.tree, + branching.radial.right.example + )); + } + ); + +test_that( + 'Radial branching 30-degree plotting direction case values', { + load('data/branching.radial.plots.Rda'); + load('data/branching.radial.data.Rda') + + result.tree <- SRCGrob( + branching.radial.test.data$tree, + plotting.direction = 30 + ); + expect_true(compare.trees( + result.tree, + branching.radial.30deg.example + )); + } + ); From 3ccbbeabfbe54104a975dabca52beb9ab2349341 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Wed, 9 Apr 2025 15:16:18 -0700 Subject: [PATCH 08/14] Linear plotting direction regression test cases --- tests/testthat/data/linear.plots.Rda | Bin 9766 -> 13119 bytes tests/testthat/test-linear.R | 14 ++++++++++++++ 2 files changed, 14 insertions(+) diff --git a/tests/testthat/data/linear.plots.Rda b/tests/testthat/data/linear.plots.Rda index 6732c726ce5c93943de4e200b25e1987203811e1..33ca95e9eacdd06ab34bf978326d01118cc5d700 100644 GIT binary patch literal 13119 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 @<7$7LPg+!A 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 literal 9766 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 diff --git a/tests/testthat/test-linear.R b/tests/testthat/test-linear.R index f518eaa..da578c5 100644 --- a/tests/testthat/test-linear.R +++ b/tests/testthat/test-linear.R @@ -21,3 +21,17 @@ test_that( expect_true(compare.trees(linear.example, result.tree)); } ); + +test_that( + 'Linear 30-degree plotting direction case values', { + load('data/linear.plots.Rda'); + load('data/linear.data.Rda') + + result.tree <- SRCGrob( + linear.test.data$tree[, c('parent', 'length.1', 'length.2')], + yaxis2.label = '', + plotting.direction = 30 + ); + expect_true(compare.trees(linear.30deg.example, result.tree)); + } + ); From bf4c19aa1b8b06a18f5dbe421cad79200689bd46 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Wed, 9 Apr 2025 15:16:33 -0700 Subject: [PATCH 09/14] Spread plotting direction regression test cases --- tests/testthat/data/complex.plots.Rda | Bin 8652 -> 17203 bytes tests/testthat/test-complex.R | 16 ++++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/testthat/data/complex.plots.Rda b/tests/testthat/data/complex.plots.Rda index c8567a493cb0c58a15e74f6489a2bbf92b11dd05..2399db92a268978fbe1ef1906fa854eb0f8eb894 100644 GIT binary patch literal 17203 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¬)FHhqyjY&wZZCDg)X@Bw2 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 literal 8652 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 diff --git a/tests/testthat/test-complex.R b/tests/testthat/test-complex.R index 724ba5f..bf1abda 100644 --- a/tests/testthat/test-complex.R +++ b/tests/testthat/test-complex.R @@ -10,3 +10,19 @@ test_that( )); } ); + +test_that( + 'Complex spread 30-degree plotting direction case values', { + load('data/complex.plots.Rda'); + load('data/complex.data.Rda') + + result.tree <- SRCGrob( + spread.test.data$tree, + plotting.direction = 30 + ); + expect_true(compare.trees( + result.tree, + spread.30deg.example + )); + } + ); From 1251f3775624b2da84c1d5b33966bbe3682b2487 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Wed, 9 Apr 2025 15:23:14 -0700 Subject: [PATCH 10/14] Branching fixed angle plotting direction regression test cases --- tests/testthat/data/branching.fixed.plots.Rda | Bin 4751 -> 9036 bytes tests/testthat/test-branching.R | 16 ++++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/testthat/data/branching.fixed.plots.Rda b/tests/testthat/data/branching.fixed.plots.Rda index c9d20cd20647065f6319fc18c4f364338a972265..aa8146ceead49580a2deb512246f93879b5e8b5a 100644 GIT binary patch literal 9036 zcmdsccUV))_BK^1f(U{NC{hFk1QC&@bWlN>5IR9c0YM49H>F8$2Bic-4?#eB2>~h6 zI|P&}(rcuIUcMdla?ZKx_d9>zJb7l%p1m?_X3bhF>wPy%5E;SYhjMf_yUR;wH~ANL0CeT_p~XOXiBW?{LZG!MX{X{Ww)W*iM%%VxicvoVH1>3N2xw zfw??c|Na51pt*9)RH_h`hrbZ+x{&m4`WfRW9(JnW4KY-4mU#I^*N(HL`T4d7 zQVwOPrT&J3GX|eGhQ=bq>8kTZ8dV)dX}4p>lXg35Z=s=&%MxM`a(rFw9bW$3Y3r~C zmAMA+*l@aqBIN%3o4CRioB)LDwuzpv0PK!zTuI+t9|9^kr&Ts_et}QZj&>?AdPGGP zW8-HCLZfHDgPSkYzX}Viw{y;_tbJVcHuH@|jJb1uQR86|Gm{r_7EfL z^Cv3f>;nBOLt)D%nM+firMylb>`|wX&vb-etbubCnbCvO9`Bk$TzB^7#=lA#6&ak& zFi4C7g9I~{dnoD->{_{}7KvRXAu2uv>7yf%#`7CC^tF<#qL#hIPJ=;6lWc?dYpY9n zQ$lb^&2=uGN%PyM3ghlUhNm$*nnYleBFZK@%;qKyI~GcsjVBzaFp< zld_cD&qc~s-dZtvlU_U2?Q0FJ1Wsd{{?R}B_CfD9ils59)Yz#bivNPa#n-yoeGk#* zu`#i_h^Kz&rNc*8T@U)%_jG9X_#JSN%~%P=A(mmBZ}uRa44m)nRL+5 z;u?#xZCOWqiZv=PbL-(c{GL&%RfulOrB_<;etq#XUAoA6L4SKORH9?Y_O5P*T|!lZ z>$gs_q~!{^4?Z113|&ioqz^oCZx>T6cNR3n_XRizaWO{0_pioyNE6NVY+Tj#6tRyY z=}kOeKHaCiev6IJzJsOGX?1j`>Ixx_Yim#PGinA-(#ztph-2>viRU4--{=$eMCF7> zdToDh*k7N1+kRh3%6(HZF0pEMn4BCjdVh3zhW!khl@M2~ebT^fdJ;<}1ye`RGG?6v z5rCmyNF>OR2x&Kxgxr;a3Kk})(?v5~f;Yz;YezKU z*iIoH%P&o{_khNPlh-a2f$lfToJPKz2~0J=gvg7eD+=`u*C7iyYEF4EQnKdJ zu%#M@{55te|Mk($q3BO3+Cx#+^2008WUR%_>yU|J)IZ5-bAWiHL!j{pdtRS9nY%~L zYl2?9IvUpV7JrSs4wpZ=ITZaVb+|Gb@-FDl6^f>f8Z^k z!p5%;0sNNRl<_qM>uLOv;cx#r6=2a{2mhw=kBaaz++0sy{%0B7Gv~A7!%4Y))Zl^S zx^M(LOFTB-2|P_H)iOgt%&n6R?4~}DkUm&X5dNx*{^uquOCC#+`qCWJRKqX&Zyh4d z!)^R+FZW)tp3imqX&UQ@pE^W3Eed3LWB^G1eWG^AAvtVTw}jGb6T;#9J@? zNqVuj3U>qfPhz9Jwl}?nhpg@T`7gmG$~Lo_ic~9sm~KFqK-}C1#c95Rk- ziRM&K@(*uiy3Ffv5zcjZ;&z%OmrB7zbAoU6Q0*gI^yG*R@Eatb=-$&)h_EGn_w~J6 zfjOenUZeMckloyi;5DqwJas;x({Awi~ z94YV-1nW)n?1+EpLxch)~ z=?Xv4(m35ELNe-M@tS!@fj0f+Nku78)VwJvTmn5zrF)B$KnO5yvdP<9dCv!p`Yf>* zxw(C=!C&Ez|MH(ZB9DH$Kb%J9WuPzb<6h&-1XuC#@X*eekp8p`;D~sS{QpdG*@p%W zcp2fp(ubc1$a-)I0#f8V5wFXdqNGwPjYRZ-o*(}5L#H&W&#xTi8*7=++??&v^B9(GzLjC_fBW5`>wZ?~kbg zk>7X3!YC+NVRwB04_!yg03zY@@rOW+9jEc-&L99%{71k*NFd^Q|1#E*)s8xL7w8#e z#KL09qPNr~3m3LB`bLNUw|A*MBv3KkbmpWT4Y2dWGy44j{Coua0N4tDc87UJmO;RL zhZJs)KfaKhpH^fv{G%)UIG*tKlp2}4)9R1@blCs34B&5-Xr1t^+NU}~xuoVR1i*j5 z2O1fCHYcQHB|#v7KJf4IYX|Qx;l5HYHnO(ouk4uGM`gvJde-)$Xbqr4}<^MzPG&9y$cOER4)Ex~W6CDe*4?r~|1F&0E?Jh5~>8=UIi z|6xQYP1vs9KD&$Q%%Bl?0a}yZ(yFhm<*>w3YBS-zy5Y9e8M=Dftb|xh8{PGtSjeK{ z!41d>MTXI z>xxDK)xF)fjQSdJx+GYFxh{lyvc7dF`o43`dj=}QM+4akP35AKrU!2Jm+76qc^Ee% zzt}q!UJ!fct8IW%pq^<>1ToWbAywkz~{ZV8R_wOSRB8(`^A(eQSd|RAuAfoX4A791S6{OBxIyW!LXQkEVu=+bpC; zeV(dlHDj!TKA%7Lio*^%ikhp5%c-*buCI)A!vlqD$2l6*p&xt)(z0 zFuhh+wc3W12XXrb#;*u5*`>Fic1mRWJCDA2z0uZn6V{C`uvFWtHrL8U%e=iksDGd; z8(nDYkt+23?wGt~@nrM*-Oe1(uHYTVo>N*o=laLnK*RO}JQKqKx-B(S$9LmMXY;R( zFPaf$)Q7Z9A~$Bb8l;<@U6%Hn5ywK@QI~Fj3KdPLt|YsctBal6>QyKMm)_IwZ+$5W z>0TXONi9$^A8vk;dH&A5#U5Wv^R$uJ^^$bIJ>y!g#y zMkGHoB}>NA45-jsB4Ve=l^z5_9gb5Q@asgNYlSat=iZgkSfSXCsE8V`a<6vwU;=fI`In4Qns1j(q~`~ zt#Vz&^n*PxMf*#Np!b|tfW%LZ+E zQ#ETwaC`nPBkyNHk{2HrLe#{q*;sD5rP*N`^%a)iZG>x$c_~(D&C8{3DinNVf$?E7 zT=x`9cI2jKM);f{GdGuFI>R%$-ZEh_BY4huFDr>C3?$|^we{kZkf|l_^Ru z&75)jCX(HnuLNX-Erdg!?LIWq_%i#9=_Iww@%bKlcYpbjB)=IeA~zpR``7jfo(A`N5AvzuckLzW+&uz9}F2xpJ~G|I9vP=;uHW>3$)@ zN+H)zzLa)RjX~M9Vi1*Yl;sJK{tKTEx~msRd8mhOdsul(B;4LW4~8!6I9)l#yGdDI zThLCvTE{>0?Tj7FQ~GVNPsU!-_eP5xYuo)s_5RW?P-Rq2NM=9fIZ^71Bj6J2aV92g z3w1Ph&J&jtSCA0~{=TxGCpn9IB~z&QazVEWywwDX!y4+mE_?8>%=}&c^sW84lAG^$ zW|}AqTaqchjW#>?k_WC1WM2Re_W_P!*!TDm{&V5e2v*c}TJK0qJD(W-eyjvjcUgQyjy z_Qv|bk}E@vWwdIJ5ck!Rd5SCKh%omBh^NPFYavOm|3SglR@?|I+-tjS?R=Poje5)I zv5#IZgIUMdwDCeU~x8MDAZrB68%<;9(03{$U#5+5Q5 zCR(-06WOM{K53J=e0cmt6|WvOFVCj-318#`1%Cc^GKnUJsBjn4c>;knbk_v9gz!(n z@!`J0`FebWpb%|W4tRNim!L$r7jjA~3Yaw*Cq$0mrtVznU!;Y*bU}9j5`yS^AOJkF zkpS>$l##ovV^2t%%rk=WD&W9Z+QE2!0YdDkC`G>(3e+++tAxko@u2e~B0&?gMbs&V zFN3vsh%^iH*reoB`hM2KhXoZj`@f2z!wOuTHFXt%uYrE8djJC*7RmV9n%mTj3SS}F zq`&-thrgV^DVY9M74^pgA4-?+^`Dab$L@$203ZR_S4|UJG8gPnNl+M^1Arh50HvS5 z2cQf>=m!`+MEqY}d47e`_>sd3@^_C!&+{CDDm)?=m9@ZEp}?`q`O;8m3j7WH9>Md! zBjTgMzjgko2rmQd?g*j(+#S8lW&G~sk^%#A?jp5bG4hD21MJIRR1Uzh5F+wu0A5B$ ztncUn%_-KPqnjTD%TK98QNUdeuX!{!idAI*Ii!-DfSZRV8We4fwEqN4g?gvp$szQF z+>Aw>fS2(6^b&W7{BOJf@QXi!CBTG-7zkg*117{nIKYHHcq#%g;jf4eFyXI*M?g!H zZ1xuSpE1?n5!X*f4DX5q)#37SM)rwc%}}cE$fBJSttJ-jnS?8seP^7xgantqI2xL7 zEFtV=1GYQS(<2hj1JnR9=xnw{Z**bgDj{z9IHYuZCdUXME^L;yqbw5LG>GQHTp^>I z+r^F?a0wiG$B(npt{mVcFM!KeHE?~N7vczT(^cDh6D*Df`~Ziklx=8=-3=t^HRV?X zy^Y_`C+oelku9;aKX%rhkm4g2Px4)QT$;?7MFqt5na=H#p|o&hsC^7T9T+$RtRo{y zB|!O6W$PbYaU{|ddbAY*JfYex2imd(2CwaaX33xuX2WemLWCeUr~#NSUk{)i^$1Rp zN)=^wC`p0PAf;s(kYxx*05VZQ%M>6m$1(bVpstkC+c$@FqC$JHy@Cp})M;cq(M7H& z0_Io1i-XCRw#MJ3h1!#V>Rf%7Pn;H=^) z5E1Y&=8TZIPG!~s2371x1Ei6&YQM$!e?$H8AArckN17TySACLU5SSA%emmEM5R(dbH<5%I;tBekAx^vf$RbD8VC=#U{o>_!Wl!ZUhfuPksb4GWA6YkP2b= z&ouh4Le1_1o@Ywo^TZaj??_al|F^f9u(}Bu8Ti0ADE+@lHZc$t4d>3~W-KIPls%%$ z-)b41=Z3DDq(9(OIn$gLyRmr>oBGD_fw@g9GH!7(l@ip$n;i;%cKE)iIHeb-j6z=vvt3VmwwJz$o*5KKu%93O07$u4oW5+#wQ3)*pb4laKi5U zTD0n^M3hZFx)!-^SnFa89qByRU!(vrc80}MHeC<7E_|C+EKDu!)X|?2Z6X+ zzbu9Jcrm~2YlyrdE?9vLhcG02woWy~*O603{5B?kgt<8+rtE6WijVG9#`2m%{g6m| z+vbk_tvNOBmAbw9H=u&~?`F5{x+!u?9YUBpVO7}{J2Uf40aKM#Gfs3CBxK7dnJu-e+VKAIhy;9NbxKaeVtaAVZ^)Wo zTVR(ia$G@q<4O=R{q|<;KVPbr$}fbTkftqf#v0m>Dfb%*Z)S6XDmUti!m$;58Kxzw z@AVN5mv+~dMBwIr=H{ggStd*Ai!Poy0@Yq~T0;rf%@TWSE3h}~cBahYRAxuYMwL>* zu*$A`(#0M6uD;h$t@??>;qncudv`6qgcAo1J#T|9MkE_brkvZsrn7%o7c6dwYbl>E z)Fv;dD~R@G;@cFa?0)*Fe!PoBC4?!i1%&NN3G?ptUK`qrQKu5~c2KfHnn7C`ANcIp zrPyCznH6c?s!?7kH=%BIj!HP_<4QD)oY%5cS`<;VN#uK@!Gr57tP&DhU}2ItHHpeK zVW?lcNyYumh34y>yEholhJU}wx7^Y)rtzUd#HcrFRa5AOn+3C1>zUWDRh+x21YXx= ziUgW%*Jak2^2Q;T)%T(eaUxXEo00Jz9!1MAKUdtmso-22?dJ<{eHXjL>#JI7l+*W< zrZl`+(N&ePjxxGbnPUyf=`iWwN?9{;P-&8REEn%f`!VX1zHy<+CLsUlQL|E2b5`0c z(?{KM$Fq+wQdpWS+$@RiQZ|{O@^S==6e6hQiM1%LhnK#;!4BOOOHrRT-ihofPAeWf z2-xSS5SdxTipQZ(mgvn}TzXY}eYa-~Q)@79EF!u4oePU@+qIr>$f?^pb{8fo*s$fH zJu;n`8zfcmv@+T65@=rTR(h)9bPKNh%dPC>j+tEcXCEGR(DV*|VM;1@|1A#@t$Q6M z;+L4Z!Jb$-v^9+d7YyKA+_UM#D%aTznCJe|oCVA?;4W2QG?AwoN|VlMSiL03CTEGm z`%J85VmNt7p^HtKI*fJ9>4j&d`F)dk4>=aAoj0*XZIBvsDDv41PZl4SHeYnfTtv?^ zY5v~L>dy519xmYv%xlzr89dw6K^3x85p(rlGex01mTfyvk&tFrqb%%`DazPp?DgZr z-tF$YvOz<#+#lvQ-mg2QKAD=EG`|e5;1D^RuE)$wz0B3%J)ty^skTN}u5(Us?L|eU zxCWEpE+n1#iR695k~IR(wCO7<piw7K*v@Th8u&mV9Oe-&MzV2y|O8+ zCE=~-Uy8ObzwJf3tdQq&1r zH9Y4#KWB^9L`&uioa|S>6j*3~Ti#EzdFzEs7}x8V{a#crYIDQ5yYq05u=wS|%1QQn zds$^a^AI>Lkc!F*;hwQaWh|AMQeI&5l2xNh!$8R#xmvOb(L~e@;yt*O73a zm(*egt1=M>D_i;EorgaKjEK7+yN8{zFAXGaht}@D)>r1Wq#!7Gi0^InewfrndT#Df z3Q~C=e{wGUNzz9ysVs+c#{&C_?m|11)+|%g2)088qhp_>vEC=54o_Iwb@*kw_&=dC zqxD-Z@-&^(QI=#Y*o1Xey~bivzcs-xo_IeVlAm)RWaT0)5?^j`;^j} z+6)I>cfHzs2`$s+AJ0C%L$H;sQDXGU+7`_it7e`HEFKuw+XW|cc!eFNG@G_2y7`&O z9D^D>X)%E*Iue@)uRMH%KkXzn=+=fXZ0ksn5+SSV6T==gD(T%b9Lrj{f^nJbdfcos z;4>D{t{aD5`~1AG;@sR`RP0mtj`yf|NzsROFW3u;Wo2m65O!sxa|c(v^}9ndrnP65 z3t6V31$@LkChm^Bl;4p@a96f5Rb~#tvx7CUdL-t|^CdmfIeCe~m(=_qp7(n6PRA#g z&gmX;mnijlH#&ca&DQx3?&?rs9PU=?v;wqvt*$2_JYLlD`RKSldzeLJ$sKDufm?Ls zbeS?LcTY**YuXDU@Ak8OVNO*LkD%p_&t_M*MvE#fHtai5CtMULZQ4vWBN^300`)VS zl@A2@m%q>4r`4ZeaOruF$oa2@2r_oj76Sh7=euNztXK%@B#a`^}B?!;VSCj6$ZB4iK*WlJ32$^0cqHA|kquz~G zWH4@a#7G2ue!Z1MFuh@%Qj1m={L>6RBBA6j%c(?;6Uz7x9G&ZPAy-(1w9l!?; z@YvxdCuohH8Y^d3TX>@8O5cEH!+ZVb`$tcu zJX{R48$!g1<;q{Y_pcMINCSBIP)?Gl5siW$6jV%!@XI*^A@=_<+bC*u zO0+M2n^7sf#uT^)`^SK@>E;sbs2ybc9b5v@ERc`<6X;jRM2!|h5Mc`;h?n`-mlRWw z-`>>#78hAc5k?&$2+LIR?L1G0dE{0pHRDlBj@zMk|J(3xB|hWb$qmyJ%iZWV8ic06 z--C^-ZAK2T{Q{a7)*D4Fi;eyQY#?G43+0AcD8UoxT$%1~F;DyXilTl%2ke~33v_^JyBMOPh2k<;F*TE~346C@Xw{7QqUa3;`B|@^TSVcr`)%yEG+JZfJ6VP$-U6 zJQo*im(dAW$PbHv>=D=3MFOycaz)zf8*#Q^V_3)*c*0#a_%C2zIjvGOIoMD}|BeS3 zW#Q-lZuH+44f2sS{&Ft%qk_2_j2p!PTd$DoX%L$i)yJpa%_-nBHYia5f)MjvMisV%aWJ0aoW+Acm50@Z~R6ilr39|V+ zzJpACsET3@Xm&B*ZjC-*cJ+8l(9&XT^0%746A)tWRpxco__^{5(Cmj-?e`KOrB$HW zDx2t_RhrGPVv5)*GiHU)u7m()7&acJ&F{_$$c^UK;$SqeE8$fE%HMI)IWd_B8`-?d(x-i=oA;s|wC_#7`)t;g*RsR)ha?Q60!E zk_91*7qW;3;0<$z`jtT_S@s1yfN3QSU=HQ*0GJ-2dK(i~A`mk6`712uM4T{7@^{(&sFc48^GDgS0JL~D%x*ZjxA3Po zG#Q{Qze`|?5g_01H&2D~{@0z2k_Dk=LPJ^L!Zw>?sknP8vNI5j5nG?ow%A;Av}A+8 z<_Hkzy0U(Py*rowTJ!Xh@%i6a`gtEfYYc1z=#AYzv?dcY$!Ya!{agZ+_ItNGqq(?Y z<2oBOMdF~!FBhkL(_Vi+(th>pC%Q6-Ek+;dT$_hq7~(=pn~28r`o!M^Kl1-GKtH<; z4=LQkFQB>M#ZM9V$}V?41a&^t?_v|A7zH&6l-8e@)@PAlO*~$=c)s;@@UfNhB%Yht?-B-ax+B3*}V0 z)c+#jst!kd=lh$~|44kDlNt-#kF|>cOaZlv|E=4PSBOt}$wEZZDr!~5X^oUMO=&4D zTyPD}N^B>`l4Wfq|-(6A7O1y@#ZLuRTg(n+H|SVoqT@@WU*zPRGqq;40b3xIU%C z4N3pnF!JD@$k!X3YX*TcxV8_vY&n*(7Kkhd@)%!eL^pw`#i8VsFvaL*N7jmyA8?5j zx*6Op9#2&;nSC+zt-1bsu#>_g9x4) zBC{f#y{4^I@UZ97bk;wpH}OJB6VBLzc@HJ%=gbsmwg=gFJ(p)`Wm>J|Wfc?=Zc#GoUL3p-hnCAv zh6d_!#?k3ljI*FtjPCHi-d@^V7mmea1`Q$B(3&yZ((Lm(2KtPE9Leykv<$(Bpm?7^ zvRd{q>g@a;n-dE9L)&cJGc&V~w@$iq?D_ZgN&fOg^Xd1T&`>jN~hkw>p&Yd57$dhc_h2wR=ie z+Q!in<16M#hkJ`W#Rr1RCTFNTs=?T2?_wuu)M*w|?%5Vk8G$$5b2KCkWAH&-Oo|zU z6iTkF$I&5`2ZbZ`EoPdnAjDNiAIrQ_Z3P^OvTCUxTZj#EJeqsxvl^un>vUBDGhdE* zyFz7d%bATBo#`>7`E*_!;B;yu`!|Es3sS5FT*{!*eJu}4(k}&4#7d!$lQKor^HFj_ zW9ZANhfd14nmxYlJdomjoRJmkTk0=!87h}4;@q^jhRrNMXFnPCHCNX>TmN2Lq3E2u z{u0{s=4x3*D5m^jwz*J26@tjw7$JT-cW+c*I1lr_$mnvL=NuPidjrp4j#te#{XDl! zcCS#*G@1P)1da;axm`;xIGVBnzgkWgs))jfuI&#nZayIXcBI{cyF9Bp2i=q4)+%Lx z^;>Rjv7c`3=!rcSEj4EkGFOnL9d*jrGYCzS;-{J$c4-aqb{g=D9XWQng3D5#IjL2| z6vdePVZPlV;7slqTPEExl|Vl3zUb#EeKDHYnk$+pJ{2(W(zDNSEFvsM;7iHvN$w7x zKe5^lucw#(lzaZfw`=Y8>Z!w@W~Y?fNa(Bcv>@ykRgsC3tLe$sq@Lq1lqL>(`H@P! zDi`;DxK?eu%fn!e9^T+YwZ%M-v(`Pr3|nIaIbsSQRV{vAD#O`fhN6Th*aL*#z{*9r z?G1YxTJmC3I9t#koV#8S34;AEBj8Cg=s5H8+_ZUmzPQs<%sg)-s6avUOQmLy|AMZo zY5i!n?8Gi4JW*h<{Srxw;8Do6+%aMjP%>|Q=7pbk60Vc2cRQ^@RfK@_8N#NMk7Av~ zAC!kUJf;PhCe7rvTbmR)zV0|^CPuK$jzn9rA7Pal dmbO{{o92*8F{`sp&D%AQpy>JT#$XW3e*n@mHDUk& diff --git a/tests/testthat/test-branching.R b/tests/testthat/test-branching.R index ec24193..dc024de 100644 --- a/tests/testthat/test-branching.R +++ b/tests/testthat/test-branching.R @@ -11,6 +11,22 @@ test_that( } ); +test_that( + 'Fixed branching 30-degree plotting direction case values', { + load('data/branching.fixed.plots.Rda'); + load('data/branching.fixed.data.Rda') + + result.tree <- SRCGrob( + branching.fixed.test.data$tree, + plotting.direction = 30 + ); + expect_true(compare.trees( + result.tree, + branching.fixed.30deg.example + )); + } + ); + test_that( 'Radial branching case values', { load('data/branching.radial.plots.Rda'); From d1dbcc252d5236da35357545d75a439240edc804 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Wed, 9 Apr 2025 15:34:55 -0700 Subject: [PATCH 11/14] Add plotting direction to manual --- man/SRCGrob.Rd | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/man/SRCGrob.Rd b/man/SRCGrob.Rd index 1c0bb61..24126e9 100644 --- a/man/SRCGrob.Rd +++ b/man/SRCGrob.Rd @@ -10,6 +10,7 @@ SRCGrob( tree, node.text = NULL, main = NULL, + plotting.direction = 'down', horizontal.padding = 0.1, scale1 = 1, scale2 = 1, @@ -46,6 +47,11 @@ SRCGrob( \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{plotting.direction}{ + Sets the direction of flow for the tree. + Can be one of 'down', 'right', 'up', 'left', or a number in degrees. + (Default is 0, downward). + } \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. From f459f0c526a5862821817707cfb0b5e4edabda19 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Wed, 9 Apr 2025 15:38:23 -0700 Subject: [PATCH 12/14] Fix code style --- tests/testthat/test-linear.R | 2 +- tests/testthat/test-prep.tree.R | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/testthat/test-linear.R b/tests/testthat/test-linear.R index da578c5..1d03531 100644 --- a/tests/testthat/test-linear.R +++ b/tests/testthat/test-linear.R @@ -26,7 +26,7 @@ test_that( 'Linear 30-degree plotting direction case values', { load('data/linear.plots.Rda'); load('data/linear.data.Rda') - + result.tree <- SRCGrob( linear.test.data$tree[, c('parent', 'length.1', 'length.2')], yaxis2.label = '', diff --git a/tests/testthat/test-prep.tree.R b/tests/testthat/test-prep.tree.R index 4e49c10..9559ad5 100644 --- a/tests/testthat/test-prep.tree.R +++ b/tests/testthat/test-prep.tree.R @@ -1030,9 +1030,8 @@ test_that( test_that( 'prep.plotting.direction errors if value is not a scalar', { direction <- 1:10; - expect_error( - { - prep.plotting.direction(direction); + expect_error({ + prep.plotting.direction(direction); }, regexp = 'scalar' ); @@ -1095,10 +1094,9 @@ test_that( test_that( 'prep.plotting.direction errors on invalid character direction', { direction <- 'invalid'; - expect_error( - { - prep.plotting.direction(direction); - }, + expect_error({ + prep.plotting.direction(direction); + }, regexp = 'direction' ); }); @@ -1106,9 +1104,8 @@ test_that( test_that( 'prep.plotting.direction errors on non-character/numeric input', { direction <- TRUE; - expect_error( - { - prep.plotting.direction(direction); + expect_error({ + prep.plotting.direction(direction); }, regexp = 'numeric or one of' ); From a25ed817eecd8fa98c82c7ecedc5734f687e0399 Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Wed, 9 Apr 2025 15:40:08 -0700 Subject: [PATCH 13/14] Update changelog --- DESCRIPTION | 2 +- NEWS.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 468209b..25e6285 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: CancerEvolutionVisualization Title: Publication Quality Phylogenetic Tree Plots Version: 3.0.0 -Date: 2024-12-09 +Date: 2025-04-09 Authors@R: c( person("Paul Boutros", role = "cre", email = "PBoutros@mednet.ucla.edu"), person("Adriana Salcedo", role = "aut"), diff --git a/NEWS.md b/NEWS.md index 18fce8c..fe8cb35 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# CancerEvolutionVisualization 3.0.0 (2024-12-09) +# CancerEvolutionVisualization 3.0.0 (2025-04-09) ## Added * Dendrogram mode @@ -12,6 +12,7 @@ * Add option to use scale bars instead of y-axes. * Wrapper function for `SRCgrob` to automatically save plots to file * Add option to annotate the CCF summary heatmap with the cell values. +* `plotting.direction` argument to `SRCGrob` to support arbitrary direction of tree "flow". Can be one of 'down' (default), 'right', 'up', 'left' or any number (in degrees). ## Update * Fixed angle calculation bug where child angles do not follow From ba8f959e8603994be127c174ab263c58c4a590fa Mon Sep 17 00:00:00 2001 From: Dan Knight Date: Thu, 10 Apr 2025 10:39:05 -0700 Subject: [PATCH 14/14] Temporary warning message for unsupported CP/plotting.direction combinations --- R/SRCGrob.R | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/R/SRCGrob.R b/R/SRCGrob.R index 430e2d5..ad4f389 100644 --- a/R/SRCGrob.R +++ b/R/SRCGrob.R @@ -34,6 +34,12 @@ SRCGrob <- function( scale.size.2 = NA, scale.padding = 1 ) { + if ('CP' %in% colnames(tree) && !(plotting.direction %in% c('down', 0))) { + warning(paste( + '"plotting.direction" is not yet supported with "CP" polygon column.', + '"plotting.direction" will be ignored.' + )); + } add.node.text <- !is.null(node.text); add.polygons <- !is.null(tree$CP) && !disable.polygons;