Pairwise Euclidean distance matrix across multiple group-mean CIs
Source:R/plot_ci_distance_matrix.R
plot_ci_distance_matrix.RdRenders a publication-ready Euclidean distance matrix across
two or more classification images (CIs). A stage-2 consumer:
accepts a group_ci() result directly, a named numeric matrix
of pixels x n_groups, or the same named-list-of-CIs format as
plot_ci_correlogram() (per-producer matrices reduced to group
means internally).
Use this when the question is "how far apart are these CIs in
pixel space?" rather than "how do they covary?". Euclidean
distance does not share the positive-baseline issue Pearson r
has on base-subtracted CIs (see rel_dissimilarity() for the
two-condition bootstrap version of the same magnitude metric).
Usage
plot_ci_distance_matrix(
cis,
img_dims = NULL,
mask = c("none", "face", "upper_face", "lower_face"),
method = c("raw", "normalised"),
triangle = c("full", "upper", "lower"),
palette = c("viridis", "inferno", "plasma", "rocket"),
show_values = TRUE,
value_digits = NULL,
main = NULL,
file = NULL,
width = NULL,
height = NULL,
...
)Arguments
- cis
CIs to compare. The recommended form is a numeric matrix
n_pixels x n_ciswith named columns; each column is one CI (a group mean, a single producer's CI, or any mix). Build it outside the call withcbind(name = rowMeans(cis$signal_matrix), ...), or use the output ofgroup_ci()(a named matrix) directly. A named list of CIs is also accepted (vectors of lengthprod(img_dims), single-column matrices, or per-producersignal_matrixobjects fromci_from_responses_*(), which are reduced to group means internally). Names become the row / column / diagonal labels in the figure. At least two CIs are required.- img_dims
Integer
c(nrow, ncol). IfNULL, inferred fromattr(cis[[1]], "img_dims")or fromsqrt(n_pixels).- mask
One of
"none"(default),"face","upper_face", or"lower_face". Restricts the pixels included in the distance computation viamake_face_mask().- method
One of
"raw"(default; absolute Euclidean) or"normalised"(raw / sqrt(n_pixels_used)).- triangle
One of
"full"(default),"upper"(mask the lower triangle and diagonal; CI labels on the diagonal cells), or"lower".- palette
One of
"viridis"(default),"inferno","plasma", or"rocket". All four are sequential, colorblind-friendly palettes appropriate for non-negative distances.- show_values
Logical. If
TRUE(default), render the distance values inside each visible cell.- value_digits
Integer or
NULL. Decimal places for the cell labels. WhenNULL(default): 2 for raw distance, 3 for normalised distance.- main
Optional plot title.
- file
Optional output path. If
NULL(default), plots to the current open device. If a path ending in.pngor.pdf(case-insensitive), saves at 600 dpi (PNG) or as vector PDF.- width, height
Optional output dimensions in inches. Defaults size the canvas to be square and scale with the number of CIs.
- ...
Currently unused; reserved for future arguments.
Value
Invisibly, a list with distance_matrix,
distance_raw, method, n_pixels_used, mask, palette,
triangle, and file. See "Reading the result".
Reading the plot
Each cell shows the Euclidean distance between two group-mean
CIs computed across the pixels included in mask (all pixels
by default). Larger values mean the two CIs sit farther apart
in pixel space. Saturation encodes magnitude on a single-hue
sequential ramp: pale (or near-white) at distance ~ 0, deep /
dark at large distances. Numbers in each cell show the exact
distance to value_digits decimal places.
The diagonal is identically 0 (a CI's distance from itself).
With triangle = "full" it is rendered as the lightest cell.
With triangle = "upper" or triangle = "lower" the
diagonal cells are blank and carry the CI labels instead,
freeing the figure margins for paper figures.
Raw vs normalised distance
method = "raw" (default) returns the absolute Euclidean
distance, in whatever units the CIs carry. Useful for comparing
contrasts computed on the same image at the same resolution.
method = "normalised" divides by sqrt(n_pixels_used),
producing a per-pixel root-mean-square distance that is
comparable across masks and resolutions. Use this when the
question is "is contrast A more separated than contrast B"
and the two contrasts were computed under different masks (or
you want a publication number whose order of magnitude does
not balloon with image size).
Both matrices are always returned (see "Reading the result"
below); the method argument only controls which is rendered
in the figure and used for cell labels.
Reading the result
The function returns invisibly a list with:
$distance_matrix: the n x n distance matrix actually rendered (raw or normalised permethod). Rows and columns are named with the CI names.$distance_raw: the raw distance matrix (always; useful for downstream MDS /hclust()regardless of which the figure showed).$method,$n_pixels_used,$mask,$palette,$triangle,$file: bookkeeping.
See also
plot_ci_correlogram() for the Pearson-r version of
the same input format; rel_dissimilarity() for a
two-condition Euclidean distance with bootstrap CI;
plot_ci_mds() to project multiple CIs into a 2D MDS scatter
using the same distance matrix.
Examples
if (FALSE) { # \dontrun{
# Minimal: synthetic CIs to see the function's call signature
# and inspect the output shape.
set.seed(1)
n_pix <- 32L * 32L
ci_list <- list(
A = rnorm(n_pix),
B = rnorm(n_pix) + 0.3,
C = rnorm(n_pix) - 0.2,
D = rnorm(n_pix) + 0.5
)
out <- plot_ci_distance_matrix(ci_list, img_dims = c(32L, 32L))
# The distance matrix (named numeric matrix):
out$distance_matrix
# Raw distance is always returned, even if `method = "normalised"`:
out$distance_raw
} # }
if (FALSE) { # \dontrun{
# Realistic: simulate three conditions with planted signals in
# different face regions, build CIs, then compare in distance space.
sim_eyes <- simulate_briefrc_data(
n_per_condition = 20, n_trials = 60, conditions = "eyes",
signal_region = "eyes", signal_strength = "strong", seed = 1
)
sim_mouth <- simulate_briefrc_data(
n_per_condition = 20, n_trials = 60, conditions = "mouth",
signal_region = "mouth", signal_strength = "strong", seed = 2
)
sim_nose <- simulate_briefrc_data(
n_per_condition = 20, n_trials = 60, conditions = "nose",
signal_region = "nose", signal_strength = "strong", seed = 3
)
cis_eyes <- ci_from_responses_briefrc(sim_eyes$data,
noise_matrix = sim_eyes$noise_matrix)
cis_mouth <- ci_from_responses_briefrc(sim_mouth$data,
noise_matrix = sim_mouth$noise_matrix)
cis_nose <- ci_from_responses_briefrc(sim_nose$data,
noise_matrix = sim_nose$noise_matrix)
plot_ci_distance_matrix(
list("Eyes" = cis_eyes$signal_matrix,
"Mouth" = cis_mouth$signal_matrix,
"Nose" = cis_nose$signal_matrix),
mask = "face",
method = "normalised", # comparable across masks / resolutions
triangle = "upper",
file = "ci_distance_matrix.pdf"
)
} # }