From 7d2bf9c9fbe43151ec2dd3d4e58d0eae1b73d05d Mon Sep 17 00:00:00 2001 From: lobanovav Date: Thu, 19 Mar 2026 14:48:33 -0400 Subject: [PATCH 1/3] Adding EnhancedVolcano function to the package --- R/Volcano_Plot.R | 314 +++++++++++++++++++++++++++++ tests/testthat/test-Volcano_Plot.R | 139 +++++++++++++ 2 files changed, 453 insertions(+) create mode 100644 R/Volcano_Plot.R create mode 100644 tests/testthat/test-Volcano_Plot.R diff --git a/R/Volcano_Plot.R b/R/Volcano_Plot.R new file mode 100644 index 0000000..e4199a1 --- /dev/null +++ b/R/Volcano_Plot.R @@ -0,0 +1,314 @@ +#' Create Volcano Plots for Differential Expression Analysis +#' +#' Creates enhanced volcano plots for differential expression analysis using the +#' EnhancedVolcano package. Generates both static and interactive (plotly) versions +#' for each comparison specified in the input data. +#' +#' @param DEGAnalysis Data frame containing differential expression analysis results. +#' Must include columns for gene/feature IDs, log fold changes, and p-values. +#' @param label.col Character string specifying the column name containing feature +#' IDs (e.g., gene names). Default is "Gene". +#' @param sig.col Character vector of column names containing significance values +#' (p-values or adjusted p-values). Can specify multiple comparisons. +#' @param lfc.col Character vector of column names containing log2 fold change values. +#' Must have the same length as \code{sig.col}. +#' @param pCutoff Numeric value for the significance threshold. Default is 0.001. +#' @param FCcutoff Numeric value for the log2 fold change threshold. Default is 1.0. +#' @param value_to_sort_the_output_dataset Character string specifying how to sort +#' features for labeling. Options are "p-value" or "fold-change". Default is "p-value". +#' @param no_genes_to_label Integer specifying the number of top features to label +#' on the plot. Default is 30. +#' @param use_only_addition_labels Logical indicating whether to label only the +#' features specified in \code{additional_labels}. Default is FALSE. +#' @param additional_labels Character string of additional feature names to label, +#' separated by commas or spaces. Default is "". +#' @param is_red Logical indicating whether to restrict labeled features to only +#' those passing both significance and fold change thresholds. Default is TRUE. +#' @param labSize Numeric value for the size of feature labels. Default is 4. +#' @param change_sig_name Character string for custom y-axis label. Default is "p-value". +#' @param change_lfc_name Character string for custom x-axis label. Default is "log2FC". +#' @param title Character string for the plot title. Default is "Volcano Plots". +#' @param use_custom_lab Logical indicating whether to use custom axis labels. +#' Default is FALSE. +#' @param ylim Numeric value for the maximum y-axis limit. Set to 0 for automatic +#' scaling. Default is 0. +#' @param custom_xlim Character string for custom x-axis limits. Can be empty for +#' automatic scaling, a single number for symmetrical limits, or two comma-separated +#' numbers for asymmetrical limits. Default is "". +#' @param xlim_additional Numeric value to add padding to x-axis limits. Default is 0. +#' @param ylim_additional Numeric value to add padding to y-axis limits. Default is 0. +#' @param axisLabSize Numeric value for the size of axis labels. Default is 24. +#' @param pointSize Numeric value for the size of points on the plot. Default is 2. +#' +#' @return A named list containing: +#' \item{data}{Original input data frame with added rank columns for each comparison} +#' \item{comparison_static}{Static ggplot2 volcano plot for each comparison} +#' \item{comparison_interactive}{Interactive plotly volcano plot for each comparison} +#' +#' @examples +#' \dontrun{ +#' # Create sample DEG data +#' set.seed(123) +#' deg_data <- data.frame( +#' Gene = paste0("Gene", 1:100), +#' `WT-KO_logFC` = rnorm(100, 0, 2), +#' `WT-KO_pval` = runif(100, 0, 0.1), +#' check.names = FALSE +#' ) +#' +#' # Generate volcano plots +#' results <- Volcano_Plot( +#' DEGAnalysis = deg_data, +#' label.col = "Gene", +#' sig.col = "WT-KO_pval", +#' lfc.col = "WT-KO_logFC", +#' pCutoff = 0.05, +#' FCcutoff = 1.0 +#' ) +#' +#' # Access the plots +#' print(results$`WT-KO_static`) +#' print(results$`WT-KO_interactive`) +#' } +#' +#' @import ggplot2 +#' @import dplyr +#' @import tidyr +#' @importFrom stringr str_split +#' @importFrom ggrepel geom_text_repel +#' @importFrom EnhancedVolcano EnhancedVolcano +#' @importFrom plotly ggplotly +#' @importFrom grid grid.newpage +#' @export +Volcano_Plot <- function(DEGAnalysis, + label.col = "Gene", + sig.col, + lfc.col, + pCutoff = 0.001, + FCcutoff = 1.0, + value_to_sort_the_output_dataset = "p-value", + no_genes_to_label = 30, + use_only_addition_labels = FALSE, + additional_labels = "", + is_red = TRUE, + labSize = 4, + change_sig_name = "p-value", + change_lfc_name = "log2FC", + title = "Volcano Plots", + use_custom_lab = FALSE, + ylim = 0, + custom_xlim = "", + xlim_additional = 0, + ylim_additional = 0, + axisLabSize = 24, + pointSize = 2) { + + ## --------------- ## + ## Main Code Block ## + ## --------------- ## + + df.orig <- DEGAnalysis + rank <- list() + plot_list <- list() + + for(i in 1:length(lfc.col)){ + lfccol <- lfc.col[i] + sigcol <- sig.col[i] + columns_of_interest <- c(label.col, lfc.col[i], sig.col[i]) + df <- df.orig %>% + dplyr::select(one_of(columns_of_interest)) %>% + mutate(!!sym(lfccol) := replace_na(!!sym(lfccol), 0)) %>% + mutate(!!sym(sigcol) := replace_na(!!sym(sigcol), 1)) + + if (use_custom_lab == TRUE){ + if (nchar(change_lfc_name) == 0){lfc_name = lfc.col[i]} + if (nchar(change_sig_name) == 0){sig_name = sig.col[i]} + colnames(df) <- c(label.col, change_lfc_name, sig_name) + } else { + lfc_name = lfc.col[i] + sig_name = sig.col[i] + } + + group <- gsub("_pval|p_val_", "", sig_name) + rank[[i]] <- -log10(df[[sig_name]]) * sign(df[[lfc_name]]) + names(rank)[i] <- paste0("C_", group, "_rank") + + cat(paste0("Genes in initial dataset: ", nrow(df), "\n")) + + # Select top genes by logFC or Significance + if (value_to_sort_the_output_dataset == "fold-change") { + df <- df %>% dplyr::arrange(desc(.data[[lfc_name]])) + } else if (value_to_sort_the_output_dataset == "p-value") { + df <- df %>% dplyr::arrange(.data[[sig_name]]) + } + + if (is_red) { + df_sub <- df[df[[sigcol]] <= pCutoff & abs(df[[lfccol]]) >= FCcutoff, ] + } else { + df_sub <- df + } + + genes_to_label <- as.character(df_sub[1:no_genes_to_label, label.col]) + + # Modifying Additional Labels List: + # Replace commas with spaces and split the string + split_values <- unlist(strsplit(gsub(",", " ", additional_labels), " ")) + additional_labels_vec <- split_values[split_values != ""] + + filter <- additional_labels_vec %in% df[, label.col] + missing_labels <- additional_labels_vec[!filter] + additional_labels_vec <- additional_labels_vec[filter] + + if(length(missing_labels) > 0){ + cat("Could not find:\n") + print(missing_labels) + } + + if(use_only_addition_labels){ + genes_to_label <- additional_labels_vec + } else { + genes_to_label <- unique(append(genes_to_label, additional_labels_vec)) + } + + significant = vector(length = nrow(df)) + significant[] = "Not significant" + significant[which(abs(df[, 2]) > FCcutoff)] = "Fold change only" + significant[which(df[, 3] < pCutoff)] = "Significant only" + significant[which(abs(df[, 2]) > FCcutoff & df[, 3] < pCutoff)] = "Significant and fold change" + print(table(significant)) + + # Fix pvalue == 0 + shapeCustom <- rep(19, nrow(df)) + maxy <- max(-log10(df[[sig_name]]), na.rm = TRUE) + if(ylim > 0){ + maxy <- ylim + } + + cat(paste0("Maxy: ", maxy, "\n")) + if(maxy == Inf){ + # Sometimes, pvalues == 0 + keep <- df[[sig_name]] > 0 + df[[sig_name]][!keep] <- min(df[[sig_name]][keep]) + shapeCustom[!keep] <- 17 + + maxy <- -log10(min(df[[sig_name]][keep])) + cat("Some p-values equal zero. Adjusting y-limits.\n") + cat(paste0("Maxy adjusted: ", maxy, "\n")) + } + + # By default, nothing will be greater than maxy. User can set this value lower + keep <- -log10(df[[sig_name]]) <= maxy + df[[sig_name]][!keep] <- maxy + shapeCustom[!keep] <- 17 + + names(shapeCustom) <- rep("Exact", length(shapeCustom)) + names(shapeCustom)[shapeCustom == 17] <- "Adjusted" + + # Remove if nothin' doin' + if(all(shapeCustom == 19)){ + shapeCustom <- NULL + } + + maxy <- ceiling(maxy) + + if (grepl("log", lfc.col[i])){ + xlab <- bquote(~Log[2]~ "fold change") + } else { + xlab <- "Fold change" + } + if (grepl("adj", sig.col[i])){ + ylab <- bquote(~-Log[10]~ "FDR") + } else { + ylab <- bquote(~-Log[10]~ "p-value") + } + if(use_custom_lab){ + if(lfc_name != lfc.col[i]){ + xlab <- gsub("_", " ", lfc_name) + } + if (sig_name != sig.col[i]){ + ylab <- gsub("_", " ", sig_name) + } + } + + # X-axis custom range change: + if (custom_xlim == "") { + xlim = c(floor(min(df[, lfc_name])) - xlim_additional, + ceiling(max(df[, lfc_name])) + xlim_additional) + } else if (grepl(",", custom_xlim) == FALSE) { + xlim = c(-1 * as.numeric(trimws(custom_xlim)), + as.numeric(trimws(custom_xlim))) + } else { + split_values <- strsplit(custom_xlim, ",")[[1]] + x_min <- as.numeric(trimws(split_values[1])) + x_max <- as.numeric(trimws(split_values[2])) + xlim <- c(x_min, x_max) + } + + # Create static plot + p <- EnhancedVolcano(df, x = lfc_name, y = sig_name, + lab = df[, label.col], + selectLab = genes_to_label, + title = title, + subtitle = group, + xlab = xlab, + ylab = ylab, + xlim = xlim, + ylim = c(0, maxy + ylim_additional), + pCutoff = pCutoff, + FCcutoff = FCcutoff, + axisLabSize = axisLabSize, + labSize = labSize, + pointSize = pointSize, + shapeCustom = shapeCustom) + + # Create interactive plot with no labels + p_empty <- EnhancedVolcano(df, x = lfc_name, y = sig_name, + lab = rep("", nrow(df)), + selectLab = NULL, + title = title, + subtitle = group, + xlab = xlab, + ylab = ylab, + xlim = xlim, + ylim = c(0, maxy + ylim_additional), + pCutoff = pCutoff, + FCcutoff = FCcutoff, + axisLabSize = axisLabSize, + labSize = labSize, + pointSize = pointSize, + shapeCustom = shapeCustom) + + # Extract the data used for plotting + plot_data <- ggplot_build(p_empty)$data[[1]] + + pxx <- p_empty + + xlab("Fold Change") + + ylab("Significance") + + theme_minimal() + + geom_point(aes( + text = paste("Gene:", df[[label.col]], + "
Log2FC:", df[[lfc_name]], + "
P-value:", df[[sig_name]]), + colour = as.character(plot_data$colour), + fill = as.character(plot_data$colour) + ), + shape = 21, + size = 2, + stroke = 0.1) + + scale_fill_identity() + + # Add interactive hover labels for the gene names + interactive_plot <- ggplotly(pxx, tooltip = c("text")) + + # Store plots in the list with descriptive names + plot_list[[paste0(group, "_static")]] <- p + plot_list[[paste0(group, "_interactive")]] <- interactive_plot + } + + # Combine original data with rank columns + df.final <- cbind(df.orig, do.call(cbind, rank)) + + # Return list with data first, then all plots + result <- c(list(data = df.final), plot_list) + return(result) +} \ No newline at end of file diff --git a/tests/testthat/test-Volcano_Plot.R b/tests/testthat/test-Volcano_Plot.R new file mode 100644 index 0000000..b5b98cd --- /dev/null +++ b/tests/testthat/test-Volcano_Plot.R @@ -0,0 +1,139 @@ +# Tests for Volcano_Plot function + +library(testthat) +library(dplyr) + +# Helper function to create test data +create_test_deg_data <- function(n_genes = 100) { + set.seed(123) + data.frame( + Gene = paste0("Gene", 1:n_genes), + `WT-KO_logFC` = rnorm(n_genes, 0, 2), + `WT-KO_pval` = runif(n_genes, 0, 0.1), + `Treated-Control_logFC` = rnorm(n_genes, 0, 1.5), + `Treated-Control_pval` = runif(n_genes, 0, 0.05), + check.names = FALSE + ) +} + +test_that("Volcano_Plot runs without errors on valid input", { + deg_data <- create_test_deg_data() + + expect_no_error( + result <- Volcano_Plot( + DEGAnalysis = deg_data, + label.col = "Gene", + sig.col = "WT-KO_pval", + lfc.col = "WT-KO_logFC", + pCutoff = 0.05, + FCcutoff = 1.0 + ) + ) +}) + +test_that("Volcano_Plot returns correct structure", { + deg_data <- create_test_deg_data() + + result <- Volcano_Plot( + DEGAnalysis = deg_data, + label.col = "Gene", + sig.col = "WT-KO_pval", + lfc.col = "WT-KO_logFC", + pCutoff = 0.05, + FCcutoff = 1.0 + ) + + # Check that result is a list + expect_type(result, "list") + + # Check that 'data' element exists + expect_true("data" %in% names(result)) + + # Check that data is a data frame + expect_s3_class(result$data, "data.frame") + + # Check that rank column was added + expect_true(any(grepl("_rank$", colnames(result$data)))) + + # Check that static plot exists + expect_true(any(grepl("_static$", names(result)))) + + # Check that interactive plot exists + expect_true(any(grepl("_interactive$", names(result)))) + + # Check that static plot is a ggplot object + static_plot_name <- names(result)[grepl("_static$", names(result))][1] + expect_s3_class(result[[static_plot_name]], "ggplot") + + # Check that interactive plot is a plotly object + interactive_plot_name <- names(result)[grepl("_interactive$", names(result))][1] + expect_s3_class(result[[interactive_plot_name]], "plotly") +}) + +test_that("Volcano_Plot handles multiple comparisons correctly", { + deg_data <- create_test_deg_data() + + result <- Volcano_Plot( + DEGAnalysis = deg_data, + label.col = "Gene", + sig.col = c("WT-KO_pval", "Treated-Control_pval"), + lfc.col = c("WT-KO_logFC", "Treated-Control_logFC"), + pCutoff = 0.05, + FCcutoff = 1.0 + ) + + # Should have data + 4 plots (2 comparisons × 2 plot types) + expect_equal(length(result), 5) + + # Check that both comparison names appear + expect_true(any(grepl("WT-KO", names(result)))) + expect_true(any(grepl("Treated-Control", names(result)))) + + # Check that we have both static and interactive for each comparison + expect_equal(sum(grepl("_static$", names(result))), 2) + expect_equal(sum(grepl("_interactive$", names(result))), 2) +}) + +test_that("Volcano_Plot handles edge cases", { + # Test with p-values = 0 + deg_data <- create_test_deg_data(n_genes = 50) + deg_data$`WT-KO_pval`[1:5] <- 0 # Set some p-values to exactly 0 + + expect_no_error( + result <- Volcano_Plot( + DEGAnalysis = deg_data, + label.col = "Gene", + sig.col = "WT-KO_pval", + lfc.col = "WT-KO_logFC", + pCutoff = 0.05, + FCcutoff = 1.0 + ) + ) + + # Check that the function completed and returned data + expect_true("data" %in% names(result)) + expect_equal(nrow(result$data), 50) + + # Test with NA values + deg_data_na <- create_test_deg_data(n_genes = 50) + deg_data_na$`WT-KO_logFC`[1:3] <- NA + deg_data_na$`WT-KO_pval`[4:6] <- NA + + expect_no_error( + result_na <- Volcano_Plot( + DEGAnalysis = deg_data_na, + label.col = "Gene", + sig.col = "WT-KO_pval", + lfc.col = "WT-KO_logFC", + pCutoff = 0.05, + FCcutoff = 1.0 + ) + ) + + # Check that the function completed and returned valid data + # (NA values are handled internally for plotting but preserved in returned data) + expect_true("data" %in% names(result_na)) + expect_equal(nrow(result_na$data), 50) + expect_s3_class(result_na$`WT-KO_static`, "ggplot") + expect_s3_class(result_na$`WT-KO_interactive`, "plotly") +}) \ No newline at end of file From bae871870cad15269a52873edd54d057e291964a Mon Sep 17 00:00:00 2001 From: lobanovav Date: Thu, 26 Mar 2026 11:22:38 -0700 Subject: [PATCH 2/3] Updating Doc, Namespace and run unit test --- DESCRIPTION | 1 + NAMESPACE | 25 +++++++++ man/Volcano_Plot.Rd | 127 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 man/Volcano_Plot.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 0a26fcb..12fddc0 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -74,6 +74,7 @@ Imports: Seurat (>= 4.1.1), gtable (>= 0.3.1), digest (>= 0.6.29), + EnhancedVolcano, png, ggExtra, httr, diff --git a/NAMESPACE b/NAMESPACE index 96b1ac4..457d856 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,17 +1,21 @@ # Generated by roxygen2: do not edit by hand +export(Volcano_Plot) export(aggregateCounts) export(annotateCellTypes) export(appendMetadataToSeuratObject) +export(build_modscore_plots) export(colorByGene) export(colorByMarkerTable) export(combineNormalize) +export(compute_modscore_data) export(degGeneExpressionMarkers) export(dotPlotMet) export(dualLabeling) export(filterQC) export(filterSeuratObjectByMetadata) export(heatmapSC) +export(launch_module_score_app) export(modScore) export(nameClusters) export(object) @@ -46,11 +50,13 @@ import(quantmod) import(reshape2) import(rlang) import(scales) +import(tidyr) import(tidyverse) import(tools) import(utils) importFrom(BiocParallel,SerialParam) importFrom(ComplexHeatmap,pheatmap) +importFrom(EnhancedVolcano,EnhancedVolcano) importFrom(RColorBrewer,brewer.pal) importFrom(RColorBrewer,brewer.pal.info) importFrom(Seurat,AddMetaData) @@ -76,6 +82,7 @@ importFrom(dplyr,arrange) importFrom(dplyr,case_when) importFrom(dplyr,desc) importFrom(dplyr,filter) +importFrom(dplyr,group_by) importFrom(dplyr,if_else) importFrom(dplyr,mutate) importFrom(dplyr,mutate_if) @@ -85,9 +92,13 @@ importFrom(dplyr,rename) importFrom(dplyr,row_number) importFrom(dplyr,select) importFrom(dplyr,summarise) +importFrom(geom_point,guide_legend) +importFrom(geom_point,guides) +importFrom(geom_point,scale_color_gradientn) importFrom(ggExtra,ggMarginal) importFrom(ggplot2,aes) importFrom(ggplot2,coord_fixed) +importFrom(ggplot2,element_blank) importFrom(ggplot2,geom_hline) importFrom(ggplot2,geom_point) importFrom(ggplot2,geom_vline) @@ -104,6 +115,7 @@ importFrom(ggplot2,ylim) importFrom(ggpubr,annotate_figure) importFrom(ggpubr,get_legend) importFrom(ggpubr,ggarrange) +importFrom(ggrepel,geom_text_repel) importFrom(grDevices,colorRampPalette) importFrom(grid,gTree) importFrom(grid,gpar) @@ -113,7 +125,10 @@ importFrom(grid,grobHeight) importFrom(grid,textGrob) importFrom(grid,unit) importFrom(gridExtra,arrangeGrob) +importFrom(gridExtra,gpar) +importFrom(gridExtra,grid) importFrom(gridExtra,tableGrob) +importFrom(gridExtra,textGrob) importFrom(htmlwidgets,saveWidget) importFrom(magrittr,"%>%") importFrom(plotly,as_widget) @@ -121,6 +136,10 @@ importFrom(plotly,ggplotly) importFrom(plotly,plot_ly) importFrom(reshape2,melt) importFrom(scDblFinder,scDblFinder) +importFrom(scale_y_continuous,geom_line) +importFrom(scale_y_continuous,geom_segment) +importFrom(scale_y_continuous,scale_x_continuous) +importFrom(scale_y_continuous,scale_y_log10) importFrom(scales,rescale) importFrom(stats,as.hclust) importFrom(stats,hclust) @@ -130,6 +149,7 @@ importFrom(stats,median) importFrom(stats,quantile) importFrom(stringr,str_replace_all) importFrom(stringr,str_sort) +importFrom(stringr,str_split) importFrom(stringr,str_split_fixed) importFrom(stringr,str_to_title) importFrom(stringr,str_wrap) @@ -138,3 +158,8 @@ importFrom(tibble,rownames_to_column) importFrom(tibble,tibble) importFrom(tidyr,fill) importFrom(tidyr,pivot_wider) +importFrom(xlab,element_text) +importFrom(xlab,geom_hline) +importFrom(xlab,geom_violin) +importFrom(xlab,theme_classic) +importFrom(xlab,ylab) diff --git a/man/Volcano_Plot.Rd b/man/Volcano_Plot.Rd new file mode 100644 index 0000000..889f40c --- /dev/null +++ b/man/Volcano_Plot.Rd @@ -0,0 +1,127 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Volcano_Plot.R +\name{Volcano_Plot} +\alias{Volcano_Plot} +\title{Create Volcano Plots for Differential Expression Analysis} +\usage{ +Volcano_Plot( + DEGAnalysis, + label.col = "Gene", + sig.col, + lfc.col, + pCutoff = 0.001, + FCcutoff = 1, + value_to_sort_the_output_dataset = "p-value", + no_genes_to_label = 30, + use_only_addition_labels = FALSE, + additional_labels = "", + is_red = TRUE, + labSize = 4, + change_sig_name = "p-value", + change_lfc_name = "log2FC", + title = "Volcano Plots", + use_custom_lab = FALSE, + ylim = 0, + custom_xlim = "", + xlim_additional = 0, + ylim_additional = 0, + axisLabSize = 24, + pointSize = 2 +) +} +\arguments{ +\item{DEGAnalysis}{Data frame containing differential expression analysis results. +Must include columns for gene/feature IDs, log fold changes, and p-values.} + +\item{label.col}{Character string specifying the column name containing feature +IDs (e.g., gene names). Default is "Gene".} + +\item{sig.col}{Character vector of column names containing significance values +(p-values or adjusted p-values). Can specify multiple comparisons.} + +\item{lfc.col}{Character vector of column names containing log2 fold change values. +Must have the same length as \code{sig.col}.} + +\item{pCutoff}{Numeric value for the significance threshold. Default is 0.001.} + +\item{FCcutoff}{Numeric value for the log2 fold change threshold. Default is 1.0.} + +\item{value_to_sort_the_output_dataset}{Character string specifying how to sort +features for labeling. Options are "p-value" or "fold-change". Default is "p-value".} + +\item{no_genes_to_label}{Integer specifying the number of top features to label +on the plot. Default is 30.} + +\item{use_only_addition_labels}{Logical indicating whether to label only the +features specified in \code{additional_labels}. Default is FALSE.} + +\item{additional_labels}{Character string of additional feature names to label, +separated by commas or spaces. Default is "".} + +\item{is_red}{Logical indicating whether to restrict labeled features to only +those passing both significance and fold change thresholds. Default is TRUE.} + +\item{labSize}{Numeric value for the size of feature labels. Default is 4.} + +\item{change_sig_name}{Character string for custom y-axis label. Default is "p-value".} + +\item{change_lfc_name}{Character string for custom x-axis label. Default is "log2FC".} + +\item{title}{Character string for the plot title. Default is "Volcano Plots".} + +\item{use_custom_lab}{Logical indicating whether to use custom axis labels. +Default is FALSE.} + +\item{ylim}{Numeric value for the maximum y-axis limit. Set to 0 for automatic +scaling. Default is 0.} + +\item{custom_xlim}{Character string for custom x-axis limits. Can be empty for +automatic scaling, a single number for symmetrical limits, or two comma-separated +numbers for asymmetrical limits. Default is "".} + +\item{xlim_additional}{Numeric value to add padding to x-axis limits. Default is 0.} + +\item{ylim_additional}{Numeric value to add padding to y-axis limits. Default is 0.} + +\item{axisLabSize}{Numeric value for the size of axis labels. Default is 24.} + +\item{pointSize}{Numeric value for the size of points on the plot. Default is 2.} +} +\value{ +A named list containing: +\item{data}{Original input data frame with added rank columns for each comparison} +\item{comparison_static}{Static ggplot2 volcano plot for each comparison} +\item{comparison_interactive}{Interactive plotly volcano plot for each comparison} +} +\description{ +Creates enhanced volcano plots for differential expression analysis using the +EnhancedVolcano package. Generates both static and interactive (plotly) versions +for each comparison specified in the input data. +} +\examples{ +\dontrun{ +# Create sample DEG data +set.seed(123) +deg_data <- data.frame( + Gene = paste0("Gene", 1:100), + `WT-KO_logFC` = rnorm(100, 0, 2), + `WT-KO_pval` = runif(100, 0, 0.1), + check.names = FALSE +) + +# Generate volcano plots +results <- Volcano_Plot( + DEGAnalysis = deg_data, + label.col = "Gene", + sig.col = "WT-KO_pval", + lfc.col = "WT-KO_logFC", + pCutoff = 0.05, + FCcutoff = 1.0 +) + +# Access the plots +print(results$`WT-KO_static`) +print(results$`WT-KO_interactive`) +} + +} From 613e087625b9a708e58b701bae161f82a21685cb Mon Sep 17 00:00:00 2001 From: lobanovav Date: Thu, 26 Mar 2026 14:58:02 -0400 Subject: [PATCH 3/3] Fixing 'is_red' situation --- R/Volcano_Plot.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/Volcano_Plot.R b/R/Volcano_Plot.R index e4199a1..12b7138 100644 --- a/R/Volcano_Plot.R +++ b/R/Volcano_Plot.R @@ -143,7 +143,7 @@ Volcano_Plot <- function(DEGAnalysis, } if (is_red) { - df_sub <- df[df[[sigcol]] <= pCutoff & abs(df[[lfccol]]) >= FCcutoff, ] + df_sub <- df[df[[sig_name]] <= pCutoff & abs(df[[lfc_name]]) >= FCcutoff, ] } else { df_sub <- df }