% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/volcanoplot.R
\name{VolcanoPlot}
\alias{VolcanoPlot}
\title{Volcano plot}
\usage{
VolcanoPlot(
  data,
  x,
  y,
  ytrans = "-log10",
  color_by = NULL,
  color_name = NULL,
  xlim = NULL,
  flip_negatives = FALSE,
  x_cutoff = NULL,
  y_cutoff = 0.05,
  split_by = NULL,
  split_by_sep = "_",
  label_by = NULL,
  x_cutoff_name = NULL,
  y_cutoff_name = NULL,
  x_cutoff_color = "red2",
  y_cutoff_color = "blue2",
  x_cutoff_linetype = "dashed",
  y_cutoff_linetype = "dashed",
  x_cutoff_linewidth = 0.5,
  y_cutoff_linewidth = 0.5,
  pt_size = 2,
  pt_alpha = 0.5,
  pt_shape = 21,
  pt_border_color = TRUE,
  pt_border_size = 0.5,
  nlabel = 5,
  labels = NULL,
  label_size = 3,
  label_fg = "black",
  label_bg = "white",
  label_bg_r = 0.1,
  highlight = NULL,
  highlight_color = "red",
  highlight_size = 2,
  highlight_alpha = 1,
  highlight_stroke = 0.5,
  raster = NULL,
  raster_dpi = c(512, 512),
  trim = c(0, 1),
  facet_by = NULL,
  facet_scales = "fixed",
  facet_ncol = NULL,
  facet_nrow = NULL,
  facet_byrow = TRUE,
  theme = "theme_this",
  theme_args = list(),
  palette = "Spectral",
  palcolor = NULL,
  palreverse = FALSE,
  title = NULL,
  subtitle = NULL,
  xlab = NULL,
  ylab = NULL,
  aspect.ratio = 1,
  legend.position = "right",
  legend.direction = "vertical",
  seed = 8525,
  combine = TRUE,
  nrow = NULL,
  ncol = NULL,
  byrow = TRUE,
  axes = NULL,
  axis_titles = axes,
  guides = NULL,
  design = NULL,
  ...
)
}
\arguments{
\item{data}{A data frame.}

\item{x}{A character string specifying the column name of the data frame to plot for the x-axis.}

\item{y}{A character string specifying the column name of the data frame to plot for the y-axis.}

\item{ytrans}{A function or a function name (as a string) to transform
the y-axis values before plotting. The transformed values are used for
both the y-axis and cutoff comparisons. Default: \code{"-log10"}
(converts p-values to a -log10 scale). Other named functions can be
passed as strings, e.g. \code{"sqrt"}.}

\item{color_by}{A character string specifying the column name to colour
the points by. When \code{NULL} (default), points are automatically
categorised as \code{"sig_pos_x"}, \code{"sig_neg_x"}, or
\code{"insig"} based on \code{x_cutoff} and \code{y_cutoff}, and the
colour legend is suppressed. When a column name is provided, the colour
mapping follows the column type — discrete (character/factor) uses
\code{scale_color_manual()} with the specified \code{palette};
numeric (continuous) uses \code{scale_color_gradientn()}.}

\item{color_name}{A character string for the colour legend title when
\code{color_by} is a numeric column. When \code{NULL} (default), the
\code{color_by} column name is used.}

\item{xlim}{A numeric vector of length 2 to set the x-axis limits.
Passed to \code{\link[ggplot2]{xlim}()}. When \code{NULL} (default),
limits are determined automatically from the data.}

\item{flip_negatives}{A logical value. When \code{TRUE}, y-values of
points with negative x-values are multiplied by -1, creating a mirrored
volcano plot where both up- and down-regulated features show their
significance on the same side of the y-axis. A horizontal line at
\code{y = 0} and absolute-value axis labels are added. Default:
\code{FALSE}.}

\item{x_cutoff}{A numeric value specifying the x-axis significance
cutoff. Both the negative and positive of this value are used as
vertical threshold lines. When \code{NULL} or \code{0}, no x-cutoff
line is drawn. Default: \code{NULL}.}

\item{y_cutoff}{A numeric value specifying the y-axis significance
cutoff in the \strong{original} (untransformed) scale. The value is
transformed by \code{ytrans} before plotting. When \code{NULL}, no
y-cutoff line is drawn and the category assignment uses only the
x-cutoff. Default: \code{0.05}.}

\item{split_by}{The column(s) to split the data by and produce separate
sub-plots. Multiple columns are concatenated with \code{split_by_sep}.}

\item{split_by_sep}{A character string to separate concatenated
\code{split_by} columns. Default \code{"_"}.}

\item{label_by}{A character string specifying the column whose values
are used as label text. When \code{NULL} (default), row names of the
data frame are used.}

\item{x_cutoff_name}{A character string for the x-cutoff legend entry.
When \code{"none"}, the legend for the x-cutoff line is suppressed
entirely (the line is still drawn). When \code{NULL} (default), a
label of the form \code{"<x> = +/-<value>"} is generated.}

\item{y_cutoff_name}{A character string for the y-cutoff legend entry.
When \code{"none"}, the legend for the y-cutoff line is suppressed
entirely (the line is still drawn). When \code{NULL} (default), a
label of the form \code{"<ylab> = <value>"} is generated.}

\item{x_cutoff_color}{A character string specifying the colour of the
x-axis cutoff line(s). Default: \code{"red2"}.}

\item{y_cutoff_color}{A character string specifying the colour of the
y-axis cutoff line(s). Default: \code{"blue2"}.}

\item{x_cutoff_linetype}{A character string specifying the linetype of
the x-axis cutoff line(s). Default: \code{"dashed"}.}

\item{y_cutoff_linetype}{A character string specifying the linetype of
the y-axis cutoff line(s). Default: \code{"dashed"}.}

\item{x_cutoff_linewidth}{A numeric value specifying the linewidth of
the x-axis cutoff line(s). Default: \code{0.5}.}

\item{y_cutoff_linewidth}{A numeric value specifying the linewidth of
the y-axis cutoff line(s). Default: \code{0.5}.}

\item{pt_size}{A numeric value specifying the point size for all data
points. Default: \code{2}.}

\item{pt_alpha}{A numeric value in \code{[0, 1]} specifying the
transparency of all data points. Default: \code{0.5}.}

\item{pt_shape}{A numeric value specifying the point shape. Default: \code{21}
(filled circle with border). Shapes 21--25 support separate fill and border
colour aesthetics; all other shapes use a single colour aesthetic. In
raster mode, all points are drawn as filled circles (shape is ignored).}

\item{pt_border_color}{Controls the point border colour. For shapes 21--25:
\itemize{
\item \code{TRUE} (default) -- border colour tracks the \code{color_by}
gradient / palette.
\item A colour string (e.g. \code{"black"}) -- constant colour border.
}
\code{FALSE} or \code{NULL} disables the border. For shapes without a fill
aesthetic (not 21--25), this parameter has no effect. In raster mode the
border is drawn as a slightly larger disc behind each point (the shape is
always a circle there), and \code{TRUE} falls back to a border disc in the
\code{color_by} colour.}

\item{pt_border_size}{A numeric value specifying the point border size
(stroke width, in mm). \code{0} disables the border. Default: \code{0.5}.}

\item{nlabel}{An integer specifying the number of top features to label
automatically. Points are ranked by Euclidean distance to the origin
within each \code{sign(x)} group (and per facet level if
\code{facet_by} is set). Only non-insignificant points receive labels.
Default: \code{5}.}

\item{labels}{A character vector of row names or integer indices
specifying which points to label. Overrides automatic \code{nlabel}
selection. When \code{NULL} (default), top \code{nlabel} points are
chosen automatically.}

\item{label_size}{A numeric value specifying the font size of the
labels. Default: \code{3}.}

\item{label_fg}{A character string specifying the text colour of the
labels. Default: \code{"black"}.}

\item{label_bg}{A character string specifying the background colour of
the label boxes (passed to \code{geom_text_repel(bg.color = ...)}).
Default: \code{"white"}.}

\item{label_bg_r}{A numeric value specifying the corner radius of the
label background boxes (passed to \code{geom_text_repel(bg.r = ...)}).
Default: \code{0.1}.}

\item{highlight}{A character vector of row names or integer indices
specifying which points to highlight with an overlaid point layer in
\code{highlight_color}. When \code{NULL} (default), no highlighting is
applied.}

\item{highlight_color}{A character string specifying the colour of the
highlight points. Default: \code{"red"}.}

\item{highlight_size}{A numeric value specifying the point size of the
highlight layer. Default: \code{2}.}

\item{highlight_alpha}{A numeric value in \code{[0, 1]} specifying the
transparency of the highlight points. Default: \code{1}.}

\item{highlight_stroke}{A numeric value specifying the stroke width of
the highlight point borders. Default: \code{0.5}.}

\item{raster}{A logical value. If \code{TRUE}, points are rendered via
\code{scattermore::geom_scattermore()} for efficient rasterised plotting.
Default is \code{NULL}, which auto-enables when \code{nrow(data) > 1e3}.}

\item{raster_dpi}{A numeric vector of length 2 \verb{[x_dpi, y_dpi]} specifying the raster
resolution in pixels. Passed to \code{scattermore::geom_scattermore(pixels = ...)}.
Default is \code{c(512, 512)}. If a single value is provided it is recycled to both dimensions.}

\item{trim}{A numeric vector of length 2 specifying quantile bounds for
winsorizing the x-axis values. Values below the first quantile are
clamped to that quantile; values above the second quantile are clamped
to that quantile. Both values must be in \code{[0, 1]}. When both bounds
are nonzero and of opposite sign, they are symmetrised to the smaller
absolute value. Default: \code{c(0, 1)} (no trimming).}

\item{facet_by}{A character string specifying the column name of the data frame to facet the plot.
Otherwise, the data will be split by \code{split_by} and generate multiple plots
and combine them into one using \code{patchwork::wrap_plots}}

\item{facet_scales}{Whether to scale the axes of facets. Default is "fixed"
Other options are "free", "free_x", "free_y". See \code{ggplot2::facet_wrap}}

\item{facet_ncol}{A numeric value specifying the number of columns in the facet.
When facet_by is a single column and facet_wrap is used.}

\item{facet_nrow}{A numeric value specifying the number of rows in the facet.
When facet_by is a single column and facet_wrap is used.}

\item{facet_byrow}{A logical value indicating whether to fill the plots by row. Default is TRUE.}

\item{theme}{A character string or a theme class (i.e. ggplot2::theme_classic) specifying the theme to use.
Default is "theme_this".}

\item{theme_args}{A list of arguments to pass to the theme function.}

\item{palette}{A character string specifying the palette to use.
A named list or vector can be used to specify the palettes for different \code{split_by} values.}

\item{palcolor}{A character string specifying the color to use in the palette.
A named list can be used to specify the colors for different \code{split_by} values.
If some values are missing, the values from the palette will be used (palcolor will be NULL for those values).}

\item{palreverse}{A logical value indicating whether to reverse the palette. Default is FALSE.}

\item{title}{A character string specifying the title of the plot.
A function can be used to generate the title based on the default title.
This is useful when split_by is used and the title needs to be dynamic.}

\item{subtitle}{A character string specifying the subtitle of the plot.}

\item{xlab}{A character string specifying the x-axis label.}

\item{ylab}{A character string specifying the y-axis label.}

\item{aspect.ratio}{A numeric value specifying the aspect ratio of the plot.}

\item{legend.position}{A character string specifying the position of the legend.
if \code{waiver()}, for single groups, the legend will be "none", otherwise "right".}

\item{legend.direction}{A character string specifying the direction of the legend.}

\item{seed}{The random seed to use. Default is 8525.}

\item{combine}{Logical; when \code{TRUE} (default), returns a combined
\code{patchwork} object. When \code{FALSE}, returns a named list of
individual \code{ggplot} objects.}

\item{ncol, nrow}{Integer number of columns / rows for the combined layout
(passed to \code{\link[patchwork]{wrap_plots}}).}

\item{byrow}{Logical; fill the combined layout by row. Default
\code{TRUE} (passed to \code{\link[patchwork]{wrap_plots}}).}

\item{axes}{A character string specifying how axes should be treated
across the combined layout (passed to
\code{\link[patchwork]{wrap_plots}}).}

\item{axis_titles}{A character string specifying how axis titles should
be treated across the combined layout. Defaults to \code{axes}.}

\item{guides}{A character string specifying how guides (legends) should
be collected across panels. Default \code{"collect"} (passed to
\code{\link{combine_plots}()}).}

\item{design}{A custom layout design for the combined plot (passed to
\code{\link{combine_plots}()}).}

\item{...}{Additional arguments.}
}
\value{
A \code{ggplot} object, a \code{patchwork} object, or a named
list of \code{ggplot} objects (when \code{combine = FALSE}), each with
\code{height} and \code{width} attributes in inches.
}
\description{
Produces a volcano plot — a scatter plot that displays statistical
significance (typically -log10 adjusted p-value) on the y-axis versus
magnitude of change (log2 fold change) on the x-axis. Points are coloured
automatically by significance category (\code{"sig_pos_x"},
\code{"sig_neg_x"}, \code{"insig"}) or by a user-supplied column. The
most significant features can be labelled automatically via
\code{\link[ggrepel]{geom_text_repel}()}, and specific points can be
highlighted.

The function supports \strong{automatic labelling} of top features (by
distance to origin), \strong{mirrored layout} via
\code{flip_negatives}, \strong{x-axis trimming} to reduce the influence
of extreme values, \strong{faceting}, and \strong{splitting} into
separate sub-plots via \code{split_by} with per-split colour palette and
legend control.
}
\section{split_by Workflow}{

When \code{split_by} is provided:
\enumerate{
\item The \code{split_by} column(s) are validated via
\code{\link{check_columns}()} with \code{force_factor = TRUE} and
\code{concat_multi = TRUE} (multiple columns are concatenated
with \code{split_by_sep}).
\item The data frame is split by \code{split_by} (preserving factor
level order). If \code{split_by} is \code{NULL}, the data is
wrapped in a single-element list with name \code{"..."}.
\item Per-split \code{palette}, \code{palcolor},
\code{legend.position}, and \code{legend.direction} are resolved
via \code{\link{check_palette}()}, \code{\link{check_palcolor}()},
and \code{\link{check_legend}()}.
\item \code{\link{VolcanoPlotAtomic}()} is called for each split. If
\code{title} is a function, it receives the split level name and
can generate dynamic titles.
\item Results are combined via \code{\link{combine_plots}()} (when
\code{combine = TRUE}) or returned as a named list.
}
}

