Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CEV Report #70

Draft
wants to merge 35 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
dcec3a9
Base CEV report Rmd
dan-knight Feb 16, 2023
fb93f4e
Basic report function
dan-knight Feb 16, 2023
4ca62d1
Update changelog
dan-knight Feb 16, 2023
88fafa8
Update dependencies
dan-knight Feb 16, 2023
cfaede0
Merge branch 'feature-report' into danknight-report-template
dan-knight Feb 16, 2023
72dd894
Merge pull request #68 from uclahs-cds/danknight-report-template
whelena Feb 16, 2023
dcdf501
Merge branch 'main' of github.com:uclahs-cds/public-R-CancerEvolution…
dan-knight Feb 22, 2023
634cb28
Define report inputs
dan-knight Feb 25, 2023
a7a7c7c
Validate input column exist
dan-knight Feb 27, 2023
bbbd2b4
Wrapper report data prep function
dan-knight Feb 27, 2023
44fb551
Column validation unit tests
dan-knight Mar 3, 2023
ca17d57
Heatmap default colours
dan-knight Mar 27, 2023
e683765
Move heatmap functions
dan-knight Mar 27, 2023
9e6171b
Refactor summary heatmap
dan-knight Mar 29, 2023
0d30107
Tests and test data for heatmap functions
dan-knight Mar 30, 2023
e57e6aa
Suppress three-colour warning in create.heatmap
dan-knight Mar 30, 2023
33528a4
Fix linting errors
dan-knight Mar 30, 2023
c519eab
Update function imports
dan-knight Mar 30, 2023
32ac364
Update changelog
dan-knight Mar 30, 2023
78ded72
Update heatmap argument names
dan-knight Mar 30, 2023
ad98b08
Merge branch 'danknight-refactor-heatmaps' of github.com:uclahs-cds/p…
dan-knight Apr 5, 2023
36d753d
Validate clone IDs in report input
dan-knight Apr 5, 2023
0ff8553
Fix DESCRIPTION
dan-knight Apr 5, 2023
31e820a
Column validation unit tests
dan-knight Apr 5, 2023
558af78
Prep report plot data
dan-knight Apr 5, 2023
e6197c7
Tests for report plot data
dan-knight Apr 5, 2023
cc44c0e
Fix code style
dan-knight Apr 5, 2023
5048d7f
Fix report column names
dan-knight Apr 5, 2023
37757c8
Add plots to CEV report Rmarkdown template
dan-knight Apr 5, 2023
72aea19
Update changelog
dan-knight Apr 5, 2023
4218d74
Fix report template filepath
dan-knight Apr 5, 2023
d9d6b14
Fix test data
dan-knight Apr 6, 2023
11d4c6f
option to save heatmaps by specifying filename
whelena Apr 11, 2023
ae9b1b3
rename CCF.df to CCF.arr for clarity
whelena Apr 11, 2023
c246daa
Merge branch 'main' of github.com:uclahs-cds/package-CancerEvolutionV…
dan-knight Dec 15, 2023
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
3 changes: 2 additions & 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: 2.0.1
Date: 2023-11-17
Date: 2023-12-15
Authors@R: c(
person("Paul Boutros", role = "cre", email = "[email protected]"),
person("Adriana Salcedo", role = "aut"),
Expand All @@ -22,6 +22,7 @@ Imports:
grDevices,
utils,
stringr,
rmarkdown,
BoutrosLab.plotting.general
Suggests:
testthat,
Expand Down
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ importFrom("graphics", "par", "strheight", "strwidth")
importFrom("grDevices", "dev.list", "rainbow")
importFrom("utils", "read.table", "vi", "head")
importFrom("stringr", "str_replace_all")
importFrom("stats", "setNames", "aggregate", "reshape")
importFrom("stats", "setNames", "median", "aggregate", "reshape")
importFrom("grDevices", "col2rgb")

export(SRCGrob)
10 changes: 9 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
CancerEvolutionVisualization 2.1.0 2023-12-15 (Helena Winata, Dan Knight)

ADDED
* CEV report template and public function
* Generic functions to generate accompanying heatmaps for summarizing
CCF and clustering datas

--------------------------------------------------------------------------
CancerEvolutionVisualization 2.0.1 2023-11-17 (Helena Winata, Dan Knight)

ADDED
Expand Down Expand Up @@ -207,4 +215,4 @@ CancerEvolutionVisualization 0.0.0 2021-09-13 (Adriana Salcedo)

INITIAL FEATURES

- Tree, CNA, and SNV input sampling
- Tree, CNA, and SNV input sampling
36 changes: 36 additions & 0 deletions R/CEV.report.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
CEV.report <- function(
phylogeny,
SNV.assignment,
SNV.counts,
CCF.values,
output.filename,
title,
author,
date = NULL
) {
inputs <- prep.report(
phylogeny,
SNV.assignment,
SNV.counts,
CCF.values
);

report.params <- list(
title = title,
author = author,
date = if (!is.null(date)) date else Sys.Date(),
summary.tree.data = inputs$summary.tree.input,
heatmap.data = inputs$heatmap.input
);

template.path <- system.file(
'CEV.report.Rmd',
package = 'CancerEvolutionVisualization'
);

rmarkdown::render(
template.path,
output_file = output.filename,
params = report.params
);
}
296 changes: 296 additions & 0 deletions R/heatmap.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
plot.ccf.hm <- function(
CCF.arr,
CCF.threshold = NULL,
cluster.dim = 'both',
cluster.method = 'complete',
dist.method = 'euclidean',
colour.scheme = NULL,
xaxis.lab = NULL,
xlab.label = 'Mutations',
filename = NULL,
...
) {

if (!is.null(CCF.threshold)) {
CCF.arr[CCF.arr <= CCF.threshold] <- 0;
}
col.labels <- seq(0, 1, .2);
sample.names <- colnames(CCF.arr);

heatmap.colours <- if (!is.null(colour.scheme)) {
colour.scheme;
} else {
default.heatmap.colours();
}

hm <- BoutrosLab.plotting.general::create.heatmap(
filename = filename,
x = CCF.arr,
force.clustering = TRUE,
cluster.dimensions = cluster.dim,
clustering.method = cluster.method,
rows.distance.method = dist.method,
cols.distance.method = dist.method,
xaxis.lab = xaxis.lab,
xlab.label = xlab.label,
xlab.cex = 1,
xaxis.cex = 0.6,
xaxis.fontface = 1,
xaxis.rot = 90,
yaxis.lab = sample.names,
ylab.cex = 1,
yaxis.cex = 0.6,
yaxis.fontface = 1,
colourkey.cex = 0.6,
colour.scheme = heatmap.colours,
left.padding = 1,
right.padding = 1,
resolution = 3000,
width = 9,
height = 5,
colourkey.labels.at = col.labels,
...
);

return(hm);
}

plot.cluster.hm <- function(
cluster.df,
plt.height = 6,
plt.width = 11,
colour.scheme = NULL,
xaxis.col = NULL,
filename = NULL,
...
) {

if (is.null(levels(cluster.df$ID))) {
cluster.df$ID <- factor(
cluster.df$ID,
levels = sort(unique(cluster.df$ID))
);
}

cluster.df <- droplevels(cluster.df)[order(cluster.df$clone.id, -abs(cluster.df$CCF)), ];
arr <- data.frame.to.array(cluster.df);
snv.order <- unique(cluster.df[, c('SNV.id', 'clone.id')]);
cluster.colours <- get.colours(cluster.df$clone.id, return.names = TRUE);
arr <- arr[snv.order$SNV.id, levels(cluster.df$ID)];

heatmap.colours <- if (!is.null(colour.scheme)) {
colour.scheme;
} else {
default.heatmap.colours();
}

if (!is.null(xaxis.col)) {
xaxis.label <- unique(cluster.df[cluster.df$SNV.id %in% rownames(arr), xaxis.col]);
}

hm <- plot.ccf.hm(
CCF.arr = arr,
cluster.dim = 'none',
colour.scheme = heatmap.colours,
...
);

# Suppress "three-colour scheme" warning with 3 clones.
cov <- suppressWarnings(BoutrosLab.plotting.general::create.heatmap(
x = t(cluster.colours[snv.order$clone.id]),
input.colours = TRUE,
clustering.method = 'none',
grid.col = FALSE,
print.colour.key = FALSE,
resolution = 5000
));

legend.clone <- BoutrosLab.plotting.general::legend.grob(
list(
legend = list(
title = 'Clones',
labels = names(cluster.colours),
colours = cluster.colours,
border = 'black'
),
legend = list(
title = 'CCF',
labels = c(min(arr), max(arr)),
colours = heatmap.colours,
border = 'black',
continuous = TRUE,
size = 0.6
)
),
size = 1,
title.cex = 0.75,
label.cex = 0.6
);

plt <- BoutrosLab.plotting.general::create.multiplot(
filename = filename,
plot.objects = list(cov, hm),
plot.layout = c(1, 2),
panel.heights = c(1, 0.05),
xaxis.lab = if (!is.null(xaxis.col)) xaxis.label else NULL,
xaxis.cex = 0.6,
xaxis.rot = 90,
xaxis.fontface = 1,
xaxis.tck = 0,
yaxis.lab = list(NULL, colnames(arr)),
yaxis.cex = 0.6,
yaxis.tck = 0,
yaxis.fontface = 1,
y.spacing = 0.5,
left.padding = 17,
print.new.legend = TRUE,
legend = list(right = list(
fun = legend.clone
)),
height = plt.height,
width = plt.width
);
return(plt);
}

plot.summary.ccf.hm <- function(
mutation.df,
CCF.threshold = 0,
filename = NULL
) {

median.ccf <- aggregate(
mutation.df$CCF,
by = list(mutation.df$ID, mutation.df$clone.id),
FUN = median
);

colnames(median.ccf) <- c('ID', 'clone.id', 'median.CCF');

arr <- data.frame.to.array(
median.ccf,
value = 'median.CCF',
x.axis = 'clone.id',
y.axis = 'ID'
);
arr[arr <= CCF.threshold] <- 0;

filtered.CCFs <- mutation.df$CCF > 0;
SNV.per.clone <- aggregate(SNV.id ~ clone.id, mutation.df[filtered.CCFs, ], FUN = length);
colnames(SNV.per.clone) <- c('clone.id', 'num.SNV');

SNV.per.sample <- aggregate(SNV.id ~ ID, mutation.df[filtered.CCFs, ], FUN = length);
colnames(SNV.per.sample) <- c('ID', 'num.SNV');

heatmap.colours <- default.heatmap.colours();
barplot.padding.percentage <- 0.05;

max.clone.SNV <- max(SNV.per.clone$num.SNV);

clone.bar <- BoutrosLab.plotting.general::create.barplot(
formula = num.SNV ~ clone.id,
data = SNV.per.clone,
yaxis.cex = 0,
xaxis.lab = rep('', nrow(arr)),
xaxis.cex = 0,
ylimits = c(
-(max.clone.SNV * barplot.padding.percentage),
max.clone.SNV * (1 + barplot.padding.percentage)
),
resolution = 50
);

max.sample.SNV <- max(SNV.per.sample$num.SNV);

sample.bar <- BoutrosLab.plotting.general::create.barplot(
formula = ID ~ num.SNV,
data = SNV.per.sample,
xlab.label = 'SNV per sample',
xlimits = c(
-(max.sample.SNV * barplot.padding.percentage),
max.sample.SNV * (1 + barplot.padding.percentage)
),
ylab.label = NULL,
yaxis.lab = rep('', length(arr)),
yaxis.cex = 0,
resolution = 50,
plot.horizontal = TRUE
);

hm <- BoutrosLab.plotting.general::create.heatmap(
x = arr,
cluster.dimensions = 'none',
xlab.cex = 1,
xlab.label = 'Clone ID',
xaxis.lab = rownames(arr),
xaxis.cex = 0.6,
xaxis.fontface = 1,
xaxis.rot = 90,
ylab.cex = 1,
ylab.label = 'Sample ID',
yaxis.lab = colnames(arr),
yaxis.cex = 0.6,
yaxis.fontface = 1,
print.colour.key = FALSE,
colour.scheme = heatmap.colours,
left.padding = 1,
right.padding = 1,
width = 9,
height = 5
);

legend.ccf <- BoutrosLab.plotting.general::legend.grob(
list(
legend = list(
title = 'CCF',
labels = c(min(arr), max(arr)),
colours = heatmap.colours,
border = 'black',
continuous = TRUE,
size = 0.6
)
),
size = 1,
title.cex = 0.75,
label.cex = 0.6
);

plt <- BoutrosLab.plotting.general::create.multiplot(
filename = filename,
plot.objects = list(hm, sample.bar, clone.bar),
plot.layout = c(2, 2),
layout.skip = c(FALSE, FALSE, FALSE, TRUE),
panel.heights = c(0.3, 1),
panel.widths = c(1, 0.2),
plot.labels.to.retrieve = 1:3,
xlab.label = c('\t', 'Clone ID', '\t', '\t', 'SNV per sample'),
xlab.cex = 0.7,
xaxis.cex = 0.6,
xaxis.tck = 0.4,
xaxis.rot = 90,
xaxis.fontface = 1,
xlab.to.xaxis.padding = - 0.5,
ylab.label = c( 'SNV per clone', '\t', '\t', 'Sample ID', '\t'),
ylab.padding = 8,
ylab.cex = 0.7,
yaxis.cex = 0.6,
yaxis.tck = 0.4,
yaxis.fontface = 1,
x.spacing = c(0),
y.spacing = c(-0.5),
left.padding = 10,
bottom.padding = 3,
merge.legends = FALSE,
print.new.legend = TRUE,
legend = list(right = list(
fun = legend.ccf
)),
height = 6,
width = 11
)
return(plt);
}

default.heatmap.colours <- function() {
return(c('white', 'blue'))
}
Loading
Loading