Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: CancerEvolutionVisualization
Title: Publication Quality Phylogenetic Tree Plots
Version: 3.0.0
Date: 2025-03-12
Date: 2025-04-09
Authors@R: c(
person("Paul Boutros", role = "cre", email = "PBoutros@mednet.ucla.edu"),
person("Adriana Salcedo", role = "aut"),
Expand Down
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CancerEvolutionVisualization 3.0.0 (2025-03-12)
# CancerEvolutionVisualization 3.0.0 (2025-04-09)

## Added
* Dendrogram mode
Expand All @@ -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).
* Function to generate single-sample density plot
* Add support for 1xn and 1x1 heatmaps.
* Add `get.colours.in.order` function to get a list of colours and corresponding clone ID order.
Expand Down
12 changes: 12 additions & 0 deletions R/SRCGrob.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ SRCGrob <- function(
tree,
node.text = NULL,
main = NULL,
plotting.direction = 'down',
horizontal.padding = 0.1,
scale1 = 1,
scale2 = 1,
Expand Down Expand Up @@ -33,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;
Expand All @@ -58,6 +65,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;
Expand Down Expand Up @@ -95,6 +106,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,
Expand Down
21 changes: 16 additions & 5 deletions R/angles.R
Original file line number Diff line number Diff line change
@@ -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);

Expand All @@ -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(
Expand All @@ -24,7 +30,7 @@ calculate.angles.radial <- function(v, tree, spread, total.angle) {
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;
}

Expand Down Expand Up @@ -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]]);

Expand All @@ -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;
}

Expand Down
16 changes: 14 additions & 2 deletions R/calculate.clone.polygons.R
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions R/make.clone.polygons.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ make.clone.polygons <- function(
scale2,
extra.len,
node.col,
start.angle,
spread = 1,
fixed.angle = NULL,
beta.in = 3,
Expand All @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion R/make.clone.tree.grobs.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ make.clone.tree.grobs <- function(
cluster.list,
add.polygons,
spread,
start.angle,
fixed.angle,
add.node.text,
text.df,
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions R/position.nodes.radial.R
Original file line number Diff line number Diff line change
Expand Up @@ -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]) {
Expand Down
28 changes: 28 additions & 0 deletions R/prep.tree.R
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions man/SRCGrob.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ SRCGrob(
tree,
node.text = NULL,
main = NULL,
plotting.direction = 'down',
horizontal.padding = 0.1,
scale1 = 1,
scale2 = 1,
Expand Down Expand Up @@ -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.
Expand Down
Binary file modified tests/testthat/data/branching.fixed.plots.Rda
Binary file not shown.
Binary file modified tests/testthat/data/branching.radial.plots.Rda
Binary file not shown.
Binary file modified tests/testthat/data/complex.plots.Rda
Binary file not shown.
Binary file modified tests/testthat/data/linear.plots.Rda
Binary file not shown.
32 changes: 21 additions & 11 deletions tests/testthat/test-angles.R
Original file line number Diff line number Diff line change
@@ -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))
Expand All @@ -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]);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
Loading