\examples{
\donttest{
set.seed(8525)
n <- 200
n_de <- 150

## Non-DE genes
fc_null <- rnorm(n - n_de, 0, 0.35)
z_null  <- rnorm(n - n_de, 0, 1)

## DE genes
fc_de <- rnorm(
  n_de,
  mean = sample(c(-1, 1), n_de, replace = TRUE),
  sd = 0.45
)

## Make significance related to effect size,
## but with substantial variation
z_de <- fc_de * rnorm(n_de, 4.5, 0.8)

avg_log2FC <- c(fc_null, fc_de)
z <- c(z_null, z_de)

p_val <- 2 * pnorm(-abs(z))
p_val_adj <- p.adjust(p_val, method = "BH")

## Shuffle genes
i <- sample(n)

data <- data.frame(
  avg_log2FC = avg_log2FC[i],
  p_val_adj = p_val_adj[i],
  gene = paste0("gene", seq_len(n))[i],
  pct_diff = rnorm(n, 0, 1),
  group = sample(LETTERS[1:2], n, replace = TRUE)
)

# --- Basic usage ---
VolcanoPlot(data, x = "avg_log2FC", y = "p_val_adj", color_by = "pct_diff",
   y_cutoff_name = "-log10(0.05)")
# --- With gene labels ---
VolcanoPlot(data, x = "avg_log2FC", y = "p_val_adj", color_by = "pct_diff",
   y_cutoff_name = "-log10(0.05)", label_by = "gene")
# --- Mirrored layout ---
VolcanoPlot(data, x = "avg_log2FC", y = "p_val_adj", y_cutoff_name = "none",
   flip_negatives = TRUE, label_by = "gene")
# --- With faceting ---
VolcanoPlot(data, x = "avg_log2FC", y = "p_val_adj", y_cutoff_name = "none",
   flip_negatives = TRUE, facet_by = "group", label_by = "gene")
# --- With splitting ---
VolcanoPlot(data, x = "avg_log2FC", y = "p_val_adj", y_cutoff_name = "none",
   flip_negatives = TRUE, split_by = "group", label_by = "gene")
# --- With highlighting ---
VolcanoPlot(data, x = "avg_log2FC", y = "p_val_adj", y_cutoff_name = "none",
   highlight = c("gene196", "gene151"), label_by = "gene")
# --- Per-split palettes ---
VolcanoPlot(data, x = "avg_log2FC", y = "p_val_adj", color_by = "pct_diff",
   y_cutoff_name = "-log10(0.05)", split_by = "group", label_by = "gene",
   palette = c(A = "Spectral", B = "PuOr"))
# Trim extreme x-values (winsorize to 40\% and 50\% quantiles), for demo purposes
VolcanoPlot(data, x = "avg_log2FC", y = "p_val_adj", color_by = "pct_diff",
   y_cutoff_name = "-log10(0.05)", trim = c(0.4, 0.5))
}
}
