% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/dimplot.R
\name{DimPlotAtomic}
\alias{DimPlotAtomic}
\title{Atomic Dimension Reduction Plot without splitting the data}
\usage{
DimPlotAtomic(
  data,
  dims = 1:2,
  group_by = NULL,
  group_by_sep = "_",
  features = NULL,
  lower_quantile = 0,
  upper_quantile = 0.99,
  lower_cutoff = NULL,
  upper_cutoff = NULL,
  pt_size = NULL,
  pt_alpha = 1,
  bg_color = "grey80",
  bg_cutoff = NULL,
  color_name = "",
  label_insitu = FALSE,
  show_stat = !identical(theme, "theme_blank"),
  label = FALSE,
  label_size = 4,
  label_fg = "white",
  label_bg = "black",
  label_bg_r = 0.1,
  label_repel = FALSE,
  label_repulsion = 20,
  label_pt_size = 1,
  label_pt_color = "black",
  label_segment_color = "black",
  order = c("as-is", "reverse", "high-top", "low-top", "random"),
  highlight = NULL,
  highlight_alpha = 1,
  highlight_size = 1,
  highlight_color = "black",
  highlight_stroke = 0.8,
  add_mark = FALSE,
  mark_type = c("hull", "ellipse", "rect", "circle"),
  mark_expand = unit(3, "mm"),
  mark_alpha = 0.1,
  mark_linetype = 1,
  stat_by = NULL,
  stat_plot_type = c("pie", "ring", "bar", "line"),
  stat_plot_size = 0.1,
  stat_palette = "Set1",
  stat_args = list(),
  graph = NULL,
  edge_size = c(0.05, 0.5),
  edge_alpha = 0.1,
  edge_color = "grey40",
  add_density = FALSE,
  density_color = "grey80",
  density_filled = FALSE,
  density_filled_palette = "Greys",
  density_filled_palcolor = NULL,
  lineages = NULL,
  lineages_trim = c(0.01, 0.99),
  lineages_span = 0.75,
  lineages_palette = "Dark2",
  lineages_palcolor = NULL,
  lineages_arrow = ggplot2::arrow(length = unit(0.1, "inches")),
  lineages_linewidth = 1,
  lineages_line_bg = "white",
  lineages_line_bg_stroke = 0.5,
  lineages_whiskers = FALSE,
  lineages_whiskers_linewidth = 0.5,
  lineages_whiskers_alpha = 0.5,
  velocity = NULL,
  velocity_plot_type = c("raw", "grid", "stream"),
  velocity_n_neighbors = NULL,
  velocity_density = 1,
  velocity_smooth = 0.5,
  velocity_scale = 1,
  velocity_min_mass = 1,
  velocity_cutoff_perc = 5,
  velocity_group_palette = "Set2",
  velocity_group_palcolor = NULL,
  arrow_angle = 20,
  arrow_color = "black",
  streamline_l = 5,
  streamline_minl = 1,
  streamline_res = 1,
  streamline_n = 15,
  arrow_alpha = 1,
  streamline_width = c(0, 0.8),
  streamline_alpha = 1,
  streamline_color = NULL,
  streamline_palette = "RdYlBu",
  streamline_palcolor = NULL,
  streamline_bg_color = "white",
  streamline_bg_stroke = 0.5,
  keep_na = FALSE,
  keep_empty = FALSE,
  facet_by = NULL,
  facet_scales = "fixed",
  facet_nrow = NULL,
  facet_ncol = NULL,
  facet_byrow = TRUE,
  title = NULL,
  subtitle = NULL,
  xlab = NULL,
  ylab = NULL,
  theme = "theme_this",
  theme_args = list(),
  aspect.ratio = 1,
  legend.position = "right",
  legend.direction = "vertical",
  raster = NULL,
  raster_dpi = c(512, 512),
  hex = FALSE,
  hex_linewidth = 0.5,
  hex_count = !is.null(group_by),
  hex_bins = 50,
  hex_binwidth = NULL,
  palette = ifelse(is.null(features), "Paired", "Spectral"),
  palcolor = NULL,
  palreverse = FALSE,
  seed = 8525,
  ...
)
}
\arguments{
\item{data}{A data frame.}

\item{dims}{A character vector of the column names to plot on the x, y (and optionally z) axes or a numeric vector
of the column indices. When 3 dimensions are provided, a 3D interactive plot is created using plotly.
Supported in 3D: group_by, features, labels, highlight, lineages, graph/network, show_stat, order.
Not supported in 3D: add_mark, stat_by, add_density, velocity, hex, facet_by, raster.}

\item{group_by}{A character string of the column name to group the data by for discrete colouring.
A character/factor column is expected. If multiple columns are provided, the columns will be concatenated with \code{group_by_sep}.}

\item{group_by_sep}{A character string to concatenate the columns in \code{group_by}, if multiple columns are provided.}

\item{features}{A character vector of the column names to plot as features (continuous colouring).
When multiple features are provided and \code{facet_by} is not set, the data is pivoted to long format and
faceted by feature name.}

\item{lower_quantile, upper_quantile}{Lower and upper quantiles for the continuous color/fill scale.
The actual cutoffs are determined by these quantiles when \code{lower_cutoff} and
\code{upper_cutoff} are \code{NULL}. Defaults: \code{lower_quantile = 0}, \code{upper_quantile = 0.99}.}

\item{lower_cutoff, upper_cutoff}{Explicit lower and upper cutoffs for the continuous color/fill scale.
When \code{NULL} (the default), the cutoffs are determined by \code{lower_quantile} and
\code{upper_quantile} via \code{\link[stats]{quantile}}. Values outside the
\code{[lower_cutoff, upper_cutoff]} range are clamped (winsorized) to the nearest cutoff value.}

\item{pt_size}{A numeric value for point size, or a character string naming a numeric column
in \code{data} to map point sizes to. If \code{NULL} (default), auto-calculated as
\code{min(3000 / nrow(data), 0.6)}. Column-name mapping only applies to 2D plots and
is ignored with a message when \code{raster = TRUE}.}

\item{pt_alpha}{A numeric value in \verb{[0, 1]} for the point transparency. Default is \code{1}.}

\item{bg_color}{A character string specifying the colour used for NA-valued points and
background context points drawn from other facets. Default is \code{"grey80"}.}

\item{bg_cutoff}{A numeric threshold. Feature values with absolute value below this
cutoff are set to \code{NA} (and therefore rendered in \code{bg_color}). Default is \code{NULL}.}

\item{color_name}{A character string used as the title for the continuous colour bar
in feature mode. Default is \code{""}.}

\item{label_insitu}{A logical value. If \code{TRUE}, the raw group names are placed at the group median
coordinates instead of numeric indices. Forces \code{label = TRUE}. Default is \code{FALSE}.}

\item{show_stat}{A logical value. If \code{TRUE} (default), the number of points per group is shown
in the legend labels and subtitle. Ignored when \code{theme = "theme_blank"}.}

\item{label}{A logical value. If \code{TRUE}, group labels (numeric indices by default, or group
names when \code{label_insitu = TRUE}) are placed at the median coordinates of each group.
Forced to \code{TRUE} when \code{label_repel} or \code{label_insitu} is set.}

\item{label_size}{A numeric value for the label text size. Passed to \code{ggrepel::geom_text_repel()}.
Default is \code{4}.}

\item{label_fg}{A character string for the label text (foreground) colour. Default is \code{"white"}.}

\item{label_bg}{A character string for the label background / outline colour. Default is \code{"black"}.}

\item{label_bg_r}{A numeric value for the background fill ratio of the label bounding box.
Passed to \code{ggrepel::geom_text_repel(bg.r = ...)}. Default is \code{0.1}.}

\item{label_repel}{A logical value. If \code{TRUE}, labels are repelled from each other with force
\code{label_repulsion}. A visible point anchor is drawn. Forces \code{label = TRUE}.}

\item{label_repulsion}{A numeric value for the repulsion force when \code{label_repel = TRUE}.
Passed to \code{ggrepel::geom_text_repel(force = ...)}. Default is \code{20}.}

\item{label_pt_size}{A numeric value for the size of the anchor point drawn when
\code{label_repel = TRUE}. Default is \code{1}.}

\item{label_pt_color}{A character string for the colour of the label anchor point. Default is \code{"black"}.}

\item{label_segment_color}{A character string for the colour of the line segment connecting
the label to the anchor. Used in non-repel mode (\code{label_repel = FALSE}) where
\code{min.segment.length = 0}. Default is \code{"black"}.}

\item{order}{A character string controlling the draw order of points:
\itemize{
\item \code{"as-is"} (default) — the row order in the data is preserved.
\item \code{"reverse"} — rows are reversed.
\item \code{"high-top"} — points with high values (last factor levels for group_by) are drawn last (on top).
\item \code{"low-top"} — points with low values (first factor levels) are drawn last.
\item \code{"random"} — rows are randomly shuffled.
}

For \code{high-top} and \code{low-top}, NA values are always plotted at the bottom.
When applied to \code{group_by}, only the draw order changes — legend colours and order
are unaffected. Within the same level, point order is preserved. For precise
control, set factor levels before plotting.
See \url{https://github.com/pwwang/scplotter/issues/29#issuecomment-3009694130} for examples.}

\item{highlight}{A specification for highlighted points:
\itemize{
\item \code{NULL} (default): no highlighting.
\item \code{TRUE}: highlight all points (adds a dark outline around every point).
\item A character string: a dplyr filter expression (e.g., \code{"clusters == 'Ductal'"}).
\item A character vector: row names to highlight.
\item A numeric vector: row indices to highlight.
}}

\item{highlight_alpha}{A numeric value in \verb{[0, 1]} for the transparency of highlighted points.
Default is \code{1}.}

\item{highlight_size}{A numeric value for the size of the inner (coloured) highlight point.
Default is \code{1}.}

\item{highlight_color}{A character string for the colour of the outer highlight ring.
Default is \code{"black"}.}

\item{highlight_stroke}{A numeric value for the thickness of the outer highlight ring (the
difference between the outer ring size and \code{highlight_size}). Default is \code{0.8}.}

\item{add_mark}{A logical value. If \code{TRUE}, group boundaries are drawn around points using
\code{ggforce} marks. Requires \code{group_by}. Only supported in 2D.}

\item{mark_type}{A character string specifying the mark shape. Options:
\code{"hull"} (convex hull, default), \code{"ellipse"}, \code{"rect"}, or \code{"circle"}.}

\item{mark_expand}{A unit value for the outward expansion of the mark boundary.
Passed to \code{ggforce::geom_mark_*(expand = ...)}. Default is \code{unit(3, "mm")}.}

\item{mark_alpha}{A numeric value in \verb{[0, 1]} for the transparency of the mark fill.
Default is \code{0.1}.}

\item{mark_linetype}{A numeric value for the line type of the mark boundary. Default is \code{1} (solid).}

\item{stat_by}{A character string naming a column used to compute per-group statistical summary
mini-plots embedded at group centroid positions. Only supported with \code{group_by} (not \code{features}).
Only supported in 2D without \code{facet_by}.}

\item{stat_plot_type}{A character string specifying the mini-plot type. Options:
\code{"pie"} (default), \code{"ring"}, \code{"bar"}, or \code{"line"}.}

\item{stat_plot_size}{A numeric value for the size of the stat mini-plot, expressed as a
fraction of the axis range. Default is \code{0.1}.}

\item{stat_args}{A list of additional arguments passed to the stat plot function
(e.g., \code{list(palette = "Set1")}). Default is \code{list(palette = "Set1")}.}

\item{graph}{A specification for network / graph edges to overlay. Sources:
\itemize{
\item A character string starting with \code{"@"} (e.g., \code{"@graph"}): extracts the attribute
named \code{"graph"} from \code{attributes(data)}.
\item A \code{Graph} object (e.g., Seurat): coerced to dense matrix via \code{as.matrix()}.
\item A \code{matrix}, \code{data.frame}, or \code{dgCMatrix}: used directly as the adjacency matrix.
\item Numeric indices or character column names: extracts columns from \code{data}.
Edges are drawn for non-zero, lower-triangle entries. Requires \code{data} to have row names
matching the matrix dimnames.
}}

\item{edge_size}{A numeric vector of length 2 specifying the range \verb{[min, max]} for
\code{scale_linewidth_continuous(range = ...)} applied to edge widths. Default is \code{c(0.05, 0.5)}.}

\item{edge_alpha}{A numeric value in \verb{[0, 1]} for the transparency of graph edges.
Default is \code{0.1}.}

\item{edge_color}{A character string for the colour of graph edges. Default is \code{"grey40"}.}

\item{add_density}{A logical value. If \code{TRUE}, a 2D density layer is overlaid. Only supported in 2D.}

\item{density_color}{A character string for the colour of the density contour lines.
Used when \code{density_filled = FALSE}. Default is \code{"grey80"}.}

\item{density_filled}{A logical value. If \code{TRUE}, the density is rendered as a filled raster
(\code{stat_density_2d(geom = "raster")}) instead of contour lines. A separate fill scale is used.}

\item{density_filled_palette}{A character string naming the palette for the filled density layer.
Default is \code{"Greys"}.}

\item{density_filled_palcolor}{A character vector of specific colours for the filled density
palette. Default is \code{NULL} (auto-resolved from \code{density_filled_palette}).}

\item{lineages}{A character vector of column names representing pseudotime / trajectory lineages.
Each column is fitted with a LOESS smooth (\verb{span = lineages_span, degree = 2}) across the
2D embedding, after trimming the top and bottom \code{lineages_trim} quantiles.
Only supported in 2D without \code{facet_by}.}

\item{lineages_trim}{A numeric vector of length 2 specifying the lower and upper quantile
thresholds \verb{[0, 1]} for trimming lineage values before LOESS fitting.
Default is \code{c(0.01, 0.99)}.}

\item{lineages_span}{A numeric value passed as \code{span} to \code{stats::loess()} controlling the
smoothness of the lineage curve. Smaller values follow the data more closely.
Default is \code{0.75}.}

\item{lineages_palette}{A character string naming the palette for lineage colours.
Default is \code{"Dark2"}.}

\item{lineages_palcolor}{A character vector of specific colours for lineage curves.
Default is \code{NULL} (auto-resolved from \code{lineages_palette}).}

\item{lineages_arrow}{A ggplot2 \code{arrow} specification applied to the end of lineage paths.
Default is \code{arrow(length = unit(0.1, "inches"))}.}

\item{lineages_linewidth}{A numeric value for the width of the lineage curve lines.
Default is \code{1}.}

\item{lineages_line_bg}{A character string for the colour of the background (wider) stroke
drawn behind each lineage curve for improved visibility. Default is \code{"white"}.}

\item{lineages_line_bg_stroke}{A numeric value for the additional width of the background
stroke relative to \code{lineages_linewidth}. The background line has total width
\code{lineages_linewidth + lineages_line_bg_stroke}. Default is \code{0.5}.}

\item{lineages_whiskers}{A logical value. If \code{TRUE}, short line segments connect the
smoothed lineage curve to the original data coordinates of the fitted points.
Default is \code{FALSE}.}

\item{lineages_whiskers_linewidth}{A numeric value for the width of the whisker lines.
Default is \code{0.5}.}

\item{lineages_whiskers_alpha}{A numeric value in \verb{[0, 1]} for the transparency of the
whisker lines. Default is \code{0.5}.}

\item{velocity}{A specification for RNA-velocity arrows. Can be:
\itemize{
\item \code{NULL} (default): no velocity overlay.
\item A character / integer vector: column names or indices in \code{data} for the velocity embedding.
\item A data frame or matrix: the velocity embedding itself (must align with \code{data} rows).
Only supported in 2D without \code{facet_by}.
}}

\item{velocity_plot_type}{A character string specifying the velocity rendering style.
Options: \code{"raw"} (arrows from embedding), \code{"grid"} (grid-based arrows), or \code{"stream"}
(streamlines). Default is \code{"raw"}.}

\item{velocity_n_neighbors}{A numeric value for the number of neighbours used in the
velocity grid computation. Default is \code{NULL} (auto).}

\item{velocity_density}{A numeric value for the velocity kernel density bandwidth.
Default is \code{1}.}

\item{velocity_smooth}{A numeric value for the velocity smoothing parameter.
Default is \code{0.5}.}

\item{velocity_scale}{A numeric value for scaling the velocity arrows. Default is \code{1}.}

\item{velocity_min_mass}{A numeric value for the minimum cell mass threshold in velocity
grid computation. Default is \code{1}.}

\item{velocity_cutoff_perc}{A numeric value for the velocity cutoff percentage.
Default is \code{5}.}

\item{velocity_group_palette}{A character string naming the palette for velocity group
colours (used in \code{"raw"} plot type). Default is \code{"Set2"}.}

\item{velocity_group_palcolor}{A character vector of specific colours for velocity groups.
Default is \code{NULL} (auto-resolved from \code{velocity_group_palette}).}

\item{arrow_angle}{A numeric value specifying the angle of the arrowheads in degrees. Applied to \code{\link[grid]{arrow}} when \code{plot_type} is \code{"raw"} or \code{"grid"}. Default is 20.}

\item{arrow_color}{A character string specifying the color of the velocity arrows. For \code{plot_type = "stream"}, this sets only the arrowhead color. Default is \code{"black"}.}

\item{streamline_l}{A numeric value specifying the integration length of the streamlines. Passed to \code{\link[metR]{geom_streamline}} as the \code{L} parameter. Default is 5.}

\item{streamline_minl}{A numeric value specifying the minimum streamline length. Shorter streamlines are not drawn. Passed to \code{\link[metR]{geom_streamline}} as the \code{min.L} parameter. Default is 1.}

\item{streamline_res}{A numeric value specifying the resolution of the streamline integration. Passed to \code{\link[metR]{geom_streamline}} as the \code{res} parameter. Default is 1.}

\item{streamline_n}{A numeric value specifying the number of streamlines to draw. Passed to \code{\link[metR]{geom_streamline}} as the \code{n} parameter. Default is 15.}

\item{arrow_alpha}{A numeric value between 0 and 1 specifying the transparency of the velocity arrows. Only used when \code{plot_type = "raw"} or \code{"grid"}; for \code{plot_type = "stream"}, use \code{streamline_alpha} instead. Default is 1.}

\item{streamline_width}{A numeric vector of length 2 specifying the range of line widths for streamlines. Passed to \code{scale_size(range = ...)}. Only used when \code{streamline_color} is \code{NULL}. Default is \code{c(0, 0.8)}.}

\item{streamline_alpha}{A numeric value between 0 and 1 specifying the transparency of the velocity streamlines. Default is 1.}

\item{streamline_color}{An optional character string specifying a fixed color for streamlines. When \code{NULL} (the default), streamlines are colored by velocity magnitude using \code{streamline_palette}.}

\item{streamline_palette}{A character string specifying the color palette for streamline velocity magnitude. Passed to \code{\link{palette_this}}. Only used when \code{streamline_color} is \code{NULL}. Default is \code{"RdYlBu"}.}

\item{streamline_palcolor}{An optional character vector of specific colors for the streamline velocity gradient. If \code{NULL}, colors are generated from \code{streamline_palette}. Default is \code{NULL}.}

\item{streamline_bg_color}{A character string specifying the background (outline) color applied to streamlines to create a stroke effect. Default is \code{"white"}.}

\item{streamline_bg_stroke}{A numeric value specifying the additional line width of the background stroke relative to the foreground streamline. Default is 0.5.}

\item{keep_na}{A logical value or a character to replace the NA values in the data.
It can also take a named list to specify different behavior for different columns.
If TRUE or NA, NA values will be replaced with NA.
If FALSE, NA values will be removed from the data before plotting.
If a character string is provided, NA values will be replaced with the provided string.
If a named vector/list is provided, the names should be the column names to apply the behavior to,
and the values should be one of TRUE, FALSE, or a character string.
Without a named vector/list, the behavior applies to categorical/character columns used on the plot,
for example, the \code{x}, \code{group_by}, \code{fill_by}, etc.}

\item{keep_empty}{One of FALSE, TRUE and "level". It can also take a named list to specify
different behavior for different columns. Without a named list, the behavior applies to the
categorical/character columns used on the plot, for example, the \code{x}, \code{group_by}, \code{fill_by}, etc.
\itemize{
\item{\code{FALSE} (default): Drop empty factor levels from the data before plotting.}
\item{\code{TRUE}: Keep empty factor levels and show them as a separate category in the plot.}
\item{\code{"level"}: Keep empty factor levels, but do not show them in the plot.
But they will be assigned colors from the palette to maintain consistency across multiple plots.
Alias: \code{levels}}
}}

\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_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_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_byrow}{A logical value indicating whether to fill the plots by row. Default is TRUE.}

\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{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{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{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) > 1e5}.}

\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{hex}{A logical value. If \code{TRUE}, points are rendered as hexagonal bins via
\code{geom_hex()} / \code{stat_summary_hex()}. Not supported with highlight.
Default is \code{FALSE}. Only supported in 2D.}

\item{hex_linewidth}{A numeric value for the width of the hexagon boundary lines.
Default is \code{0.5}.}

\item{hex_count}{A logical value. If \code{TRUE} and \code{group_by} is set, hex fill alpha
is mapped to \code{after_stat(count)} so denser bins are more opaque.
For \code{features} mode hex_count is ignored. Default is \code{!is.null(group_by)}.}

\item{hex_bins}{A numeric value for the number of hex bins along each axis.
Passed to \code{geom_hex(bins = ...)}. Default is \code{50}.}

\item{hex_binwidth}{A numeric value for the width of individual hex bins.
Passed to \code{geom_hex(binwidth = ...)}. Takes precedence over \code{hex_bins} when set.}

\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{seed}{The random seed to use. Default is 8525.}

\item{...}{Additional arguments.}
}
\value{
A ggplot object or a plotly object (when 3 dimensions are provided)
}
\description{
Core implementation for dimension reduction visualisation. This is the
internal workhorse dispatched by both \code{DimPlot()} (group-based) and
\code{FeatureDimPlot()} (continuous feature expression). It renders a 2D
scatter plot of ordination axes with extensive annotation capabilities,
and automatically delegates to \code{DimPlotAtomic3D()} for interactive 3D
plots when three \code{dims} are provided.

The function supports two primary colouring modes:
\itemize{
\item \strong{group_by} — discrete factor colouring with a legend of group levels,
optional density/statistical overlays, and group mark / label annotations.
\item \strong{features} — continuous numeric colouring with a gradient colour bar,
multi-feature faceting via \code{tidyr::pivot_longer()}, and optional cutoff
/ quantile trimming via \code{prepare_continuous_color_scale()}.
}

Additional annotation layers include: graph / network edges drawn as
segments between connected nodes, 2D density contours (filled or outline),
group marks (hull, ellipse, rect, circle via \code{ggforce}), lineage curves
(LOESS-smoothed paths with optional whiskers), velocity / RNA-velocity
arrows (raw, grid, or stream via \code{VelocityPlot()}), statistical summary
mini-plots (pie, ring, bar, line) embedded at group centroids, background
points from other facets (faded context), and group labels with repulsion
(via \code{ggrepel::geom_text_repel()}).

Rendering scales automatically: scatter points for small datasets,
\code{scattermore::geom_scattermore()} raster for \code{n > 1e5}, or hex-binned
aggregation (\code{stat_summary_hex()} / \code{geom_hex()}). Legend assembly uses
\code{cowplot::get_plot_component()} with independent guide-boxes for base
groups, lineages, velocity, and stat-by annotations — combined via
\code{rbind} / \code{cbind} and re-inserted with \code{add_grob()}.
}
\section{Architecture}{

\strong{DimPlotAtomic} executes the following steps:
\enumerate{
\item \strong{ggplot dispatch} — selects \code{gglogger::ggplot} or \code{ggplot2::ggplot}.
\item \strong{Order validation} — \code{match.arg(order)}.
\item \strong{Dimension resolution} — converts numeric indices to column names,
validates exactly 2 or 3 dims via \code{check_columns()}.
\item \strong{Column resolution} — validates \code{group_by} (force_factor, concat_multi),
\code{features}, and \code{facet_by}. Requires at least one of \code{group_by} or
\code{features}. Blocks \code{facet_by} when multiple features are present (features
themselves become facets).
\item \strong{Auto defaults} — \code{pt_size} defaults to \code{min(3000 / nrow(data), 0.6)}
when \code{NULL}. If a character string is given, it is treated as a column name
for variable point sizing (2D only, ignored in raster mode);
\code{raster} auto-enables when \code{nrow(data) > 1e5}; \code{theme_blank} suppresses
axis labels.
\item \strong{Label force-enable} — if \code{label_repel} or \code{label_insitu} is \code{TRUE},
\code{label} is forced to \code{TRUE} with a message.
\item \strong{NA / empty handling} — \code{process_keep_na_empty()} filters the data;
\code{keep_empty} values extracted for group_by and facet_by.
\item \strong{group_by preprocessing} — group values / colours resolved via
\code{palette_this()}. NA levels mapped to literal \code{"NA"} string.
\code{label_use} is constructed based on \code{label}, \code{label_insitu}, and
\code{show_stat} combinations. Facet labeller is set to \code{as_labeller()} with
per-facet N annotations when \code{show_stat = TRUE}.
\item \strong{Multi-feature pivot} — when \code{length(features) > 1}, data is pivoted
to long format via \code{tidyr::pivot_longer()} with \code{.feature} as the facet
variable and \code{.value} as the numeric column.
\item \strong{Continuous colour scale} — when \code{features} is set,
\code{prepare_continuous_color_scale()} applies quantile/cutoff trimming
and returns anchor values for the gradient.
\item \strong{Point ordering} — applies the selected \code{order} strategy (as-is,
reverse, high-top, low-top, random) by sorting or shuffling rows.
\item \strong{3D branch} — if \code{length(dims) == 3}, emits a warning for unsupported
features, optionally down-samples with stratified group sampling (when
\code{raster = TRUE}), and delegates to \code{DimPlotAtomic3D()}.
\item \strong{Group marks} (2D only, when \code{add_mark = TRUE}) — dispatches to
\code{ggforce::geom_mark_hull/ellipse/rect/circle}, with \code{new_scale_fill()}
/ \code{new_scale_color()} to isolate mark scales.
\item \strong{Graph / network} (2D only) — resolves the graph source (same logic
as 3D), melts the matrix, handles faceted data by per-facet edge
splitting, and adds \code{geom_segment(aes(linewidth = value))} with
\code{scale_linewidth_continuous()}.
\item \strong{Density overlay} (2D only) — filled (\code{stat_density_2d(geom = "raster")})
or outline (\code{geom_density_2d()}).
\item \strong{Base scales and theme} — x / y limits from data range,
\code{do_call(theme, theme_args)}, aspect ratio and legend position.
\item \strong{Background points for facet context} — for faceted plots (excluding
multi-feature auto-faceting), points from other facets are added as
faded background (raster / hex / point depending on settings).
\item \strong{Main point layer} — dispatches by rendering mode:
\itemize{
\item \emph{raster}: \code{scattermore::geom_scattermore()} with separate NA / non-NA
group layers.
\item \emph{hex}: \code{geom_hex()} (group_by with optional count alpha, or
\code{stat_summary_hex()} for features). Raises \code{has_fill = TRUE}.
\item \emph{standard}: \code{geom_point()}.
}
\item \strong{Highlight} (2D only) — resolves highlight specification (TRUE, filter
expression, row names, indices), errors on hex + highlight combo, renders
highlight points with stroke (outer ring + inner colour).
\item \strong{Colour scales} — \code{scale_color_manual()} for group_by (with
\code{keep_empty}-aware \code{breaks}/\code{limits}/\code{drop}), or
\code{scale_color_gradientn()} for features. \code{scale_fill_manual()} /
\code{scale_fill_gradientn()} added when \code{has_fill} is TRUE.
\item \strong{Base legend} — extracted via \code{cowplot::get_plot_component("guide-box-bottom")}.
\item \strong{Lineages} (2D only, no facet_by) — per-lineage LOESS fitting
(\verb{span = lineages_span, degree = 2}) with optional whiskers connecting
smoothed to raw coordinates. Rendered as \code{geom_path()} with background
stroke + foreground colour, plus \code{scale_color_manual()}. Legend extracted
as a separate guide-box.
\item \strong{Velocity} (2D only, no facet_by) — delegates to \code{VelocityPlot()} with
\code{return_layer = TRUE}. Adds \code{new_scale_color()} when the velocity layer
has its own colour scale. Legend extracted separately.
\item \strong{Stat-by mini-plots} (2D only, no facet_by, no features) — dispatches
to \code{PieChart()} / \code{RingPlot()} / \code{BarPlot()} / \code{LinePlot()} via
\code{do_call()}. Each mini-plot is rendered as \code{annotation_custom()} at the
group's median coordinates, scaled by \code{stat_plot_size * range}.
Legend extracted from the stat plot.
\item \strong{Group labels} (2D only, no features) — \code{geom_text_repel()} with
optional repulsion (\code{force = label_repulsion}) or fixed segments
(\code{force = 0}, bold, \code{min.segment.length = 0}). Labels positioned at
group median coordinates (computed per facet if applicable).
\item \strong{Legend assembly} — when additional legends exist (lineages, velocity,
stat_by), they are combined with the base legend via \code{cbind} (vertical
direction) or \code{rbind} (horizontal). The combined legend is re-inserted
via \code{add_grob(gtable, legend, legend.position)}.
\item \strong{Dimension calculation} — \code{calculate_plot_dimensions(base_height = 5.5, aspect.ratio, legend_n, legend_nchar)} sets \code{height} / \code{width} attributes.
\item \strong{Faceting} — \code{facet_plot()} is called only when no additional legends
were assembled (otherwise the combined-legend grob is returned directly).
}
}

\keyword{internal}
