diff --git a/NAMESPACE b/NAMESPACE index 67087fd..947ef89 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -37,6 +37,7 @@ export(plot_glycan_distribution) export(plot_missval_heatmap) export(plot_or) export(plot_pca) +export(plot_peptide_volcano) export(plot_volcano) export(prepare_PTMSEA) export(prepare_kinome) diff --git a/R/DE.R b/R/DE.R index 3043ca9..7cba846 100644 --- a/R/DE.R +++ b/R/DE.R @@ -616,6 +616,280 @@ plot_volcano <- function(dep, contrast, label_size = 3, name_col = NULL, } } +#' @export +plot_peptide_volcano <- function(dep, contrast, peptides=NA, show_other_peptides=T, show_gene=F, + label_size = 3, name_col = NULL, + add_names = TRUE, adjusted = T, alpha = 0.05, lfc = 1) { + # Show error if inputs are not the required classes + if (is.integer(label_size)) label_size <- as.numeric(label_size) + assertthat::assert_that( + inherits(dep, "SummarizedExperiment"), + is.character(contrast), + length(contrast) == 1, + is.numeric(label_size), + length(label_size) == 1, + is.logical(add_names), + length(add_names) == 1, + is.logical(adjusted), + length(adjusted) == 1, + metadata(se)$level == "peptide" + ) + + row_data <- rowData(dep, use.names = FALSE) + + # Show error if inputs do not contain required columns + if (is.null(name_col)) { + name_col <- "ID" + } + if (any(!c("name", "ID", name_col) %in% colnames(row_data))) { + stop( + paste0( + "'name' and/or 'ID' columns are not present in '", + deparse(substitute(dep)), + "'.\nRun make_unique() to obtain required columns." + ), + call. = FALSE + ) + } + + if (length(grep("_p.adj|_diff", colnames(row_data))) < 1) { + stop( + paste0( + "'[contrast]_diff' and '[contrast]_p.adj' columns are not present in '", + deparse(substitute(dep)), + "'.\nRun test_diff() to obtain the required columns." + ), + call. = FALSE + ) + } + + if (length(grep("_significant", colnames(row_data))) < 1) { + stop( + paste0( + "'[contrast]_significant' columns are not present in '", + deparse(substitute(dep)), + "'.\nRun add_rejections() to obtain the required columns." + ), + call. = FALSE + ) + } + + # Show error if an unvalid contrast is given + if (length(grep( + paste("^", contrast, "_diff", sep = ""), + colnames(row_data) + )) == 0) { + valid_cntrsts <- row_data %>% + data.frame() %>% + select(ends_with("_diff")) %>% + colnames(.) %>% + gsub("_diff", "", .) + valid_cntrsts_msg <- paste0( + "Valid contrasts are: '", + paste0(valid_cntrsts, collapse = "', '"), + "'" + ) + stop("Not a valid contrast, please run `plot_volcano()` with a valid contrast as argument\n", + valid_cntrsts_msg, + call. = FALSE + ) + } + + # Generate a data.frame containing all info for the volcano plot + diff <- grep( + paste("^", contrast, "_diff", sep = ""), + colnames(row_data) + ) + if (adjusted) { + p_values <- grep( + paste("^", contrast, "_p.adj", sep = ""), + colnames(row_data) + ) + } else { + p_values <- grep( + paste("^", contrast, "_p.val", sep = ""), + colnames(row_data) + ) + } + signif <- abs(row_data[, diff]) >= lfc & row_data[, p_values] <= alpha + + df_tmp <- data.frame( + diff = row_data[, diff], + p_values = -log10(row_data[, p_values]), + signif = signif, + name = row_data$name, + ID = row_data$ID, + label = row_data[,name_col], + Gene = row_data$Gene + ) + + df <- df_tmp %>% + data.frame() %>% + filter(!is.na(signif)) %>% + arrange(signif) + name1 <- gsub("_vs_.*", "", contrast) + name2 <- gsub(".*_vs_", "", contrast) + # return(df) + # Plot volcano with or without labels + if (show_gene) { + df$ID_new <- paste0(df$Gene, gsub(".*_", "_", df$ID)) + if (!show_other_peptides) { + p <- ggplot(df, aes(diff, p_values)) + + geom_vline(xintercept = 0) + + geom_point(aes(col = signif)) + + geom_point(data = subset(df, ID %in% c(peptides)), color = "maroon", size= 3) + + geom_text(data = data.frame(), aes( + x = c(Inf, -Inf), + y = c(-Inf, -Inf), + hjust = c(1, 0), + vjust = c(-1, -1), + label = c(name1, name2), + size = 5, + fontface = "bold" + )) + + geom_text_repel(data = subset(df, ID %in% peptides), + color = "maroon", + aes(label = ID_new)) + + labs( + title = contrast, + x = expression(log[2] ~ "Fold change") + ) + + theme_bw() + + theme(panel.border = element_blank(), panel.grid.major = element_blank(), + panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), legend.position = "none") + + scale_color_manual(values = c("TRUE" = "black", "FALSE" = "grey")) + if (add_names) { + p <- p + ggrepel::geom_text_repel( + data = filter(df, signif), + aes(label = label), + size = label_size, + box.padding = unit(0.1, "lines"), + point.padding = unit(0.1, "lines"), + segment.size = 0.5 + ) + } + } else { + p <- ggplot(df, aes(diff, p_values)) + + geom_vline(xintercept = 0) + + geom_point(aes(col = signif)) + + geom_point(data = subset(df, gsub("_.*", "", ID) %in% c(gsub("_.*", "", peptides))), + color = "blue", size= 3) + + geom_point(data = subset(df, ID %in% peptides), + color = "maroon", size= 3) + + geom_text_repel(data = subset(df, ID %in% peptides), + color = "maroon", + aes(label = ID_new)) + + geom_text(data = data.frame(), aes( + x = c(Inf, -Inf), + y = c(-Inf, -Inf), + hjust = c(1, 0), + vjust = c(-1, -1), + label = c(name1, name2), + size = 5, + fontface = "bold" + )) + + labs( + title = contrast, + x = expression(log[2] ~ "Fold change") + ) + + theme_bw() + + theme(panel.border = element_blank(), panel.grid.major = element_blank(), + panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), legend.position = "none") + + scale_color_manual(values = c("TRUE" = "black", "FALSE" = "grey")) + if (add_names) { + p <- p + ggrepel::geom_text_repel( + data = filter(df, signif), + aes(label = ID_new), + size = label_size, + box.padding = unit(0.1, "lines"), + point.padding = unit(0.1, "lines"), + segment.size = 0.5 + ) + } + } + } else { + if (!show_other_peptides) { + p <- ggplot(df, aes(diff, p_values)) + + geom_vline(xintercept = 0) + + geom_point(aes(col = signif)) + + geom_point(data = subset(df, ID %in% c(peptides)), color = "maroon", size= 3) + + geom_text(data = data.frame(), aes( + x = c(Inf, -Inf), + y = c(-Inf, -Inf), + hjust = c(1, 0), + vjust = c(-1, -1), + label = c(name1, name2), + size = 5, + fontface = "bold" + )) + + labs( + title = contrast, + x = expression(log[2] ~ "Fold change") + ) + + theme_bw() + + theme(panel.border = element_blank(), panel.grid.major = element_blank(), + panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), legend.position = "none") + + scale_color_manual(values = c("TRUE" = "black", "FALSE" = "grey")) + if (add_names) { + p <- p + ggrepel::geom_text_repel( + data = filter(df, signif), + aes(label = label), + size = label_size, + box.padding = unit(0.1, "lines"), + point.padding = unit(0.1, "lines"), + segment.size = 0.5 + ) + } + } else { + p <- ggplot(df, aes(diff, p_values)) + + geom_vline(xintercept = 0) + + geom_point(aes(col = signif)) + + geom_point(data = subset(df, gsub("_.*", "", ID) %in% c(gsub("_.*", "", peptides))), + color = "blue", size= 3) + + geom_point(data = subset(df, ID %in% peptides), + color = "maroon", size= 3) + + geom_text_repel(data = subset(df, ID %in% peptides), + color = "maroon", + aes(label = ID)) + + geom_text(data = data.frame(), aes( + x = c(Inf, -Inf), + y = c(-Inf, -Inf), + hjust = c(1, 0), + vjust = c(-1, -1), + label = c(name1, name2), + size = 5, + fontface = "bold" + )) + + labs( + title = contrast, + x = expression(log[2] ~ "Fold change") + ) + + theme_bw() + + theme(panel.border = element_blank(), panel.grid.major = element_blank(), + panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), legend.position = "none") + + scale_color_manual(values = c("TRUE" = "black", "FALSE" = "grey")) + if (add_names) { + p <- p + ggrepel::geom_text_repel( + data = filter(df, signif), + aes(label = label), + size = label_size, + box.padding = unit(0.1, "lines"), + point.padding = unit(0.1, "lines"), + segment.size = 0.5 + ) + } + } + } + + if (adjusted) { + p <- p + labs(y = expression(-log[10] ~ "Adjusted p-value")) + } else { + p <- p + labs(y = expression(-log[10] ~ "P-value")) + } + + return(p) +} + # From DEP theme_DEP1 <- function() { # Use theme_bw() as default