% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot-mcml.R
\name{plot_mcml}
\alias{plot_mcml}
\title{Plot Multi-Cluster Multi-Layer Network}
\usage{
plot_mcml(
  x,
  cluster_list = NULL,
  mode = c("weights", "tna"),
  theme = c("classic", "rich", "light"),
  layer_spacing = NULL,
  spacing = 3,
  shape_size = 1.2,
  summary_size = 4,
  skew_angle = 60,
  aggregation = c("sum", "mean", "max"),
  minimum = 0,
  colors = NULL,
  legend = TRUE,
  show_labels = TRUE,
  nodes = NULL,
  label_size = NULL,
  label_abbrev = NULL,
  node_size = 2.4,
  node_shape = "circle",
  cluster_shape = "circle",
  title = NULL,
  subtitle = NULL,
  title_size = 1.2,
  subtitle_size = 0.9,
  legend_position = "right",
  legend_size = 0.7,
  legend_pt_size = 1.2,
  summary_labels = TRUE,
  summary_label_size = 0.8,
  summary_label_position = 3,
  summary_label_color = "gray20",
  summary_arrows = TRUE,
  summary_arrow_size = 0.1,
  node_donut = NULL,
  node_donut_inner_ratio = 0.55,
  summary_donut_inner_ratio = 0.6,
  summary_donut_show_value = FALSE,
  curved_edges = NULL,
  summary_curve = NULL,
  summary_pie = c("inits", "self"),
  edge_color_by = c("auto", "cluster", "sign"),
  edge_positive_color = "#2E7D32",
  edge_negative_color = "#C62828",
  between_arrows = FALSE,
  edge_width_range = c(0.3, 1.3),
  between_edge_width_range = c(0.5, 2),
  summary_edge_width_range = c(0.5, 2),
  edge_alpha = 0.35,
  between_edge_alpha = 0.6,
  summary_edge_alpha = 0.7,
  inter_layer_alpha = 0.5,
  edge_labels = FALSE,
  edge_label_size = 0.5,
  edge_label_color = "gray40",
  edge_label_digits = 2,
  summary_edge_labels = FALSE,
  summary_edge_label_size = 0.6,
  top_layer_scale = c(0.8, 0.25),
  inter_layer_gap = 0.6,
  node_radius_scale = 0.55,
  shell_alpha = 0.15,
  shell_border_width = 0.75,
  node_border_color = "gray30",
  node_border_width = 0.4,
  summary_border_color = "gray20",
  summary_border_width = 0.6,
  label_color = "gray20",
  label_position = 3,
  directed = NULL,
  ...
)
}
\arguments{
\item{x}{A weight matrix, \code{tna} object, \code{cograph_network},
\code{cluster_summary}, or \code{mcml}/\code{mcml_pc} object (the
latter from \code{Nestimate::build_mcml_pc()}, rendered undirected via
its \code{meta$directed} flag). When a \code{cluster_summary} is provided
(e.g., from \code{\link{csum}}), all aggregation has already
been performed and the \code{cluster_list}, \code{aggregation}, and
\code{nodes} parameters are ignored. See the \strong{Input Formats}
section for details.}

\item{cluster_list}{How to assign nodes to clusters. Accepts:
\itemize{
\item A \strong{named list} of character vectors — each element
contains the node names belonging to that cluster, and the list
names become the cluster labels (e.g.,
\code{list(GroupA = c("A","B"), GroupB = c("C","D"))}).
\item A \strong{string} giving a column name in the node metadata
(from a \code{cograph_network}) to use as the grouping variable.
\item \code{NULL} — attempt auto-detection from common column names
(\code{cluster}, \code{group}, etc.) in node metadata.
}
Ignored when \code{x} is a \code{cluster_summary}.}

\item{mode}{What values to display on edges:
\describe{
\item{\code{"weights"}}{(default) Shows raw aggregated edge values.
Useful when absolute magnitudes (e.g., total co-occurrences) matter.}
\item{\code{"tna"}}{Row-normalizes the summary matrix so each row
sums to 1, producing transition probabilities. Automatically enables
\code{edge_labels} and \code{summary_edge_labels} unless you
explicitly set them to \code{FALSE}.}
}}

\item{theme}{Visual preset controlling node and edge styling. One of:
\describe{
\item{\code{"classic"}}{(default) The historical look — pie-chart nodes
and straight summary edges, with thin borders and slightly larger
detail nodes.}
\item{\code{"rich"}}{Donut nodes on both layers plus curved (qgraph-style)
summary edges and splot self-loops.}
\item{\code{"light"}}{Like \code{"rich"} but with no cluster-shell
outline and a softer shell fill.}
}
The granular style arguments (\code{node_donut}, \code{curved_edges})
override the preset when supplied.}

\item{layer_spacing}{Vertical distance between the bottom and top layers.
\code{NULL} (default) auto-calculates a gap that prevents overlap based
on cluster positions and shell sizes. Increase for more vertical
separation; decrease to make the plot more compact.}

\item{spacing}{Distance from the center to each cluster's position in the
bottom layer. Larger values spread clusters farther apart. Default 3.}

\item{shape_size}{Radius of each cluster's elliptical shell in the bottom
layer. Increase when nodes overlap or shells feel cramped. Default 1.2.}

\item{summary_size}{Size of the pie-chart summary nodes in the top layer.
Controls the visual radius of each pie chart. Default 4.}

\item{skew_angle}{Perspective tilt angle in degrees (0–90). At 0 the
bottom layer is viewed from directly above (fully circular); at 90 it
collapses to a flat line. Values around 45–70 give a natural table-top
perspective. Default 60.}

\item{aggregation}{Method for collapsing individual edge weights into
between-cluster and within-cluster summaries:
\describe{
\item{\code{"sum"}}{(default) Total flow — appropriate when you care
about the volume of all transitions between clusters.}
\item{\code{"mean"}}{Average flow per node pair — useful when clusters
differ in size and you want a size-normalized comparison.}
\item{\code{"max"}}{Strongest single edge — highlights the dominant
connection between each pair of clusters.}
}
Ignored when \code{x} is a \code{cluster_summary}.}

\item{minimum}{Edge weight threshold. Edges with absolute weight below
this value are not drawn. Set to a small positive value (e.g., 0.01)
to remove visual noise from near-zero edges. Default 0 (show all).}

\item{colors}{Character vector of colors for the clusters. The first
color is applied to the first cluster, and so on. Must have length
equal to the number of clusters, or it will be recycled. When
\code{NULL} (default), colors are auto-generated from a colorblind-safe
palette.}

\item{legend}{Logical. Whether to draw a legend mapping cluster names to
colors. Default \code{TRUE}.}

\item{show_labels}{Logical. Show node labels in the bottom layer.
Default \code{TRUE}. Set to \code{FALSE} for dense networks where
labels create clutter.}

\item{nodes}{Node metadata data frame for custom display labels. Must
contain a \code{label} column whose values match the row/column names
of the weight matrix. If a \code{labels} column also exists, those
values are used as display text (e.g., full names instead of codes).
Display priority: \code{labels} column > \code{label} column.
Ignored when \code{x} is a \code{cluster_summary} or
\code{cograph_network} (which carries its own node metadata).}

\item{label_size}{Text size (\code{cex}) for bottom-layer node labels.
\code{NULL} (default) auto-scales to 0.6. Increase for readability
in publication figures; decrease for dense networks.}

\item{label_abbrev}{Controls label abbreviation to reduce overlap:
\itemize{
\item \code{NULL} — no abbreviation (show full labels).
\item An \strong{integer} — truncate labels to this many characters.
\item \code{"auto"} — adaptively abbreviates based on the total
number of nodes: more nodes triggers shorter abbreviations.
}}

\item{node_size}{Size of individual detail nodes in the bottom layer.
This controls the pie-chart radius for each node. Default 2.4.}

\item{node_shape}{Shape for detail nodes in the bottom layer. Supported
values: \code{"circle"}, \code{"square"}, \code{"diamond"},
\code{"triangle"}. Can be a single value applied to all nodes or a
character vector of length equal to the number of nodes (one shape
per node). Default \code{"circle"}.}

\item{cluster_shape}{Accepted for backward compatibility. Summary nodes
are currently drawn as pie charts, so this parameter does not change
their shape.}

\item{title}{Main plot title displayed above the figure. Default
\code{NULL} (no title).}

\item{subtitle}{Subtitle displayed below the title. Default \code{NULL}
(no subtitle).}

\item{title_size}{Text size (\code{cex.main}) for the title. Default 1.2.}

\item{subtitle_size}{Text size (\code{cex.sub}) for the subtitle.
Default 0.9.}

\item{legend_position}{Where to place the legend: \code{"right"},
\code{"left"}, \code{"top"}, \code{"bottom"}, or \code{"none"} to
suppress it entirely. Default \code{"right"}.}

\item{legend_size}{Text size (\code{cex}) for legend labels. Default 0.7.}

\item{legend_pt_size}{Point size (\code{pt.cex}) for legend symbols.
Default 1.2.}

\item{summary_labels}{Logical. Show cluster name labels next to the
summary pie-chart nodes in the top layer. Default \code{TRUE}.}

\item{summary_label_size}{Text size for summary labels. Default 0.8.}

\item{summary_label_position}{Position of summary labels relative to
nodes: 1 = below, 2 = left, 3 = above, 4 = right. Default 3 (above).}

\item{summary_label_color}{Color for summary labels. Default
\code{"gray20"}.}

\item{summary_arrows}{Logical. Draw arrowheads on summary-layer directed
edges. Default \code{TRUE}. For fully undirected networks prefer
\code{directed = FALSE}, which also suppresses these arrowheads and
draws each symmetric edge pair only once.}

\item{summary_arrow_size}{Size of arrowheads on summary edges. Default
0.10.}

\item{node_donut}{Logical or \code{NULL}. Force donut node rendering on
(\code{TRUE}) or off (\code{FALSE}), overriding \code{theme}. \code{NULL}
(default) follows the preset (donut for \code{"rich"}/\code{"light"}).}

\item{node_donut_inner_ratio}{Hole size (0–1) of the detail-node donut ring.
Default 0.55.}

\item{summary_donut_inner_ratio}{Hole size (0–1) of the top-layer summary
donut ring. Default 0.6.}

\item{summary_donut_show_value}{Logical. Print the fill proportion in the
center of each summary donut. Default \code{FALSE}.}

\item{curved_edges}{Logical or \code{NULL}. Force curved summary edges on or
off, overriding \code{theme}. \code{NULL} (default) follows the preset.}

\item{summary_curve}{Numeric or \code{NULL}. Curvature of curved summary
edges (only used when curved). \code{NULL} auto-selects (0.25 for directed,
straight for undirected).}

\item{summary_pie}{Character scalar controlling what the colored slice
of the top-layer pie chart represents. One of:
\describe{
\item{\code{"inits"}}{(default) The cluster's share of the initial
state distribution (\code{cs$macro$inits[i]}). Answers "how often
do sequences start in this cluster?" Summed across clusters the
colored slices equal 1.}
\item{\code{"self"}}{The cluster's self-retention share of
out-strength (\code{bw[i, i] / rowSums(bw)[i]}). Answers "how
sticky is this cluster — how much of its outgoing flow loops
back to itself?" Each pie is normalized independently.}
}}

\item{edge_color_by}{How to color edges on all layers:
\describe{
\item{\code{"auto"}}{(default) Color edges by their cluster when the
weights are non-negative (transition networks), but switch to
sign-based coloring automatically when any negative weight is present
(correlation / association networks).}
\item{\code{"cluster"}}{Always color edges by the source cluster's color.}
\item{\code{"sign"}}{Always color edges by weight sign — positive in
\code{edge_positive_color}, negative in \code{edge_negative_color}.}
}
Sign coloring uses each edge's absolute weight for the threshold
(\code{minimum}) and line-width scaling, so negative edges are drawn
rather than dropped.}

\item{edge_positive_color}{Color for positive-weight edges when sign
coloring is active. Default \code{"#2E7D32"} (green).}

\item{edge_negative_color}{Color for negative-weight edges when sign
coloring is active. Default \code{"#C62828"} (red).}

\item{between_arrows}{Logical. Draw arrowheads on between-cluster edges
in the bottom layer. Default \code{FALSE}.}

\item{edge_width_range}{Numeric vector \code{c(min, max)} controlling the
line-width range for \strong{within-cluster} edges in the bottom layer.
The weakest edge gets \code{min} and the strongest gets \code{max}.
Default \code{c(0.3, 1.3)}.}

\item{between_edge_width_range}{Numeric vector \code{c(min, max)} for
\strong{between-cluster} edges in the bottom layer (shell-to-shell
lines). Default \code{c(0.5, 2.0)}.}

\item{summary_edge_width_range}{Numeric vector \code{c(min, max)} for
\strong{summary} edges in the top layer. Default \code{c(0.5, 2.0)}.}

\item{edge_alpha}{Transparency (0–1) for within-cluster edges. Lower
values make these edges more subtle, keeping focus on between-cluster
structure. Default 0.35.}

\item{between_edge_alpha}{Transparency (0–1) for between-cluster edges
in the bottom layer. Default 0.6.}

\item{summary_edge_alpha}{Transparency (0–1) for summary-layer edges.
Default 0.7.}

\item{inter_layer_alpha}{Transparency (0–1) for the dashed inter-layer
lines connecting detail nodes to their summary node. Lower values make
these scaffolding lines less visually dominant. Default 0.5.}

\item{edge_labels}{Logical. Show numeric weight labels on within-cluster
edges. Default \code{FALSE} (automatically set to \code{TRUE} when
\code{mode = "tna"}).}

\item{edge_label_size}{Text size for within-cluster edge labels.
Default 0.5.}

\item{edge_label_color}{Color for within-cluster edge labels. Default
\code{"gray40"}.}

\item{edge_label_digits}{Number of decimal places for edge weight labels
on both layers. Default 2.}

\item{summary_edge_labels}{Logical. Show numeric weight labels on
summary-layer edges. Default \code{FALSE} (automatically set to
\code{TRUE} when \code{mode = "tna"}).}

\item{summary_edge_label_size}{Text size for summary edge labels.
Default 0.6.}

\item{top_layer_scale}{Numeric vector \code{c(x_scale, y_scale)}
controlling the horizontal and vertical radii of the oval on which
summary nodes are placed, as multiples of \code{spacing}. Widen with
\code{c(1.0, 0.25)} or flatten with \code{c(0.8, 0.15)} to adjust the
top-layer shape. Default \code{c(0.8, 0.25)}.}

\item{inter_layer_gap}{Vertical gap between the top of the bottom layer
and the bottom of the top layer, as a multiple of \code{spacing}.
Increase to separate the layers more. Default 0.6.}

\item{node_radius_scale}{Radius of the circle on which nodes are
arranged inside each cluster shell, as a fraction of
\code{shape_size}. Increase to push nodes outward toward the shell
border; decrease to pack them tighter. Default 0.55.}

\item{shell_alpha}{Fill transparency (0–1) for cluster shells. Higher
values make shells more opaque, giving stronger visual grouping but
potentially obscuring edges. Default 0.15.}

\item{shell_border_width}{Line width for cluster shell borders. Default
0.75 (thin). \code{theme = "light"} drops the outline entirely.}

\item{node_border_color}{Border color for detail nodes in the bottom
layer. Default \code{"gray30"}.}

\item{node_border_width}{Line width for detail-node borders in the bottom
layer. Default 0.4 (thin). Increase for heavier outlines.}

\item{summary_border_color}{Border color for summary pie-chart nodes.
Default \code{"gray20"}.}

\item{summary_border_width}{Border line width for summary nodes.
Default 0.6 (thin).}

\item{label_color}{Text color for detail node labels. Default
\code{"gray20"}.}

\item{label_position}{Accepted for backward compatibility. Detail labels
are currently positioned automatically to the left or right of each node.}

\item{directed}{Logical or \code{NULL}. \code{NULL} (default)
auto-detects: a \code{cluster_summary}/\code{mcml} input uses its own
\code{$meta$directed} flag; other objects use their \code{$directed}
field when present; a plain matrix is undirected when symmetric (the
same contract as \code{\link{splot}}). When \code{TRUE}, every
non-zero cell of the weight matrices is drawn as a directed edge with
an arrowhead. When \code{FALSE} (undirected, e.g. co-occurrence
weights): arrowheads are suppressed on all three edge layers
(within-cluster, between-cluster, and summary), each symmetric pair is
drawn once instead of twice (the upper triangle is used; a warning is
issued if the weights are not symmetric), edge labels move to the edge
midpoint, and matrix input is aggregated with
\code{type = "cooccurrence"} (symmetrized counts) instead of the
row-normalized \code{type = "tna"}. Overrides \code{summary_arrows}
and \code{between_arrows}.}

\item{...}{Additional arguments (currently unused).}
}
\value{
Invisibly returns the \code{cluster_summary} object used for
plotting. This object can be passed back to \code{plot_mcml()} to
avoid recomputation, inspected with \code{print()}, or fed to
\code{\link{as_tna}} for further analysis.
}
\description{
Produces a two-layer hierarchical visualization of a clustered network.
The \strong{bottom layer} shows every node arranged inside elliptical cluster
shells with full within-cluster and between-cluster edges drawn at the
individual-node level. The \strong{top layer} collapses each cluster into a
single summary pie-chart node whose colored slice represents, by default,
the cluster's share of the initial state distribution (see
\code{summary_pie} for the alternative self-retention interpretation),
with edges carrying the aggregated between-cluster weights. Dashed
inter-layer lines connect each detail node to its corresponding summary
node, making the hierarchical mapping explicit.
}
\details{
Use \code{plot_mcml} when you need a simultaneous micro/macro view of
cluster structure — the bottom layer reveals internal cluster dynamics while
the top layer provides a bird's-eye summary. For a flat multi-cluster plot
without the summary layer, see \code{\link{plot_mtna}}. For stacked
multilevel/multiplex layers, see \code{\link{plot_mlna}}.

\strong{Two workflows:}
\enumerate{
\item \strong{Direct}: pass a weight matrix (or tna / cograph_network
object) together with \code{cluster_list}. The function calls
\code{\link{csum}} internally to compute aggregated weights.
\item \strong{Pre-computed}: call \code{\link{csum}} yourself,
inspect or modify the result, then pass the \code{cluster_summary}
object as \code{x}. This avoids redundant computation when you plot
the same clustering repeatedly with different visual settings.
}

\strong{Mode:}
\itemize{
\item \code{"weights"} (default) — displays raw aggregated edge values.
Use this when the absolute magnitude of transitions matters.
\item \code{"tna"} — row-normalizes the summary matrix to transition
probabilities (rows sum to 1) and automatically enables edge labels
on both layers (unless you explicitly set \code{edge_labels} or
\code{summary_edge_labels} to \code{FALSE}).
}

\strong{Directionality:}
\code{directed = NULL} (default) auto-detects directedness from the
input: \code{cluster_summary}/\code{mcml} objects carry it in
\code{$meta$directed}, and plain matrices are treated as undirected when
symmetric. Directed edges get arrowheads; undirected weights (e.g.,
co-occurrence aggregations) are drawn as a single plain line per
symmetric pair on every layer, with no arrowheads. Pass
\code{directed = TRUE}/\code{FALSE} to override the detection.

\strong{Layout logic:}
Bottom-layer clusters are arranged on a circle of radius \code{spacing},
flattened by the perspective \code{skew_angle}. Nodes inside each cluster
sit on a smaller circle of radius \code{shape_size * node_radius_scale}.
The top-layer summary nodes are placed on an oval above the bottom layer
whose proportions are controlled by \code{top_layer_scale}.
}
\section{Input Formats}{

\code{x} accepts four types:
\describe{
\item{\strong{matrix}}{A square numeric weight matrix with row/column
names matching the node identifiers in \code{cluster_list}.}
\item{\strong{tna}}{A TNA model object. The \code{$weights} matrix is
extracted automatically.}
\item{\strong{cograph_network}}{A cograph network object. Weights are
extracted via \code{to_matrix()} and node metadata (display labels)
is read from the \code{$nodes} data frame.}
\item{\strong{cluster_summary}}{A pre-computed summary from
\code{\link{csum}}. When this type is passed, the
\code{cluster_list}, \code{aggregation}, and \code{nodes} parameters
are ignored because the summary already contains everything needed.}
}
}

\section{Edge Types}{

The plot contains four distinct edge categories, each with its own set
of visual parameters:
\describe{
\item{\strong{Within-cluster (bottom)}}{Edges connecting nodes inside
the same cluster shell. Controlled by \code{edge_width_range},
\code{edge_alpha}, \code{edge_labels}, \code{edge_label_size},
\code{edge_label_color}, and \code{edge_label_digits}.}
\item{\strong{Between-cluster (bottom)}}{Edges from one cluster shell
to another, drawn between shell borders. Controlled by
\code{between_edge_width_range} and \code{between_edge_alpha}.}
\item{\strong{Summary (top)}}{Edges between summary pie-chart nodes
in the top layer. Controlled by \code{summary_edge_width_range},
\code{summary_edge_alpha}, \code{summary_edge_labels},
\code{summary_edge_label_size}, \code{summary_arrows}, and
\code{summary_arrow_size}.}
\item{\strong{Inter-layer (dashed)}}{Dashed lines connecting each
detail node to its cluster's summary node. Controlled by
\code{inter_layer_alpha}.}
}
}

\section{Customization Quick Reference}{

\tabular{ll}{
\strong{Visual element}       \tab \strong{Key parameters} \cr
Cluster spacing / perspective  \tab \code{spacing}, \code{skew_angle} \cr
Cluster shell appearance       \tab \code{shape_size}, \code{shell_alpha}, \code{shell_border_width}, \code{colors} \cr
Detail nodes                   \tab \code{node_size}, \code{node_shape}, \code{node_border_color} \cr
Detail labels                  \tab \code{show_labels}, \code{label_size}, \code{label_abbrev}, \code{label_color}, \code{label_position} \cr
Summary nodes                  \tab \code{summary_size}, \code{summary_border_color}, \code{summary_border_width} \cr
Summary labels                 \tab \code{summary_labels}, \code{summary_label_size}, \code{summary_label_color}, \code{summary_label_position} \cr
Within-cluster edges           \tab \code{edge_width_range}, \code{edge_alpha}, \code{edge_labels} \cr
Between-cluster edges          \tab \code{between_edge_width_range}, \code{between_edge_alpha} \cr
Summary edges                  \tab \code{summary_edge_width_range}, \code{summary_edge_alpha}, \code{summary_edge_labels}, \code{summary_arrows} \cr
Directed vs undirected         \tab \code{directed} \cr
Inter-layer lines              \tab \code{inter_layer_alpha} \cr
Top-layer layout               \tab \code{top_layer_scale}, \code{inter_layer_gap} \cr
Title / legend                 \tab \code{title}, \code{subtitle}, \code{legend}, \code{legend_position} \cr
}
}

\examples{
mat <- matrix(runif(36), 6, 6); diag(mat) <- 0
colnames(mat) <- rownames(mat) <- LETTERS[1:6]
clusters <- list(C1 = c("A","B"), C2 = c("C","D"), C3 = c("E","F"))
plot_mcml(mat, clusters)
\donttest{
cs <- csum(mat, clusters)
plot_mcml(cs, mode = "tna", edge_labels = TRUE)
}
}
\seealso{
\code{\link{csum}} for pre-computing aggregated cluster data,
\code{\link{plot_mtna}} for flat multi-cluster visualization (no summary
layer),
\code{\link{plot_mlna}} for stacked multilevel/multiplex layer
visualization,
\code{\link{aggregate_weights}} for the low-level weight aggregation
used internally,
\code{\link{detect_communities}} for algorithmic cluster detection
}
