| Title: | Spatially Constrained Clustering for Neuroimaging Data |
|---|---|
| Description: | Provides multiple algorithms for spatially constrained clustering of 3D and 4D neuroimaging data. Methods include supervoxels, SNIC (Simple Non-Iterative Clustering), SLIC (Simple Linear Iterative Clustering), slice-based minimum spanning forest, FLASH-3D with DCT compression, and adaptive correlation superclustering (ACSC). All methods balance feature similarity and spatial proximity to produce coherent brain parcellations. A unified 'cluster4d' interface standardizes access to all algorithms. |
| Authors: | Bradley Buchsbaum [aut, cre] |
| Maintainer: | Bradley Buchsbaum <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.1.0.9000 |
| Built: | 2026-10-16 17:38:48 UTC |
| Source: | https://github.com/bbuchsbaum/neurocluster |
Clusters fMRI voxels into spatially-coherent groups based on temporal correlation and spatial proximity. Includes optional refinement for boundary corrections. The algorithm supports parallel processing via the future package for improved performance.
acsc( bvec, mask, block_size = 2, ann_k = 10, alpha = 0.5, correlation_metric = c("pearson", "spearman", "robust"), spatial_weighting = c("gaussian", "binary"), refine = TRUE, max_refine_iter = 5, K = NULL, knn_proj_dim = 0L, knn_proj_method = c("none", "dct", "rp"), knn_proj_seed = 1L )acsc( bvec, mask, block_size = 2, ann_k = 10, alpha = 0.5, correlation_metric = c("pearson", "spearman", "robust"), spatial_weighting = c("gaussian", "binary"), refine = TRUE, max_refine_iter = 5, K = NULL, knn_proj_dim = 0L, knn_proj_method = c("none", "dct", "rp"), knn_proj_seed = 1L )
bvec |
A NeuroVec-like object containing 4D fMRI data. |
mask |
A NeuroVol-like object (logical or numeric mask). |
block_size |
Approximate side length of blocks (e.g., 2 or 3). Must be > 0. |
ann_k |
Number of approximate (or exact) nearest neighbors per block. Must be >= 1. |
alpha |
Feature-similarity weight in |
correlation_metric |
Similarity definition: Pearson correlation, Spearman correlation of average ranks, or robust biweight midcorrelation with tuning constant 9. |
spatial_weighting |
Spatial adjacency weighting ("gaussian", "binary"). |
refine |
Logical; whether to refine boundaries. |
max_refine_iter |
Maximum iterations for boundary refinement. Must be >= 0. |
K |
(Optional) Desired number of clusters. |
knn_proj_dim |
Optional integer; if > 0, project block summaries to this
dimension before kNN graph construction (speeds up |
knn_proj_method |
Projection method for |
knn_proj_seed |
Integer seed used when |
ACSC builds feature-neighbor edges from the declared correlation metric and
unions them with six-neighbor block-grid edges. Edge correlations are mapped
to non-negative Louvain similarities as (correlation + 1) / 2. At
alpha = 0, feature-neighbor selection is bypassed entirely, so the graph
topology and weights depend only on spatial adjacency. Optional DCT or random
projection changes feature-neighbor candidate selection, but edge weights are
always recomputed using the declared metric. Louvain calls use a fixed
internal seed and restore the caller's RNG state, so identical ACSC inputs
produce the same partition independently of the surrounding random stream.
Boundary refinement uses the same metric representation as graph building. Pearson uses centered unit vectors, Spearman uses centered average ranks, and robust mode uses median-centered Tukey-bisquare residuals. The C++ path accelerates centroid dot products and recomputes the active boundary after every synchronous pass; failures fall back to the equivalent R path.
After refinement, labels are flood-filled into connected components. If K
is supplied, the shared adjacency-preserving exact-K engine merges or splits
those components and fails closed when the target is topologically infeasible.
A standardized cluster4d_result (also classed acsc_result) with
final contiguous labels, original-space centers, physical coordinate
centers, provenance, and these ACSC-specific elements:
3D array with cluster labels per voxel.
An igraph object used for clustering.
Initial coarse partition (3D array) matching mask dimensions.
Diagnostic function to detect whether cluster IDs are spatially ordered along any axis. Useful for identifying clustering algorithms that may produce ordered IDs.
check_cluster_ordering(cluster_result)check_cluster_ordering(cluster_result)
cluster_result |
A clustering result object with |
A list with correlation statistics:
cor_x: Spearman correlation between cluster ID and x-coordinate
cor_y: Spearman correlation between cluster ID and y-coordinate
cor_z: Spearman correlation between cluster ID and z-coordinate
max_abs_cor: Maximum absolute correlation across all axes
is_ordered: Logical indicating if any axis shows strong ordering (|r| > 0.3)
## Not run: result <- cluster4d(vec, mask, K = 100, method = "flash3d") # Check for ordering ordering <- check_cluster_ordering(result) print(ordering) # If strongly ordered, randomize if (ordering$is_ordered) { result <- randomize_cluster_ids(result) } ## End(Not run)## Not run: result <- cluster4d(vec, mask, K = 100, method = "flash3d") # Check for ordering ordering <- check_cluster_ordering(result) print(ordering) # If strongly ordered, randomize if (ordering$is_ordered) { result <- randomize_cluster_ids(result) } ## End(Not run)
This function extracts the cluster class identifiers from a cluster result object.
It is a method for the cl_class_ids generic from the clue package.
## S3 method for class 'cluster_result' cl_class_ids(x)## S3 method for class 'cluster_result' cl_class_ids(x)
x |
A |
An integer vector of cluster assignments, one for each data point.
cl_class_ids for the generic function.
Computes partition, within-cluster temporal, and physical spatial estimands from final voxel labels. Temporal coherence is the mean Pearson correlation over all unordered within-cluster voxel pairs. Spatial dispersion is the root mean squared Euclidean distance from each voxel coordinate to its final cluster centroid; lower values are more compact.
cluster_metrics(result, feature_mat = NULL, coords = NULL, truth = NULL)cluster_metrics(result, feature_mat = NULL, coords = NULL, truth = NULL)
result |
A |
feature_mat |
Optional finite numeric matrix with voxels in rows and at least two time/features in columns. A transposed matrix is accepted when only its columns match the number of labels. Every row must be non-constant for Pearson correlation. |
coords |
Optional finite numeric matrix with voxels in rows and spatial
dimensions in columns. When omitted for a canonical |
truth |
Optional partition labels over exactly the same voxels. |
A named list. Always contains n_clusters and size_summary.
With truth, it adds adjusted Rand, variation of information in bits, and
pairwise Dice. With feature_mat, it adds
temporal_pairwise_correlation. With coordinates, it adds
spatial_rms_distance_mm (or spatial_rms_distance when explicit
coordinates are not declared to be millimetres by a canonical result).
Performs spatially-constrained clustering on 4D neuroimaging data using various algorithms. This is the main entry point for all clustering methods in the neurocluster package.
cluster4d( vec, mask, n_clusters = 100, method = c("supervoxels", "snic", "slic", "corr_slic", "brs_slic", "slice_msf", "flash3d", "g3s", "rena", "rena_plus", "mcl", "acsc", "commute"), spatial_weight = 0.5, max_iterations = NULL, connectivity = NULL, parallel = TRUE, verbose = FALSE, ... )cluster4d( vec, mask, n_clusters = 100, method = c("supervoxels", "snic", "slic", "corr_slic", "brs_slic", "slice_msf", "flash3d", "g3s", "rena", "rena_plus", "mcl", "acsc", "commute"), spatial_weight = 0.5, max_iterations = NULL, connectivity = NULL, parallel = TRUE, verbose = FALSE, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
method |
Clustering algorithm to use. One of the 13 values below; the order is not a performance ranking or recommendation.
|
spatial_weight |
Method-specific spatial control in
|
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
connectivity |
Integer neighborhood connectivity. Supported values are method-specific: supervoxels accepts 6, 18, 26, or 27; slic, corr_slic, brs_slic, and slice_msf accept 6 or 26; G3S, ReNA variants, and MCL accept 6, 18, or 26. It is inactive for snic, flash3d, acsc, and commute. |
parallel |
Enable parallel processing for supervoxels and slic. For all
other methods, an explicit |
verbose |
Print progress messages. Default FALSE. |
... |
Additional method-specific parameters. See method documentation for details. |
A cluster4d_result object (also inherits from cluster_result)
containing:
labels |
Contiguous positive integer final labels in mask voxel order |
cluster |
Backward-compatible alias that is identical to |
clusvol |
A |
centers |
Actual final-label means in the original feature space, with shape actual K by timepoints |
coord_centers |
Actual final-label coordinate means in physical mm, with shape actual K by 3 |
actual_k |
Actual number of clusters produced |
n_clusters |
Backward-compatible alias of |
label_ids |
Explicit mapping from center rows to contiguous label IDs |
method |
Clustering method used |
parameters |
List of all parameters used |
provenance |
Typed label, original-feature, physical-coordinate, geometry, and mask provenance |
metadata |
Method-specific additional information |
The Speed column reports single-threaded wall-clock tiers measured
with cluster4d() defaults on the neuroim2 bundled mask
(global_mask_v4.nii, 29,532 voxels), 20 timepoints of Gaussian noise
and n_clusters = 200: Fast is under 1 s,
Moderate a few seconds, and Slow tens of seconds. Timings depend on
hardware, mask size, and parameters; treat the tiers as relative guidance,
not a ranking of quality. Parallel, Iterations, and
Spatial weight state whether the common parallel,
max_iterations, and spatial_weight arguments are active.
| Method | Speed | Parallel | Iterations | Spatial weight | Notes |
| supervoxels | Moderate | Yes | Yes | Yes | Heat-kernel iterative clustering; default method |
| snic | Slow | No | No | Yes | Non-iterative; run time is dominated by k-NN gradient seeding |
| slic | Fast | Yes | Yes | Yes | Compact 4D SLIC supervoxels |
| corr_slic | Fast | No | Yes | Yes | Correlation feature distance on a random-projection embedding |
| brs_slic | Fast | No | Yes | Yes | Sketch SLIC with exact-correlation boundary refinement |
| slice_msf | Fast | No | No | Yes | Experimental; explicit evaluation only |
| flash3d | Fast | No | Yes | Yes | Hash-based low-rank superclusters |
| g3s | Fast | No | Yes | Yes | Gradient-guided geodesic supervoxels |
| rena | Fast | No | Yes | No | Balanced, topology-aware agglomeration |
| rena_plus | Fast | No | Yes | No | Edge-aware ReNA coarsening with exact Ward refinement |
| mcl | Slow | No | Yes | Yes | Picks the natural MCL partition closest to n_clusters, so actual_k can differ unless exact_k = TRUE |
| acsc | Slow | No | Yes | Yes | Correlation graph with boundary refinement |
| commute | Moderate | No | No | Yes | Commute-time spectral embedding; sparse eigensolver (eigencore) above 3,000 voxels |
For whole-brain parcellation:
n_clusters: 100-1000 depending on desired granularity
spatial_weight: 0.4-0.6 for balanced clustering
connectivity: 26 for smoother boundaries
For ROI analysis:
n_clusters: 10-100 depending on ROI size
spatial_weight: 0.2-0.4 to emphasize functional similarity
connectivity: 6 for more discrete parcels
For high-resolution data (< 2mm):
method: "flash3d" for speed; Slice-MSF remains experimental
n_clusters: Scale with voxel count (roughly n_voxels/200)
Method-specific functions: cluster4d_supervoxels,
cluster4d_snic, cluster4d_slic,
cluster4d_slice_msf, cluster4d_flash3d,
cluster4d_g3s, cluster4d_rena,
cluster4d_rena_plus, cluster4d_mcl,
cluster4d_acsc, cluster4d_commute
Legacy functions (deprecated): supervoxels, snic,
slic4d_supervoxels, slice_msf, supervoxels_flash3d
# Simple synthetic example (runs quickly) library(neuroim2) set.seed(1) mask <- NeuroVol(array(1, c(4,4,4)), NeuroSpace(c(4,4,4))) vec <- NeuroVec(array(rnorm(4*4*4*20), c(4,4,4,20)), NeuroSpace(c(4,4,4,20))) result <- cluster4d(vec, mask, n_clusters = 3, method = "g3s", max_iterations = 1) print(result$n_clusters) # More realistic examples with larger data mask <- NeuroVol(array(1, c(20,20,20)), NeuroSpace(c(20,20,20))) vec <- replicate(50, NeuroVol(array(runif(20*20*20), c(20,20,20)), NeuroSpace(c(20,20,20))), simplify=FALSE) vec <- do.call(concat, vec) # Basic usage with default supervoxels method result <- cluster4d(vec, mask, n_clusters = 100) # Fast clustering with FLASH-3D (hash-based) result <- cluster4d(vec, mask, n_clusters = 100, method = "flash3d") # Emphasize spatial compactness result <- cluster4d(vec, mask, n_clusters = 100, spatial_weight = 0.8) # Explicitly evaluate the experimental Slice-MSF method result <- cluster4d(vec, mask, n_clusters = 100, method = "slice_msf", num_runs = 3, # slice_msf-specific parameter consensus = TRUE) # Get parameter suggestions for your data n_vox <- sum(mask > 0) n_time <- dim(vec)[4] params <- suggest_cluster4d_params(n_vox, n_time, priority = "quality") result <- cluster4d(vec, mask, n_clusters = params$n_clusters, method = params$recommended_method)# Simple synthetic example (runs quickly) library(neuroim2) set.seed(1) mask <- NeuroVol(array(1, c(4,4,4)), NeuroSpace(c(4,4,4))) vec <- NeuroVec(array(rnorm(4*4*4*20), c(4,4,4,20)), NeuroSpace(c(4,4,4,20))) result <- cluster4d(vec, mask, n_clusters = 3, method = "g3s", max_iterations = 1) print(result$n_clusters) # More realistic examples with larger data mask <- NeuroVol(array(1, c(20,20,20)), NeuroSpace(c(20,20,20))) vec <- replicate(50, NeuroVol(array(runif(20*20*20), c(20,20,20)), NeuroSpace(c(20,20,20))), simplify=FALSE) vec <- do.call(concat, vec) # Basic usage with default supervoxels method result <- cluster4d(vec, mask, n_clusters = 100) # Fast clustering with FLASH-3D (hash-based) result <- cluster4d(vec, mask, n_clusters = 100, method = "flash3d") # Emphasize spatial compactness result <- cluster4d(vec, mask, n_clusters = 100, spatial_weight = 0.8) # Explicitly evaluate the experimental Slice-MSF method result <- cluster4d(vec, mask, n_clusters = 100, method = "slice_msf", num_runs = 3, # slice_msf-specific parameter consensus = TRUE) # Get parameter suggestions for your data n_vox <- sum(mask > 0) n_time <- dim(vec)[4] params <- suggest_cluster4d_params(n_vox, n_time, priority = "quality") result <- cluster4d(vec, mask, n_clusters = params$n_clusters, method = params$recommended_method)
Wrapper for Adaptive Correlation Superclustering algorithm with standardized interface. ACSC uses graph-based clustering with Louvain community detection and optional boundary refinement.
cluster4d_acsc( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 5, verbose = FALSE, block_size = 2, correlation_metric = c("pearson", "spearman", "robust"), spatial_weighting = c("gaussian", "binary"), refine = TRUE, max_refine_iter = NULL, ... )cluster4d_acsc( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 5, verbose = FALSE, block_size = 2, correlation_metric = c("pearson", "spearman", "robust"), spatial_weighting = c("gaussian", "binary"), refine = TRUE, max_refine_iter = NULL, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
verbose |
Print progress messages. Default FALSE. |
block_size |
Approximate side length of initial blocks. Default 2. |
correlation_metric |
Correlation definition used consistently for graph
construction and refinement: |
spatial_weighting |
Spatial block-edge weights: |
refine |
Logical; whether to refine boundaries. Default TRUE. |
max_refine_iter |
Maximum iterations for boundary refinement. Default 5. |
... |
Additional parameters passed to acsc |
A cluster4d_result object
Hybrid method: fast sketch-SLIC coarse assignment, then exact-correlation refinement only on boundary voxels.
cluster4d_brsslic( vec, mask, n_clusters = 100, spatial_weight = 0.05, max_iterations = 2, connectivity = 6, parallel = FALSE, verbose = FALSE, embedding_dim = 24L, sketch_repeats = 1L, coarse_alpha = NULL, boundary_passes = 1L, global_passes = 0L, refine_spatial_weight = NULL, refine_l2_weight = 0, refine_stride = NULL, seed = 1L, min_size = NULL, ... )cluster4d_brsslic( vec, mask, n_clusters = 100, spatial_weight = 0.05, max_iterations = 2, connectivity = 6, parallel = FALSE, verbose = FALSE, embedding_dim = 24L, sketch_repeats = 1L, coarse_alpha = NULL, boundary_passes = 1L, global_passes = 0L, refine_spatial_weight = NULL, refine_l2_weight = 0, refine_stride = NULL, seed = 1L, min_size = NULL, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
connectivity |
Integer neighborhood connectivity. Supported values are method-specific: supervoxels accepts 6, 18, 26, or 27; slic, corr_slic, brs_slic, and slice_msf accept 6 or 26; G3S, ReNA variants, and MCL accept 6, 18, or 26. It is inactive for snic, flash3d, acsc, and commute. |
parallel |
Enable parallel processing for supervoxels and slic. For all
other methods, an explicit |
verbose |
Print progress messages. Default FALSE. |
embedding_dim |
Embedding dimension for coarse sketch stage. |
sketch_repeats |
Number of independent sketches to average. |
coarse_alpha |
Optional backward-compatible alias for the coarse spatial
blend weight in |
boundary_passes |
Number of boundary-only refinement passes. |
global_passes |
Number of local-global refinement passes after boundary passes. |
refine_spatial_weight |
Optional spatial blend weight during exact
refinement. |
refine_l2_weight |
Optional L2 prototype penalty during boundary refinement. |
refine_stride |
Optional temporal stride for refinement (NULL = auto). |
seed |
Random seed. |
min_size |
Minimum component size for connectivity enforcement. |
... |
Reserved for future extensions. |
Both the coarse and exact-refinement spatial weights use the convex
blend (1 - w) * correlation_distance + w * scaled_spatial_distance.
refine_l2_weight is a separate optional feature penalty, so a strictly
spatial-only refinement uses refine_spatial_weight = 1 and
refine_l2_weight = 0. The hash-sketch artifact is explicitly marked as a
pre-refinement embedding under metadata$approximation$coarse_embedding.
Public centers and coordinates are final-label means in original feature and
physical coordinate spaces, respectively.
A cluster4d_result object
Wrapper for commute_cluster with standardized interface.
cluster4d_commute( vec, mask, n_clusters = 100, spatial_weight = 0.5, verbose = FALSE, ncomp = NULL, ... )cluster4d_commute( vec, mask, n_clusters = 100, spatial_weight = 0.5, verbose = FALSE, ncomp = NULL, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
verbose |
Print progress messages. Default FALSE. |
ncomp |
Number of embedding components (defaults to sqrt(2K)). |
... |
Additional method-specific parameters. See method documentation for details. |
A cluster4d_result object
Masks with more than 3,000 voxels use a sparse shift-invert
eigensolver (the required package eigencore); smaller masks use the
dense eigen() path. Pass eigen_solver (see
commute_cluster) to choose explicitly.
Wrapper for a correlation-first SLIC variant that builds a compact random projection embedding of voxel time series, then runs local 3D SLIC updates.
cluster4d_corrslic( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 6, connectivity = 6, parallel = FALSE, verbose = FALSE, embedding_dim = 64L, adaptive_embedding = FALSE, embedding_basis = c("hash", "dct"), embedding_whiten = FALSE, sketch_repeats = 1L, alpha = NULL, assign_stride = 1L, quantize_assign = FALSE, refine_exact_iters = 0L, refine_boundary_only = TRUE, refine_stride = 1L, refine_alpha = NULL, seed = 1L, min_size = NULL, ..., .input_contract = NULL )cluster4d_corrslic( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 6, connectivity = 6, parallel = FALSE, verbose = FALSE, embedding_dim = 64L, adaptive_embedding = FALSE, embedding_basis = c("hash", "dct"), embedding_whiten = FALSE, sketch_repeats = 1L, alpha = NULL, assign_stride = 1L, quantize_assign = FALSE, refine_exact_iters = 0L, refine_boundary_only = TRUE, refine_stride = 1L, refine_alpha = NULL, seed = 1L, min_size = NULL, ..., .input_contract = NULL )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
connectivity |
Integer neighborhood connectivity. Supported values are method-specific: supervoxels accepts 6, 18, 26, or 27; slic, corr_slic, brs_slic, and slice_msf accept 6 or 26; G3S, ReNA variants, and MCL accept 6, 18, or 26. It is inactive for snic, flash3d, acsc, and commute. |
parallel |
Enable parallel processing for supervoxels and slic. For all
other methods, an explicit |
verbose |
Print progress messages. Default FALSE. |
embedding_dim |
Embedding dimension used to approximate correlations.
Use |
adaptive_embedding |
Logical; if TRUE, choose embedding dimension from data size and time length. |
embedding_basis |
Embedding basis, either |
embedding_whiten |
Logical; if TRUE, whiten embedding dimensions across voxels. |
sketch_repeats |
Number of independent hash sketches combined per voxel. |
alpha |
Optional backward-compatible alias for the spatial blend weight.
It must be in |
assign_stride |
Assignment subsampling stride for coarse updates. 1 disables subsampling; values > 1 process one z-slice phase per iteration followed by a final full assignment pass. |
quantize_assign |
Logical; if TRUE, quantize embeddings and centroid features to int8 during assignment for faster dot-product distance checks. |
refine_exact_iters |
Number of exact-correlation refinement passes after coarse embedding-SLIC iterations. |
refine_boundary_only |
Logical; if TRUE, exact refinement is restricted to boundary voxels each pass. |
refine_stride |
Time-axis subsampling stride for exact refinement.
Values > 1 speed up refinement by computing correlations on every
|
refine_alpha |
Optional spatial blend weight for exact refinement. If
|
seed |
Random seed for embedding hash and seed initialization. |
min_size |
Minimum component size for connectivity enforcement. |
... |
Additional arguments (currently unused; reserved for forward compatibility). |
.input_contract |
Internal prevalidated input receipt used by
|
spatial_weight (or its alias alpha) is a convex blend:
(1 - w) * correlation_distance + w * scaled_spatial_distance.
Coarse correlation is approximated by a hash or DCT sketch. Assignment may
additionally use int8 quantization or z-plane subsampling; exact refinement
may use a temporal stride. These choices and their stage are recorded under
metadata$approximation. The public centers are always recomputed from the
final labels in the original time-series space; sketch centers are separately
typed metadata and are never substituted for them.
A cluster4d_result object
Wrapper for FLASH-3D algorithm with standardized interface.
cluster4d_flash3d( vec, mask, n_clusters = 100, spatial_weight = 0.25, max_iterations = 4, verbose = FALSE, lambda_t = NULL, bits = 64, dctM = 16, ... )cluster4d_flash3d( vec, mask, n_clusters = 100, spatial_weight = 0.25, max_iterations = 4, verbose = FALSE, lambda_t = NULL, bits = 64, dctM = 16, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
verbose |
Print progress messages. Default FALSE. |
lambda_t |
Optional finite non-negative temporal weight for Hamming
distance. When omitted, it is |
bits |
Hash length (64 or 128) |
dctM |
Number of DCT coefficients |
... |
Additional parameters passed to supervoxels_flash3d |
A cluster4d_result object
Compresses voxel features, selects low-gradient seeds, and assigns voxels by
deterministic multi-source Dijkstra propagation. Edges are exactly the
requested masked-grid neighbors; excluded gaps are never bridged. The edge
objective is alpha * feature_distance + (1 - alpha) * physical_distance / compactness.
cluster4d_g3s( vec, mask, K = 100, n_components = 15, variance_threshold = 0.95, alpha = 0.5, compactness = NULL, max_refinement_iter = 3, verbose = FALSE, use_irlba = TRUE, use_rsvd = TRUE, connectivity = 26 )cluster4d_g3s( vec, mask, K = 100, n_components = 15, variance_threshold = 0.95, alpha = 0.5, compactness = NULL, max_refinement_iter = 3, verbose = FALSE, use_irlba = TRUE, use_rsvd = TRUE, connectivity = 26 )
vec |
A |
mask |
A |
K |
Positive requested cluster count. |
n_components |
Requested SVD feature count. |
variance_threshold |
Minimum retained variance in |
alpha |
Feature-distance weight in |
compactness |
Positive finite physical length scale. Smaller values impose a stronger spatial penalty. The default uses masked voxel measure, K, and the effective dimension, so single-slice masks remain well-defined. |
max_refinement_iter |
Non-negative number of boundary passes. Refinement uses the same feature/spatial mixture and final labels are repaired through the shared adjacency-preserving exact-K engine. |
verbose |
Whether to report phase progress. |
use_irlba |
Whether large SVDs may use |
use_rsvd |
Whether randomized SVD may be used when available. |
connectivity |
Exact grid connectivity: 6, 18, or 26. |
A typed g3s_result and cluster4d_result with K by T centers,
physical coordinate centers, graph provenance, and physical-scale metadata.
Dijkstra, E. W. (1959). A note on two problems in connexion with graphs. Numerische Mathematik, 1, 269-271.
Builds a sparse voxel graph, runs an MCL flow process, and maps attractors to cluster labels. The implementation is optimized for sparse neuroimaging graphs.
cluster4d_mcl( vec, mask, n_clusters = 100, spatial_weight = 0.2, max_iterations = 8, connectivity = 6, verbose = FALSE, inflation = 1.6, expansion = 2L, loop_weight = 1, prune_k = NULL, prune_threshold = 1e-06, tol = 1e-04, feature_metric = c("correlation", "euclidean"), feature_sigma = NULL, spatial_sigma = NULL, exact_k = FALSE )cluster4d_mcl( vec, mask, n_clusters = 100, spatial_weight = 0.2, max_iterations = 8, connectivity = 6, verbose = FALSE, inflation = 1.6, expansion = 2L, loop_weight = 1, prune_k = NULL, prune_threshold = 1e-06, tol = 1e-04, feature_metric = c("correlation", "euclidean"), feature_sigma = NULL, spatial_sigma = NULL, exact_k = FALSE )
vec |
A NeuroVec, SparseNeuroVec, or NeuroVol containing the features. |
mask |
A NeuroVol mask; finite values strictly greater than zero are included. |
n_clusters |
Requested cluster count. With |
spatial_weight |
Convex weight from zero through one for physical edge similarity. |
max_iterations |
Positive MCL iteration limit for each inflation candidate. |
connectivity |
Exact masked grid connectivity: 6, 18, or 26. |
verbose |
Logical; report iteration diagnostics. |
inflation |
Nominal MCL inflation parameter (>1). In natural target mode, the deterministic search evaluates this value and fixed multipliers around it. |
expansion |
MCL expansion power (integer >= 2). Default 2. |
loop_weight |
Finite non-negative self-loop weight added before normalization. |
prune_k |
Maximum nonzero entries kept per column during MCL iterations. Must be a positive integer; the default is 64 and is independent of the target K. |
prune_threshold |
Finite threshold in [0, 1). The strongest entry in every column is retained even when all entries fall below the threshold. |
tol |
Positive convergence tolerance on maximum absolute matrix delta. |
feature_metric |
Feature similarity metric: |
feature_sigma |
Optional bandwidth for euclidean heat-kernel feature similarity. |
spatial_sigma |
Optional bandwidth for spatial heat-kernel similarity. |
exact_k |
If TRUE, use the shared adjacency-preserving exact-K engine. |
Every expansion, inflation, and pruning step is checked to remain
finite, non-negative, and column stochastic. The parallel argument was
removed because this sparse Matrix implementation has no parallel backend.
Supplying it is therefore an ordinary unused-argument error rather than a
silently sequential execution.
A cluster4d_result. Metadata records natural and final K,
convergence, selected inflation, candidate search results, flow sparsity,
final normalization error, and exact-K policy.
Wrapper for ReNA algorithm with standardized cluster4d interface.
cluster4d_rena( vec, mask, n_clusters = 100, max_iterations = 50, connectivity = 26, verbose = FALSE, exact_k = TRUE, ... )cluster4d_rena( vec, mask, n_clusters = 100, max_iterations = 50, connectivity = 26, verbose = FALSE, exact_k = TRUE, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
connectivity |
Integer neighborhood connectivity. Supported values are method-specific: supervoxels accepts 6, 18, 26, or 27; slic, corr_slic, brs_slic, and slice_msf accept 6 or 26; G3S, ReNA variants, and MCL accept 6, 18, or 26. It is inactive for snic, flash3d, acsc, and commute. |
verbose |
Print progress messages. Default FALSE. |
exact_k |
Logical; if TRUE, apply edge pruning to target exactly |
... |
Additional parameters (currently unused for ReNA). ReNA has no
spatial/feature trade-off, so |
A cluster4d_result object
Cluster4d wrapper for ReNA++
cluster4d_rena_plus( vec, mask, n_clusters = 100, r = 2, lambda = 1, grad_img = NULL, connectivity = 26, max_iterations = 50, verbose = FALSE, ... )cluster4d_rena_plus( vec, mask, n_clusters = 100, r = 2, lambda = 1, grad_img = NULL, connectivity = 26, max_iterations = 50, verbose = FALSE, ... )
vec |
A |
mask |
A |
n_clusters |
Exact finite integer target number of clusters, from one through the number of included mask voxels. |
r |
Over-clustering factor for coarsening stage. |
lambda |
Gradient penalty weight. |
grad_img |
Optional gradient/intensity vector (see |
connectivity |
Integer neighborhood connectivity. Supported values are method-specific: supervoxels accepts 6, 18, 26, or 27; slic, corr_slic, brs_slic, and slice_msf accept 6 or 26; G3S, ReNA variants, and MCL accept 6, 18, or 26. It is inactive for snic, flash3d, acsc, and commute. |
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
verbose |
Print progress messages. Default FALSE. |
... |
Additional arguments passed to |
A cluster4d_result.
Wrapper for SLIC algorithm with standardized interface.
cluster4d_slic( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 10, connectivity = 26, parallel = TRUE, verbose = FALSE, preserve_k = FALSE, seed_relocate = "none", ..., .input_contract = NULL )cluster4d_slic( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 10, connectivity = 26, parallel = TRUE, verbose = FALSE, preserve_k = FALSE, seed_relocate = "none", ..., .input_contract = NULL )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
connectivity |
Integer neighborhood connectivity. Supported values are method-specific: supervoxels accepts 6, 18, 26, or 27; slic, corr_slic, brs_slic, and slice_msf accept 6 or 26; G3S, ReNA variants, and MCL accept 6, 18, or 26. It is inactive for snic, flash3d, acsc, and commute. |
parallel |
Enable parallel processing for supervoxels and slic. For all
other methods, an explicit |
verbose |
Print progress messages. Default FALSE. |
preserve_k |
Request exactly K connected clusters. Exact K is feasible only when K is at least the number of connected mask components; below that topological minimum, connectivity takes precedence and the minimum feasible cluster count is returned with a warning. |
seed_relocate |
Seed relocation method |
... |
Additional parameters passed to slic4d_supervoxels |
.input_contract |
Internal prevalidated input receipt used by
|
A cluster4d_result object
Wrapper for slice_msf algorithm with standardized interface.
Slice-MSF is experimental and is deliberately excluded from
suggest_cluster4d_params() recommendations pending release recertification.
cluster4d_slice_msf( vec, mask, n_clusters = 100, spatial_weight = 0.2, connectivity = 26, parallel = TRUE, verbose = FALSE, num_runs = 1, consensus = FALSE, stitch_z = TRUE, r = 12, gamma = 0, z_mult = 0, min_size = NULL, seed = 1L, ensemble_fraction = 0.8, ... )cluster4d_slice_msf( vec, mask, n_clusters = 100, spatial_weight = 0.2, connectivity = 26, parallel = TRUE, verbose = FALSE, num_runs = 1, consensus = FALSE, stitch_z = TRUE, r = 12, gamma = 0, z_mult = 0, min_size = NULL, seed = 1L, ensemble_fraction = 0.8, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
connectivity |
Integer neighborhood connectivity. Supported values are method-specific: supervoxels accepts 6, 18, 26, or 27; slic, corr_slic, brs_slic, and slice_msf accept 6 or 26; G3S, ReNA variants, and MCL accept 6, 18, or 26. It is inactive for snic, flash3d, acsc, and commute. |
parallel |
Enable parallel processing for supervoxels and slic. For all
other methods, an explicit |
verbose |
Print progress messages. Default FALSE. |
num_runs |
Number of independent runs |
consensus |
Use consensus fusion |
stitch_z |
Whether graph edges may cross axial slices. |
r |
Number of non-DC DCT modes. |
gamma |
Reserved compatibility parameter; must be zero. |
z_mult |
Axial DCT-sketch smoothing fraction in |
min_size |
Minimum component size after connectivity enforcement. Default NULL (auto). |
seed |
Integer seed for multi-run DCT subspaces. |
ensemble_fraction |
Candidate-pool fraction for multi-run DCT subspaces. |
... |
Additional parameters passed to slice_msf |
Unlike direct slice_msf(), this wrapper always requests exactly
n_clusters, defaults to one non-consensus run, and chooses a conservative
automatic min_size. spatial_weight maps to compactness = spatial_weight * 10 and then to FH scale 2 / (compactness + 1); it is not
a convex spatial/feature blend. Positive gamma values fail with class
slice_msf_unsupported_gamma.
A cluster4d_result object with natural/exact-K and effective-control
provenance in metadata$exact_k_repair; see slice_msf().
Wrapper for SNIC algorithm with standardized interface.
cluster4d_snic( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 100, verbose = FALSE, ... )cluster4d_snic( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 100, verbose = FALSE, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
verbose |
Print progress messages. Default FALSE. |
... |
Additional parameters passed to snic |
A cluster4d_result object
Wrapper for supervoxels algorithm with standardized interface.
cluster4d_supervoxels( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 50, connectivity = 27, parallel = TRUE, verbose = FALSE, sigma1 = 1, sigma2 = 2.5, use_gradient = TRUE, converge_thresh = 0.001, ... )cluster4d_supervoxels( vec, mask, n_clusters = 100, spatial_weight = 0.5, max_iterations = 50, connectivity = 27, parallel = TRUE, verbose = FALSE, sigma1 = 1, sigma2 = 2.5, use_gradient = TRUE, converge_thresh = 0.001, ... )
vec |
A |
mask |
A |
n_clusters |
Finite integer target number of clusters (default 100), from one through the number of included mask voxels. Note that some methods may produce slightly different numbers of clusters due to algorithmic constraints. |
spatial_weight |
Method-specific spatial control in
|
max_iterations |
Positive finite integer iteration limit for iterative
methods. It is inactive for |
connectivity |
Integer neighborhood connectivity. Supported values are method-specific: supervoxels accepts 6, 18, 26, or 27; slic, corr_slic, brs_slic, and slice_msf accept 6 or 26; G3S, ReNA variants, and MCL accept 6, 18, or 26. It is inactive for snic, flash3d, acsc, and commute. |
parallel |
Enable parallel processing for supervoxels and slic. For all
other methods, an explicit |
verbose |
Print progress messages. Default FALSE. |
sigma1 |
Bandwidth of heat kernel for features (supervoxels-specific) |
sigma2 |
Bandwidth of heat kernel for coordinates (supervoxels-specific) |
use_gradient |
Use gradient-based initialization |
converge_thresh |
Convergence threshold |
... |
Additional parameters passed to supervoxels |
A cluster4d_result object
Compares predicted cluster assignments against ground truth using multiple metrics that are invariant to cluster label permutation.
clustering_accuracy(predicted, truth)clustering_accuracy(predicted, truth)
predicted |
Integer vector of predicted cluster assignments |
truth |
Integer vector of ground truth cluster assignments |
The metrics compare the two induced equivalence relations; cluster names do not need to match. All observations are included, including a label of zero. Missing or non-finite labels are rejected rather than silently removed. Computation uses only observed contingency cells and is linear in the number of observations for singleton-heavy partitions.
Adjusted Rand Index (ARI): Measures agreement between two clusterings, adjusted for chance. ARI = 1 means perfect agreement, ARI = 0 means random, ARI < 0 means worse than random.
Variation of information (VI): The sum of the two conditional entropies, measured with base-2 logarithms. VI is zero exactly for identical partitions and increases with disagreement.
Pairwise Dice:
2 * TP / (2 * TP + FP + FN) over unordered pairs of observations,
where a positive pair is co-clustered. If both partitions contain only
singleton clusters, their pairwise Dice is defined as one.
Matched accuracy:
The greatest fraction of matched observations under a one-to-one mapping
between predicted and truth labels. It is solved exactly on the sparse
observed contingency graph. accuracy is retained as an alias for existing
callers; it is not the former greedy approximation.
A list with adjusted Rand index (ari), variation of information
in bits (variation_of_information_bits), pairwise Dice
(pairwise_dice), arithmetic normalized mutual information (nmi),
exact maximum one-to-one label-matched accuracy (matched_accuracy),
its compatibility alias accuracy, partition counts, and a
permutation-invariant perfect flag.
# Perfect clustering truth <- rep(1:3, each = 10) pred <- rep(c(2, 3, 1), each = 10) # Same clustering, different labels clustering_accuracy(pred, truth) # ARI = 1# Perfect clustering truth <- rep(1:3, each = 10) pred <- rep(c(2, 3, 1), each = 10) # Same clustering, different labels clustering_accuracy(pred, truth) # ARI = 1
Builds an explicitly declared symmetric k-nearest-neighbor graph in physical coordinate space, computes a Laplacian commute-time embedding, and applies deterministically initialized k-means.
commute_cluster( bvec, mask, K = 100, ncomp = ceiling(sqrt(K * 2)), alpha = 0.5, sigma1 = 0.73, sigma2 = 5, connectivity = 6L, weight_mode = c("binary", "heat"), bad_voxel_policy = c("error", "zero_constant"), variance_tol = 1e-09, eigen_tol = 1e-10, eigen_solver = c("auto", "dense", "sparse"), verbose = FALSE )commute_cluster( bvec, mask, K = 100, ncomp = ceiling(sqrt(K * 2)), alpha = 0.5, sigma1 = 0.73, sigma2 = 5, connectivity = 6L, weight_mode = c("binary", "heat"), bad_voxel_policy = c("error", "zero_constant"), variance_tol = 1e-09, eigen_tol = 1e-10, eigen_solver = c("auto", "dense", "sparse"), verbose = FALSE )
bvec |
A NeuroVec or SparseNeuroVec supplying voxel features. |
mask |
A NeuroVol mask. Finite values strictly greater than zero are included. |
K |
Finite integer cluster count from one through the included voxel count. |
ncomp |
Finite integer embedding dimension from one through N - 1. |
alpha |
Feature-similarity weight from zero through one. |
sigma1 |
Positive physical-distance heat-kernel bandwidth. |
sigma2 |
Positive feature-distance heat-kernel bandwidth. |
connectivity |
Number of nearest physical neighbors per directed search. The final undirected graph is the symmetric union of those directed edges; this is not masked grid adjacency and may bridge mask holes. |
weight_mode |
|
bad_voxel_policy |
|
variance_tol |
Non-negative threshold defining a constant voxel series. |
eigen_tol |
Positive tolerance for the Laplacian zero eigenspace. |
eigen_solver |
|
verbose |
Logical; print progress. |
The implementation is deterministic. RNG initialization for the
sparse eigensolver and stats::kmeans() is scoped to a fixed local seed,
after which the caller's prior RNG state (including absence of
.Random.seed) is restored
exactly. With the dense solver it forms a full Laplacian
eigendecomposition, requiring quadratic memory and cubic time, so
eigen_solver = "auto" switches to the sparse solver above 3,000
voxels. Sparse solver memory and time depend on factorization fill-in,
the requested embedding dimension, and convergence. Sparse eigenpairs
must have original-Laplacian relative residuals at most 1e-10 and
orthogonality error at most 1e-8. Residuals are scaled by
(norm(L, "I") + abs(lambda)) * norm(v, "2"). These checks and
eigencore's separate certificate at the solver tolerance are retained in
metadata$spectral$diagnostics. The sparse solver never silently falls
back to a dense solve. A full-spectrum request (ncomp = N - 1)
uses the dense solver even when eigen_solver = "sparse".
A commute_time_cluster_result with contiguous labels, K-by-T
original-space feature means, K-by-3 physical coordinate means, the N-by-ncomp
embedding, graph and spectral provenance, and explicit data-policy provenance.
Compares clustering results over exactly the same included mask voxels and physical coordinate system. Ambiguous center-based scores are not used.
compare_cluster4d( ..., metrics = c("summary", "spatial_dispersion"), feature_mat = NULL )compare_cluster4d( ..., metrics = c("summary", "spatial_dispersion"), feature_mat = NULL )
... |
cluster4d_result objects to compare |
metrics |
Character vector selecting explicit estimands:
|
feature_mat |
A shared finite numeric matrix with voxels in rows and
at least two time/features in columns. Required only for
|
Every result must carry canonical mask and affine provenance. The exact included voxel indices and physical geometry are checked before any cross-result comparison. Partition metrics use only observed contingency cells and never construct an N-by-N co-membership matrix. Pairwise agreement columns are repeated on the two result rows so the return value remains a data frame.
A data frame with one row per result and explicitly named metrics.
Reduces the dimensionality of fMRI time series data using Singular Value Decomposition (SVD) while preserving the majority of variance. This is a key component of the G3S (Gradient-Guided Geodesic Supervoxels) algorithm, enabling 10-20x speedup in similarity computations.
compress_features_svd( feature_mat, n_components = 15, variance_threshold = 0.95, use_irlba = TRUE, use_rsvd = TRUE )compress_features_svd( feature_mat, n_components = 15, variance_threshold = 0.95, use_irlba = TRUE, use_rsvd = TRUE )
feature_mat |
A numeric matrix with voxels in rows and timepoints in columns (N x T). The function will center and scale the data automatically. |
n_components |
Target number of dimensions (default: 15). Higher values preserve more variance but reduce speed gains. |
variance_threshold |
Minimum proportion of variance to preserve (0-1). If the requested n_components doesn't meet this threshold, more components will be retained. Default: 0.95 (95% variance). |
use_irlba |
Logical; if TRUE and the irlba package is available, use fast randomized SVD for large datasets (>10,000 voxels). Default: TRUE. |
use_rsvd |
Logical; if TRUE and the rsvd package is available, prefer the randomized SVD implementation from rsvd for large datasets (>10,000 voxels). This can outperform irlba on tall-and-skinny matrices. Default: TRUE. |
The compression follows these steps:
Center and scale: Each timepoint is centered (mean=0) and scaled (sd=1) to ensure equal contribution from all timepoints.
SVD decomposition: Computes X = U * D * t(V) where:
U (N x k): Left singular vectors (voxel loadings)
D (k x k): Diagonal matrix of singular values
V (T x k): Right singular vectors (time loadings)
Compression: Retains only the first M components where M is chosen to balance speed (fewer components) and accuracy (more variance explained).
Normalization: Each compressed feature vector is normalized to unit length,
enabling fast cosine similarity via dot products: cor(x, y) approx x * y
Memory: Compressed data uses M/T of original size (e.g., 15/300 = 5%)
Speed: Similarity calculations are M/T times faster (e.g., 20x for 15/300)
Accuracy: Typically preserves 95%+ of signal with M=10-20 for fMRI data
Small (M=10): Maximum speed, good for noisy or heavily smoothed data
Medium (M=15): Balanced, recommended default for most fMRI data
Large (M=25): High accuracy, use for high SNR data or critical applications
The function will automatically increase n_components if needed to meet variance_threshold. If that requires the full available rank, the exact full-rank decomposition is used.
A list with components:
features |
Compressed feature matrix (N x M), starting from the
requested |
variance_explained |
Proportion of total variance explained by the retained components (0-1). |
n_components |
Actual number of components retained (may be > n_components input if needed to meet variance_threshold). |
rotation |
The right singular vectors (V matrix) for transforming new data. |
singular_values |
The singular values (d vector) for each component. |
center |
Column means used for centering (for transforming new data). |
scale |
Column standard deviations used for scaling (for transforming new data). |
Both randomized backends draw random projections. They are run under a fixed
internal seed and the caller's RNG state is restored afterwards, so repeated
calls on the same data return the same decomposition and the function never
perturbs the surrounding stream. Without that, two identical
cluster4d_g3s runs could disagree on half their voxel labels.
cluster4d_g3s for the full G3S clustering algorithm.
transform_new_data_svd for applying the compression to new data.
# Simulate fMRI time series data n_voxels <- 1000 n_timepoints <- 300 latent <- matrix(rnorm(n_voxels * 8), n_voxels, 8) loadings <- matrix(rnorm(n_timepoints * 8), n_timepoints, 8) feature_mat <- latent %*% t(loadings) + matrix(rnorm(n_voxels * n_timepoints, sd = 0.05), n_voxels, n_timepoints) # Compress to 15 dimensions (typical for G3S) compressed <- compress_features_svd(feature_mat, n_components = 15) print(compressed$variance_explained) # At least 0.95 print(ncol(compressed$features)) # 15 here; may increase when necessary # More aggressive compression compressed_fast <- compress_features_svd(feature_mat, n_components = 10) # Conservative compression (preserve 98% variance) compressed_accurate <- compress_features_svd( feature_mat, n_components = 15, variance_threshold = 0.98 )# Simulate fMRI time series data n_voxels <- 1000 n_timepoints <- 300 latent <- matrix(rnorm(n_voxels * 8), n_voxels, 8) loadings <- matrix(rnorm(n_timepoints * 8), n_timepoints, 8) feature_mat <- latent %*% t(loadings) + matrix(rnorm(n_voxels * n_timepoints, sd = 0.05), n_voxels, n_timepoints) # Compress to 15 dimensions (typical for G3S) compressed <- compress_features_svd(feature_mat, n_components = 15) print(compressed$variance_explained) # At least 0.95 print(ncol(compressed$features)) # 15 here; may increase when necessary # More aggressive compression compressed_fast <- compress_features_svd(feature_mat, n_components = 10) # Conservative compression (preserve 98% variance) compressed_accurate <- compress_features_svd( feature_mat, n_components = 15, variance_threshold = 0.98 )
The compute_centroids function calculates the center and centroid of each cluster given a feature matrix, grid, and cluster assignments.
compute_centroids(feature_mat, grid, assignment, medoid = FALSE)compute_centroids(feature_mat, grid, assignment, medoid = FALSE)
feature_mat |
A matrix of features, where columns represent data points and rows represent features. |
grid |
A matrix representing the spatial grid of data points. |
assignment |
A vector containing the cluster assignment for each data point. |
medoid |
A logical value indicating whether to calculate medoids instead of means for cluster centers and centroids. Default is FALSE. |
A list containing two elements:
center |
A matrix containing the centers of each cluster. |
centroid |
A matrix containing the centroids of each cluster. |
# Simple synthetic example feature_mat <- matrix(rnorm(100), nrow = 10, ncol = 10) grid <- cbind(x = runif(10), y = runif(10), z = runif(10)) assignment <- rep(1:2, each = 5) centroids <- compute_centroids(feature_mat, grid, assignment) print(names(centroids)) ## Not run: # Larger example with real neuroimaging data # Assuming `feature_mat`, `grid`, and `assignment` are available centroids <- compute_centroids(feature_mat, grid, assignment) # To compute medoids instead of means medoids <- compute_centroids(feature_mat, grid, assignment, medoid=TRUE) ## End(Not run)# Simple synthetic example feature_mat <- matrix(rnorm(100), nrow = 10, ncol = 10) grid <- cbind(x = runif(10), y = runif(10), z = runif(10)) assignment <- rep(1:2, each = 5) centroids <- compute_centroids(feature_mat, grid, assignment) print(names(centroids)) ## Not run: # Larger example with real neuroimaging data # Assuming `feature_mat`, `grid`, and `assignment` are available centroids <- compute_centroids(feature_mat, grid, assignment) # To compute medoids instead of means medoids <- compute_centroids(feature_mat, grid, assignment, medoid=TRUE) ## End(Not run)
Calculates the functional gradient for each voxel as the average dissimilarity to its spatial neighbors in feature space. Low gradient values indicate stable, homogeneous regions (good seed locations); high values indicate boundaries.
compute_functional_gradient(feature_mat, coords, k_neighbors = 26)compute_functional_gradient(feature_mat, coords, k_neighbors = 26)
feature_mat |
Numeric matrix (N x M) of features (voxels x dimensions). |
coords |
Numeric matrix (N x 3) of spatial coordinates. |
k_neighbors |
Integer; number of nearest spatial neighbors to use. Default: 26. |
For each voxel i, the functional gradient is:
where are the k nearest spatial neighbors and
is the dot product (cosine similarity for unit-length vectors).
Numeric vector of length N containing gradient values for each voxel.
## Not run: features <- matrix(rnorm(500 * 15), 500, 15) features <- t(apply(features, 1, function(x) x / sqrt(sum(x^2)))) coords <- matrix(rnorm(500 * 3), 500, 3) grad <- compute_functional_gradient(features, coords, k_neighbors = 26) hist(grad, breaks = 50, main = "Functional Gradient Distribution") ## End(Not run)## Not run: features <- matrix(rnorm(500 * 15), 500, 15) features <- t(apply(features, 1, function(x) x / sqrt(sum(x^2)))) coords <- matrix(rnorm(500 * 3), 500, 3) grad <- compute_functional_gradient(features, coords, k_neighbors = 26) hist(grad, breaks = 50, main = "Functional Gradient Distribution") ## End(Not run)
Removes trends from each voxel's timeseries by projecting out a basis. Supports polynomial or DCT (discrete cosine transform) basis functions.
detrend_basis_cpp(data, basis)detrend_basis_cpp(data, basis)
data |
Numeric matrix with voxels as rows and timepoints as columns |
basis |
Orthonormal basis matrix (n_time x n_basis) to project out. Use make_dct_basis() or make_poly_basis() to generate. |
For orthonormal basis B, computes residuals as: y_detrend = y - B * (B^T * y)
This is equivalent to regressing out the basis and keeping residuals.
Numeric matrix with basis components removed from each row
## Not run: # Remove linear + quadratic trend (polynomial degree 2) basis <- make_poly_basis(n_time = 100, degree = 2) data_detrend <- detrend_basis_cpp(data, basis) # Remove low-frequency drift with DCT (first 5 components) basis <- make_dct_basis(n_time = 100, n_basis = 5) data_detrend <- detrend_basis_cpp(data, basis) ## End(Not run)## Not run: # Remove linear + quadratic trend (polynomial degree 2) basis <- make_poly_basis(n_time = 100, degree = 2) data_detrend <- detrend_basis_cpp(data, basis) # Remove low-frequency drift with DCT (first 5 components) basis <- make_dct_basis(n_time = 100, n_basis = 5) data_detrend <- detrend_basis_cpp(data, basis) ## End(Not run)
Removes low-frequency components using discrete cosine transform.
detrend_dct_cpp(data, n_basis = 4L)detrend_dct_cpp(data, n_basis = 4L)
data |
Numeric matrix with voxels as rows and timepoints as columns |
n_basis |
Number of DCT basis functions to remove (including constant). Default 4 removes constant, linear, and first two cosine harmonics. |
DCT detrending is commonly used in fMRI preprocessing. The number of basis functions controls the high-pass filter cutoff:
n_basis = 1: mean removal only
n_basis = 2: ~ linear detrend
n_basis = 4-6: typical for fMRI (removes drift < ~0.01 Hz for TR=2s)
Higher n_basis = more aggressive high-pass filtering.
Numeric matrix with low-frequency components removed
Removes polynomial trend up to specified degree from each voxel.
detrend_poly_cpp(data, degree = 1L)detrend_poly_cpp(data, degree = 1L)
data |
Numeric matrix with voxels as rows and timepoints as columns |
degree |
Polynomial degree (0 = mean, 1 = linear, 2 = quadratic, etc.) |
Convenience wrapper that generates polynomial basis and calls detrend_basis_cpp. For degree=1, this is equivalent to detrend_time_cpp but slightly slower.
Numeric matrix with polynomial trend removed
Fast removal of trends from each voxel's timeseries in 4D neuroimaging data. Supports linear, polynomial, and DCT (discrete cosine transform) detrending.
detrend_time( vec, mask = NULL, method = c("linear", "poly", "dct"), degree = 2, n_basis = 4 )detrend_time( vec, mask = NULL, method = c("linear", "poly", "dct"), degree = 2, n_basis = 4 )
vec |
A |
mask |
Optional |
method |
Detrending method: "linear" (default), "poly", or "dct" |
degree |
For method="poly", the polynomial degree (1=linear, 2=quadratic, etc.) |
n_basis |
For method="dct", number of DCT basis functions to remove. Higher values = more aggressive high-pass filtering. |
Three detrending methods are available:
Linear (method="linear"): Fastest option. Removes linear drift by fitting y = a + b*t.
Polynomial (method="poly"): Removes polynomial trend up to specified degree. degree=1 is linear, degree=2 adds quadratic, etc. Uses orthonormalized basis for stability.
DCT (method="dct"): Removes low-frequency components using discrete cosine transform basis. This is a standard high-pass filter for fMRI data. The n_basis parameter controls the cutoff:
n_basis=1: mean removal only
n_basis=2: approximately linear detrend
n_basis=4-6: typical for fMRI (removes ~0.01 Hz drift for TR=2s)
All methods use fast C++ parallel implementation via RcppParallel.
A NeuroVec with trend removed from each voxel
## Not run: vec <- neuroim2::read_vec("functional.nii.gz") # Linear detrend (fastest) vec_lin <- detrend_time(vec) # Quadratic detrend vec_quad <- detrend_time(vec, method = "poly", degree = 2) # DCT high-pass filter (common for fMRI) vec_dct <- detrend_time(vec, method = "dct", n_basis = 5) ## End(Not run)## Not run: vec <- neuroim2::read_vec("functional.nii.gz") # Linear detrend (fastest) vec_lin <- detrend_time(vec) # Quadratic detrend vec_quad <- detrend_time(vec, method = "poly", degree = 2) # DCT high-pass filter (common for fMRI) vec_dct <- detrend_time(vec, method = "dct", n_basis = 5) ## End(Not run)
Removes linear trend from each voxel's timeseries using fast parallel linear regression.
detrend_time_cpp(data)detrend_time_cpp(data)
data |
Numeric matrix with voxels as rows and timepoints as columns |
For each voxel, fits a linear model y = intercept + slope * t and subtracts the fitted values: residuals = y - fitted.
Uses RcppParallel for fast parallel computation across voxels. The linear regression is computed efficiently using precomputed time statistics.
Numeric matrix with linear trend removed from each row (voxel)
Backwards-compatible alias for rena_plus
er_ml_rena(bvec, mask, ...)er_ml_rena(bvec, mask, ...)
bvec |
A |
mask |
A |
... |
Reserved for future options. |
Same as rena_plus.
Uses the elbow method or cumulative variance to suggest an appropriate number of components for SVD compression.
estimate_optimal_components( feature_mat, max_components = 50, method = c("variance", "elbow"), variance_target = 0.95 )estimate_optimal_components( feature_mat, max_components = 50, method = c("variance", "elbow"), variance_target = 0.95 )
feature_mat |
Numeric matrix (N x T) |
max_components |
Maximum components to test (default: 50) |
method |
Either "elbow" (find elbow in scree plot) or "variance" (return number needed for 95% variance). Default: "variance". |
variance_target |
Target variance for "variance" method (default: 0.95) |
Integer; suggested number of components
## Not run: data <- matrix(rnorm(1000 * 300), 1000, 300) n_opt <- estimate_optimal_components(data) print(n_opt) ## End(Not run)## Not run: data <- matrix(rnorm(1000 * 300), 1000, 300) n_opt <- estimate_optimal_components(data) print(n_opt) ## End(Not run)
Identifies optimal seed locations for G3S clustering by finding local minima in the functional gradient field. Unlike uniform grid seeding, this approach places seeds in the centers of stable functional regions rather than on boundaries.
find_gradient_seeds_g3s( feature_mat, coords, K, k_neighbors = 26, oversample_ratio = 3, min_separation_factor = 1, distance = c("cosine", "euclidean"), knn = NULL, spatial_scale = NULL )find_gradient_seeds_g3s( feature_mat, coords, K, k_neighbors = 26, oversample_ratio = 3, min_separation_factor = 1, distance = c("cosine", "euclidean"), knn = NULL, spatial_scale = NULL )
feature_mat |
Numeric matrix (N x M) of compressed features, where each row
is a voxel and each column is a feature dimension. Should be normalized to
unit length for cosine similarity (as output by |
coords |
Numeric matrix (N x 3) of spatial coordinates for each voxel,
typically in mm units from |
K |
Integer; target number of seeds (clusters). The function may return fewer seeds if spatial separation constraints cannot be satisfied. |
k_neighbors |
Integer; number of nearest neighbors to use for gradient computation. Default: 26 (full 3D connectivity). |
oversample_ratio |
Numeric; ratio of candidates to K considered before spatial separation is applied. Default: 3. Candidates are the lowest-gradient voxels within each spatial cell rather than the globally lowest, so a flat or heavily tied gradient field cannot concentrate the whole pool in one part of the mask. |
min_separation_factor |
Numeric; starting minimum separation between seeds, as a multiple of the expected supervoxel scale. Default: 1. This is a starting point only: the radius decays until K seeds fit, so the outcome is the widest separation the mask actually admits and is insensitive to the exact starting value. |
distance |
Character; distance metric for gradient computation.
One of |
knn |
Optional pre-computed k-nearest-neighbor object. If NULL (default), KNN is computed internally. |
spatial_scale |
Optional positive physical length scale for the seed inhibition radius, normally the masked-volume scale used for compactness. When NULL the radius is estimated from the coordinate bounding box, which can overestimate it on non-convex masks. |
The seeding process follows these steps:
Functional Gradient Computation: For each voxel, compute the average dissimilarity to its k nearest spatial neighbors in feature space:
where (cosine distance).
Candidate Selection: Rank voxels by gradient value and select the top K * oversample_ratio voxels with lowest gradient (most stable regions).
Spatial Separation: Starting with the lowest-gradient candidate, greedily select seeds that maintain minimum spatial separation from all previously selected seeds. If that pool cannot provide K seeds at the physical inhibition radius, deterministic farthest-point sampling over the full mask fills the shortfall.
Traditional uniform grid seeding often places seeds on functional boundaries (high gradient regions), leading to:
Poor initial cluster centroids
Slower convergence
Less biologically plausible parcellations
Gradient-based seeding ensures:
Seeds are in functional cores (low gradient = stable, homogeneous regions)
Better initial centroids = faster, more accurate clustering
Biologically plausible: aligns with cortical organization
vs. Uniform Grid: G3S gradient seeding reduces boundary artifacts and improves convergence speed by 2-3x.
vs. K-means Initialization: G3S respects spatial structure, preventing disconnected clusters.
vs. Random Seeding: G3S is deterministic given the data, improving reproducibility.
Integer vector of length K containing the row indices of selected seed voxels in the feature_mat/coords matrices.
compute_functional_gradient for gradient computation details.
cluster4d_g3s for the full G3S clustering algorithm.
spatial_gradient for spatial-only gradient (used in SNIC).
## Not run: # Simulate compressed fMRI features n_voxels <- 1000 n_components <- 15 features <- matrix(rnorm(n_voxels * n_components), n_voxels, n_components) features <- t(apply(features, 1, function(x) x / sqrt(sum(x^2)))) # Normalize # Spatial coordinates (10x10x10 grid) coords <- as.matrix(expand.grid(x = 1:10, y = 1:10, z = 1:10)) # Find 20 seeds seeds <- find_gradient_seeds_g3s(features, coords, K = 20) print(length(seeds)) # Should be 20 or close to it # Visualize gradient values grad_vals <- compute_functional_gradient(features, coords) print(summary(grad_vals[seeds])) # Should be low values ## End(Not run)## Not run: # Simulate compressed fMRI features n_voxels <- 1000 n_components <- 15 features <- matrix(rnorm(n_voxels * n_components), n_voxels, n_components) features <- t(apply(features, 1, function(x) x / sqrt(sum(x^2)))) # Normalize # Spatial coordinates (10x10x10 grid) coords <- as.matrix(expand.grid(x = 1:10, y = 1:10, z = 1:10)) # Find 20 seeds seeds <- find_gradient_seeds_g3s(features, coords, K = 20) print(length(seeds)) # Should be 20 or close to it # Visualize gradient values grad_vals <- compute_functional_gradient(features, coords) print(summary(grad_vals[seeds])) # Should be low values ## End(Not run)
Deprecated: This function is now available as find_gradient_seeds()
in cluster4d_init.R. This version is maintained for backward compatibility.
This function finds the initial cluster centers for a supervoxel algorithm. Supervoxels are used to partition 3D image data into volumetric regions, grouping similar voxels together. The initial cluster centers are crucial for the performance and quality of the final supervoxels.
find_initial_points(cds, grad, K = 100)find_initial_points(cds, grad, K = 100)
cds |
A matrix or data frame representing the spatial coordinates of the voxels. |
grad |
A vector representing the gradient values of the voxels. |
K |
The desired number of supervoxels (clusters) in the output (default: 100). |
A list containing two elements: selected - a vector of the selected indices corresponding to the initial cluster centers, coords - a matrix or data frame with the spatial coordinates of the initial cluster centers.
find_gradient_seeds, initialize_clusters
Convenient synthetic data for examples, vignettes, and tests. Each scenario
produces a NeuroVec (time series volume), a NeuroVol mask, and the
ground-truth cluster labels so you can benchmark algorithms or build
illustrations quickly.
generate_synthetic_volume( scenario = c("gaussian_blobs", "z_layers", "checkerboard"), dims = c(16, 16, 8), n_clusters = 4, n_time = 30, spread = c(3.5, 3.5, 2), noise_sd = 0.05, amplitude_range = c(0.8, 1.2), spacing_mm = c(3, 3, 3), pattern_type = c("orthogonal", "harmonic", "random"), seed = NULL )generate_synthetic_volume( scenario = c("gaussian_blobs", "z_layers", "checkerboard"), dims = c(16, 16, 8), n_clusters = 4, n_time = 30, spread = c(3.5, 3.5, 2), noise_sd = 0.05, amplitude_range = c(0.8, 1.2), spacing_mm = c(3, 3, 3), pattern_type = c("orthogonal", "harmonic", "random"), seed = NULL )
scenario |
Pattern to embed. One of |
dims |
Integer vector of length 3 giving the spatial grid dimensions. |
n_clusters |
Number of latent clusters to embed. |
n_time |
Number of time points. |
spread |
Characteristic spread of each Gaussian blob (scalar or length 3). |
noise_sd |
Standard deviation of additive Gaussian noise. |
amplitude_range |
Range used when scaling each voxel's amplitude. |
spacing_mm |
Physical voxel size supplied to the generated |
pattern_type |
Type of temporal patterns to generate. One of
|
seed |
Optional seed for reproducibility. |
A list with elements vec, mask, truth, coords,
patterns, weights, dims, n_clusters, and scenario.
syn <- generate_synthetic_volume( scenario = "gaussian_blobs", dims = c(12, 12, 6), n_clusters = 4, seed = 1 ) str(syn) truth_vol <- array(syn$truth, syn$dims) clusvol <- neuroim2::ClusteredNeuroVol(syn$mask > 0, clusters = syn$truth) # Visualise a single slice (requires neuroim2 plot method): ## Not run: plot(clusvol) ## End(Not run)syn <- generate_synthetic_volume( scenario = "gaussian_blobs", dims = c(12, 12, 6), n_clusters = 4, seed = 1 ) str(syn) truth_vol <- array(syn$truth, syn$dims) clusvol <- neuroim2::ClusteredNeuroVol(syn$mask > 0, clusters = syn$truth) # Visualise a single slice (requires neuroim2 plot method): ## Not run: plot(clusvol) ## End(Not run)
This function tests whether a cluster result object represents a partition.
It is a method for the is.cl_partition generic from the clue package.
For cluster_result objects, this always returns TRUE since cluster results
represent valid partitions where each data point belongs to exactly one cluster.
## S3 method for class 'cluster_result' is.cl_partition(x)## S3 method for class 'cluster_result' is.cl_partition(x)
x |
A |
TRUE, indicating that cluster results are always valid partitions.
is.cl_partition for the generic function.
Replace each voxel by the mean of its k nearest neighbors in its local spatial neighborhood.
knn_shrink(bvec, mask, k = 5, connectivity = 27)knn_shrink(bvec, mask, k = 5, connectivity = 27)
bvec |
A |
mask |
A |
k |
The number of nearest neighbors to average over. |
connectivity |
The number of spatial neighbors to include in the search around each voxel. |
A SparseNeuroVec or similar object with the smoothed data.
## Not run: mask <- neuroim2::NeuroVol(array(1, c(20,20,20)), neuroim2::NeuroSpace(c(20,20,20))) bvec <- replicate(10, neuroim2::NeuroVol(array(runif(20*20*20), c(20,20,20)), neuroim2::NeuroSpace(c(20,20,20))), simplify=FALSE) bvec <- do.call(neuroim2::concat, bvec) sbvec <- knn_shrink(bvec, mask, k=3) ## End(Not run)## Not run: mask <- neuroim2::NeuroVol(array(1, c(20,20,20)), neuroim2::NeuroSpace(c(20,20,20))) bvec <- replicate(10, neuroim2::NeuroVol(array(runif(20*20*20), c(20,20,20)), neuroim2::NeuroSpace(c(20,20,20))), simplify=FALSE) bvec <- do.call(neuroim2::concat, bvec) sbvec <- knn_shrink(bvec, mask, k=3) ## End(Not run)
A scikit-learn style make_blobs for neuroimaging demos. Builds a small
2D/3D mask with three spatial bands (left/mid/right) and clearly separated
time-series patterns plus mild Gaussian noise. Designed to be fast,
deterministic, and visually intuitive in vignettes and tests.
make_block_synthetic( dims = c(12, 12, 1), ntime = 80, noise = 0.15, seed = NULL )make_block_synthetic( dims = c(12, 12, 1), ntime = 80, noise = 0.15, seed = NULL )
dims |
Integer vector length 3, spatial dimensions. Default |
ntime |
Number of time points. Default 80. |
noise |
Standard deviation of added Gaussian noise. Default 0.15. |
seed |
Optional integer seed for reproducibility. Default |
List with components:
NeuroVec 4D volume
NeuroVol mask
Integer ground-truth labels (length = prod(dims))
Creates a discrete cosine transform (type II) basis matrix for detrending.
make_dct_basis(n_time, n_basis)make_dct_basis(n_time, n_basis)
n_time |
Number of timepoints |
n_basis |
Number of DCT basis functions (including constant) |
DCT basis functions are excellent for removing low-frequency drift in fMRI. The first basis is constant (mean), subsequent bases capture increasingly higher frequency components.
Numeric matrix (n_time x n_basis) with orthonormal DCT basis
Creates a polynomial basis matrix for detrending.
make_poly_basis(n_time, degree)make_poly_basis(n_time, degree)
n_time |
Number of timepoints |
degree |
Polynomial degree (0 = constant, 1 = linear, 2 = quadratic, etc.) |
Uses Gram-Schmidt orthonormalization for numerical stability. Degree 0 = mean removal, 1 = linear detrend, 2 = quadratic, etc.
Numeric matrix (n_time x (degree+1)) with orthonormalized polynomial basis
Generates a volume with perfectly separable clusters for testing clustering algorithm correctness. Each cluster is a spatially contiguous cubic sub-region with identical timeseries within the cluster and orthogonal signals between clusters.
make_synthetic_clusters( n_time = 100, noise_sd = 0, n_clusters = 27, dim_per_cluster = 3, seed = NULL )make_synthetic_clusters( n_time = 100, noise_sd = 0, n_clusters = 27, dim_per_cluster = 3, seed = NULL )
n_time |
Number of timepoints. Default 100. |
noise_sd |
Standard deviation of Gaussian noise to add. Default 0 (no noise = perfect separability). |
n_clusters |
Number of clusters. Must be a perfect cube (8, 27, 64, etc.) for cubic cluster geometry. Default 27. |
dim_per_cluster |
Voxels per dimension per cluster. Default 3. |
seed |
Random seed for reproducibility. Default NULL. |
For the default n_clusters=27, creates a 9x9x9 volume divided into 27 cubic 3x3x3 clusters arranged in a 3x3x3 grid:
z=1-3: z=4-6: z=7-9: y y y ^ ^ ^ | 7 | 8 | 9 | | 16| 17| 18| | 25| 26| 27| | 4 | 5 | 6 | | 13| 14| 15| | 22| 23| 24| | 1 | 2 | 3 | | 10| 11| 12| | 19| 20| 21| +-----------> x +-----------> x +-----------> x
Each cluster has a unique orthogonal signal generated from QR decomposition of a random matrix, ensuring zero correlation between clusters.
This creates an "easy" test case where any reasonable clustering algorithm should achieve perfect or near-perfect recovery with noise_sd=0.
A list with:
vec |
NeuroVec object |
mask |
NeuroVol mask (all ones) |
true_clusters |
NeuroVol with ground truth cluster labels |
true_labels |
Integer vector of true cluster assignments |
n_clusters |
Number of clusters |
cluster_size |
Size of each cluster in voxels |
signals |
Matrix of cluster signals (n_time x n_clusters) |
# Default: 27 clusters, perfect separability data <- make_synthetic_clusters() table(data$true_labels) # 27 voxels per cluster # 8 clusters (2x2x2 grid of 3x3x3 cubes = 6x6x6 volume) data <- make_synthetic_clusters(n_clusters = 8) # With noise for more realistic testing data <- make_synthetic_clusters(noise_sd = 0.5)# Default: 27 clusters, perfect separability data <- make_synthetic_clusters() table(data$true_labels) # 27 voxels per cluster # 8 clusters (2x2x2 grid of 3x3x3 cubes = 6x6x6 volume) data <- make_synthetic_clusters(n_clusters = 8) # With noise for more realistic testing data <- make_synthetic_clusters(noise_sd = 0.5)
The merge_clus function combines a set of clustering results using a consensus clustering algorithm.
merge_clus(x, ...)merge_clus(x, ...)
x |
A clustering result, typically a list or an object of class |
... |
Additional clustering results to be merged and method-specific arguments
(e.g., |
A ClusteredNeuroVol instance.
cl_consensus, as.cl_hard_partition, cl_ensemble
## Not run: # Assuming clustering1, clustering2, and clustering3 are objects of class "cluster_result" merged_clustering <- merge_clus(clustering1, clustering2, clustering3, method="SE") ## End(Not run)## Not run: # Assuming clustering1, clustering2, and clustering3 are objects of class "cluster_result" merged_clustering <- merge_clus(clustering1, clustering2, clustering3, method="SE") ## End(Not run)
This method of merge_clus is specifically designed to merge clustering results for ClusteredNeuroVol objects
by performing consensus clustering across multiple clustering results.
## S3 method for class 'cluster_result' merge_clus(x, method = "SE", ...)## S3 method for class 'cluster_result' merge_clus(x, method = "SE", ...)
x |
A |
method |
A character string indicating the consensus clustering algorithm to use. Default is "SE".
See |
... |
Additional clustering results to be merged. |
A ClusteredNeuroVol instance representing the consensus partition.
cl_consensus, as.cl_hard_partition, cl_ensemble
The meta_clust generic function is used to define methods for different classes of input objects.
meta_clust(x, cuts, ...)meta_clust(x, cuts, ...)
x |
A clustering result, typically an object of class |
cuts |
The number of cluster cuts to consider. |
... |
Additional arguments passed to methods. |
Depends on the method called.
The meta_clust function performs meta clustering on a given clustering result by applying hierarchical clustering on the cluster centers.
## S3 method for class 'cluster_result' meta_clust(x, cuts = NULL, ...)## S3 method for class 'cluster_result' meta_clust(x, cuts = NULL, ...)
x |
A clustering result, typically an object of class |
cuts |
Integer vector specifying the number of cluster cuts to consider.
Default is |
... |
Additional arguments:
|
Currently NOT parallelized. Meta-clustering performs hierarchical clustering on cluster centers using sequential R functions.
Distance Matrix Computation:
Computes correlation distance (1 - cor) between all cluster centers
O(K^2) pairwise correlations where K = number of input clusters
Sequential double loop in base R
Hierarchical Clustering: hclust()
Standard hierarchical agglomeration (Ward.D by default)
Sequential merging of closest clusters
O(K^2 log K) complexity
Tree Cutting: cutree()
Cuts dendrogram at multiple heights
Creates nested cluster assignments
Linear in number of clusters
Small scale: Usually operates on hundreds of clusters, not thousands of voxels
R built-ins: Uses standard hclust() which is sequential
Fast enough: Typically completes in seconds even for large K
Memory efficient: Only stores K x K distance matrix
Distance matrix computation could use parallel correlation
Some hierarchical clustering variants support parallelization
Multiple cuts could be computed in parallel
Input size: K clusters from initial clustering (typically 100-1000)
Complexity: O(K^2) for distances, O(K^2 log K) for clustering
Memory: O(K^2) for distance matrix
Speed: Usually < 1 second for K < 500
Pre-reduce clusters: Start with fewer initial clusters if meta-clustering is slow
Use appropriate linkage: Ward.D is slower but often gives better results
Limit cuts: Fewer cut levels = faster processing
Alternative: Use consensus clustering (merge_clus()) for different approach
Meta-clustering is useful for:
Creating multi-resolution parcellations
Hierarchical organization of functional regions
Reducing large numbers of clusters to interpretable groups
Finding stable cluster boundaries across scales
A list containing:
cvols |
A list of |
cuts |
The number of cluster cuts. |
cutmat |
A matrix representing the cluster assignments for each cut. |
hclus |
The hierarchical clustering result. |
original_result |
The original clustering result (optional reference). |
Reports build-time SIMD feature macros and (when available) a small set of runtime CPU feature flags, plus the currently-selected int8 dot-product kernel used by neurocluster's correlation-SLIC code paths.
neurocluster_simd_info()neurocluster_simd_info()
This is primarily a development/benchmarking aid. For definitive evidence that an ISA-specific kernel is in use, disassemble the package shared library and look for the corresponding instructions.
A named list with fields compiler, arch, compile, runtime,
dot_i8_kernel, shared_library, and notes.
Combined fast preprocessing: removes volume mean offsets and linear trends in a single efficient operation.
normalize_detrend(vec, mask = NULL)normalize_detrend(vec, mask = NULL)
vec |
A |
mask |
Optional |
Combines normalize_volumes and detrend_time
in a single pass for efficiency. The operations are applied in order:
Remove volume-wise mean offset
Remove linear trend from each voxel's timeseries
Uses fast C++ parallel implementation via RcppParallel.
A NeuroVec with volume offsets and linear trends removed
## Not run: vec <- neuroim2::read_vec("functional.nii.gz") vec_clean <- normalize_detrend(vec) ## End(Not run)## Not run: vec <- neuroim2::read_vec("functional.nii.gz") vec_clean <- normalize_detrend(vec) ## End(Not run)
Combined operation: first removes volume mean offsets, then removes linear trend from each voxel's timeseries. More efficient than calling both functions separately.
normalize_detrend_cpp(data)normalize_detrend_cpp(data)
data |
Numeric matrix with voxels as rows and timepoints as columns |
Performs two operations in a single parallel pass:
Centers each volume to zero mean
Removes linear trend from each voxel's (now centered) timeseries
Numeric matrix with volume offsets and linear trends removed
Fast removal of volume-wise mean offset from 4D neuroimaging data. Each volume/timepoint is centered to have zero mean across voxels.
normalize_volumes(vec, mask = NULL)normalize_volumes(vec, mask = NULL)
vec |
A |
mask |
Optional |
This function removes global signal offset that can vary across timepoints due to scanner drift, physiological noise, or other factors. For each timepoint t:
Uses fast C++ parallel implementation via RcppParallel.
A NeuroVec with each volume centered to zero mean
## Not run: vec <- neuroim2::read_vec("functional.nii.gz") vec_normalized <- normalize_volumes(vec) ## End(Not run)## Not run: vec <- neuroim2::read_vec("functional.nii.gz") vec_normalized <- normalize_volumes(vec) ## End(Not run)
Removes the mean offset from each volume/timepoint in a matrix. This centers each volume to have zero mean across voxels.
normalize_volumes_cpp(data)normalize_volumes_cpp(data)
data |
Numeric matrix with voxels as rows and timepoints as columns |
For each timepoint t, computes mean_t = mean(data[, t]) and subtracts
it from all voxels: output[, t] = data[, t] - mean_t
Uses RcppParallel for fast parallel computation across voxels.
Numeric matrix with each column (volume) centered to mean zero
Creates visualization of clustering results. Shows axial, sagittal, and coronal slices through the clustered volume.
## S3 method for class 'cluster4d_result' plot(x, slice = NULL, view = "all", colors = NULL, zlim = NULL, ...)## S3 method for class 'cluster4d_result' plot(x, slice = NULL, view = "all", colors = NULL, zlim = NULL, ...)
x |
A cluster4d_result object |
slice |
Slice specification. Can be:
|
view |
Viewing plane: "axial", "sagittal", "coronal", or "all" |
colors |
Color palette for clusters. Default uses rainbow colors. |
zlim |
Numeric length-two label range shared by every displayed plane.
The default, |
... |
Additional arguments passed to plotting functions |
Invisibly returns the plotted data
Methods for printing, summarizing, and plotting cluster4d results. Print cluster4d result
## S3 method for class 'cluster4d_result' print(x, ...)## S3 method for class 'cluster4d_result' print(x, ...)
x |
A cluster4d_result object |
... |
Additional arguments (ignored) |
Invisibly returns x
Print Method for G3S Results
## S3 method for class 'g3s_result' print(x, ...)## S3 method for class 'g3s_result' print(x, ...)
x |
A g3s_result object |
... |
Additional arguments (ignored) |
Randomly permute cluster IDs to break any spatial ordering. This is useful when visualizing clusters with continuous color scales, as spatially-ordered cluster IDs create artificial gradients that can be misleading.
randomize_cluster_ids(cluster_result, seed = NULL)randomize_cluster_ids(cluster_result, seed = NULL)
cluster_result |
A clustering result object (e.g., from cluster4d, supervoxels_flash3d, slice_msf, etc.) containing at minimum:
|
seed |
Optional random seed for reproducibility. If NULL, uses R's current random state. Default is NULL. |
Many clustering algorithms assign cluster IDs sequentially as clusters are encountered during processing. When voxels are processed in memory order (which is typically z-major in 3D arrays), this creates systematic ordering where cluster ID correlates with z-position (inferior to superior in brain imaging).
This spatial ordering creates two problems:
Visualization artifacts: When viewed with continuous color scales (e.g., viridis, rainbow), ordered cluster IDs create artificial gradients that suggest spatial structure where none exists. Randomized IDs show each cluster as a distinct color patch.
Interpretation bias: Ordered IDs may mislead users into thinking cluster numbering has anatomical significance (e.g., "cluster 1 is always inferior, cluster 100 is always superior").
This function breaks the ordering by randomly permuting cluster IDs while maintaining all cluster memberships and properties.
A modified cluster_result object with randomized cluster IDs. All components (cluster vector, clusvol, centers, coord_centers, etc.) are updated consistently.
## Not run: # Standard workflow with ordered IDs result <- cluster4d(vec, mask, K = 100, method = "flash3d") # Randomize for better visualization result_random <- randomize_cluster_ids(result, seed = 42) # Compare visualizations # Ordered IDs show gradient from inferior to superior plot(result$clusvol) # Randomized IDs show distinct color patches plot(result_random$clusvol) # Works with other supported clustering methods result_snic <- cluster4d(vec, mask, n_clusters = 100, method = "snic") result_snic_random <- randomize_cluster_ids(result_snic) ## End(Not run)## Not run: # Standard workflow with ordered IDs result <- cluster4d(vec, mask, K = 100, method = "flash3d") # Randomize for better visualization result_random <- randomize_cluster_ids(result, seed = 42) # Compare visualizations # Ordered IDs show gradient from inferior to superior plot(result$clusvol) # Randomized IDs show distinct color patches plot(result_random$clusvol) # Works with other supported clustering methods result_snic <- cluster4d(vec, mask, n_clusters = 100, method = "snic") result_snic_random <- randomize_cluster_ids(result_snic) ## End(Not run)
Performs spatially-constrained hierarchical clustering using recursive 1-nearest neighbor aggregation. ReNA is a fast, linear-time agglomerative algorithm that avoids the "percolation" problem of standard hierarchical methods by using 1-NN graphs to ensure balanced cluster sizes.
rena( bvec, mask, K = 100, connectivity = 26, max_iterations = 50, verbose = FALSE, exact_k = TRUE )rena( bvec, mask, K = 100, connectivity = 26, max_iterations = 50, verbose = FALSE, exact_k = TRUE )
bvec |
A |
mask |
A |
K |
The number of clusters to find (default 100). |
connectivity |
Exact masked-grid connectivity (6, 18, or 26). |
max_iterations |
Maximum number of recursion iterations (default 50). Algorithm stops when K clusters are reached or max_iterations is hit. |
verbose |
Logical; whether to print progress messages. Default FALSE. |
exact_k |
Logical; whether to use the shared adjacency-preserving merge and split engine to ensure exactly K clusters. A target below the number of disconnected mask components is infeasible. |
ReNA recursively aggregates features using a 1-Nearest Neighbor (1-NN) graph to ensure clusters remain roughly balanced in size and spatially compact. The algorithm proceeds in iterations:
Connectivity Constraint: Clustering respects the spatial topology graph G. Distance is only calculated between spatially adjacent voxels.
Similarity Calculation: For all connected edges, compute squared Euclidean distance in feature space.
1-NN Subgraph: For every voxel, identify its single nearest neighbor. This forms a directed subgraph Q. The 1-NN graph is less likely to "percolate" (create giant components) compared to k-NN graphs where k >= 2.
Connected Components: Extract weakly connected components of Q. These components become the clusters for the current iteration.
Reduction: Features within each component are averaged to form a single "super-feature" for the next iteration. The graph G is contracted so edges between new clusters exist if any constituent voxels were connected.
Stopping Condition: Repeat recursively until the number of clusters drops to the desired K. If exact_k = TRUE, edges are pruned by distance to ensure exactly K clusters.
Complexity: O(N log N) per iteration where N = number of voxels
Memory: O(N) for graph and assignments
Speed: Generally faster than iterative methods (supervoxels)
Iterations: Typically 5-15 iterations to reach K clusters from N voxels
No percolation: Unlike single-linkage, doesn't form one giant cluster
Balanced sizes: 1-NN graph encourages roughly equal cluster sizes
Topology-aware: Respects spatial structure via connectivity graph
Deterministic: No random initialization
Fast convergence: Linear-time operations per iteration
Currently NOT parallelized. ReNA uses a sequential recursive algorithm that processes the graph in a hierarchical manner. Each iteration depends on the previous iteration's clustering result.
Distance Computation: Pairwise distances for connected voxels (C++)
1-NN Finding: Each voxel finds its nearest neighbor (C++)
Component Detection: Union-Find algorithm for connected components (C++)
Feature Aggregation: Mean pooling within components (C++)
Graph Contraction: Building reduced graph for next iteration (C++)
Sequential dependency: Each iteration requires previous iteration's result
Fast per-iteration: Linear-time operations make parallelization overhead high
Small iteration count: Typically 5-15 iterations total
C++ optimization: Core operations already optimized in C++
Reduce connectivity: Use connectivity=6 instead of 26 for larger graphs
Use smaller K: Fewer target clusters means fewer iterations
Pre-smooth data: Reduces noise, improves cluster coherence
Parallel alternatives: In the unified API, supervoxels and slic
support parallel = TRUE. The other methods do not advertise a parallel
clustering contract.
A list of class rena_cluster_result (inheriting from
cluster_result) with the following elements:
An instance of type ClusteredNeuroVol.
A vector of cluster indices equal to the number of voxels in the mask.
A matrix of cluster centers with each row representing the feature vector for a cluster.
A matrix of spatial coordinates with each row corresponding to a cluster.
Actual number of clusters found.
Clustering method used ("rena").
List of all parameters used.
List containing iteration count and convergence information.
Consider using cluster4d with method = "rena" for a
standardized interface across all clustering methods.
Hoyos-Idrobo, A., Varoquaux, G., Kahn, J., & Thirion, B. (2019). Recursive Nearest Agglomeration (ReNA): Fast clustering for approximation of structured signals. Pattern Recognition, 94, 17-28.
cluster4d for unified interface,
supervoxels for iterative heat kernel clustering,
snic for non-iterative priority queue clustering
## Not run: # Small synthetic example library(neuroim2) mask <- NeuroVol(array(1, c(10,10,10)), NeuroSpace(c(10,10,10))) vec <- replicate(20, NeuroVol(array(runif(10*10*10), c(10,10,10)), NeuroSpace(c(10,10,10))), simplify=FALSE) vec <- do.call(concat, vec) # Run ReNA clustering rena_res <- rena(vec, mask, K=50, connectivity=26) print(rena_res$n_clusters) # With verbose output rena_res <- rena(vec, mask, K=50, verbose=TRUE) ## End(Not run)## Not run: # Small synthetic example library(neuroim2) mask <- NeuroVol(array(1, c(10,10,10)), NeuroSpace(c(10,10,10))) vec <- replicate(20, NeuroVol(array(runif(10*10*10), c(10,10,10)), NeuroSpace(c(10,10,10))), simplify=FALSE) vec <- do.call(concat, vec) # Run ReNA clustering rena_res <- rena(vec, mask, K=50, connectivity=26) print(rena_res$n_clusters) # With verbose output rena_res <- rena(vec, mask, K=50, verbose=TRUE) ## End(Not run)
Two-stage pipeline:
Edge-aware reciprocal-nearest-neighbor ReNA coarsening toward K' = ceiling(r * K) super-voxels.
Spatially-constrained Ward refinement on the super-graph to reach exactly K clusters.
rena_plus( bvec, mask, K = 100, r = 2, lambda = 1, grad_img = NULL, connectivity = 26, max_iterations = 50, verbose = FALSE, ... )rena_plus( bvec, mask, K = 100, r = 2, lambda = 1, grad_img = NULL, connectivity = 26, max_iterations = 50, verbose = FALSE, ... )
bvec |
A |
mask |
A |
K |
Target number of clusters. |
r |
Finite over-clustering factor at least 1. Coarsening approaches K' = ceiling(r * K) without applying a level that would overshoot below K'. Default 2. |
lambda |
Gradient penalty strength (>=0). 0 disables edge weighting. |
grad_img |
Optional numeric vector: gradient/intensity per voxel. Either length = prod(dim(mask)) (in which case values are subset by mask) or length = number of masked voxels. If NULL, no gradient. |
connectivity |
Neighborhood connectivity (6, 18, or 26). Default 26. |
max_iterations |
Max iterations for coarsening stage. |
verbose |
Logical for progress messages. |
... |
Reserved for future options. |
A reciprocal-neighbor level is retained only when applying the complete
level would leave at least K' super-voxels. This prevents the coarsening
stage from overshooting below K and leaves the remaining one-at-a-time
adjacent merges to Ward refinement. Ward costs are recomputed from the
current size-weighted means before every accepted merge; equal-cost edges
are resolved by ascending super-voxel identifiers. Because the adjacency
constraint can expose a new edge after a merge, individual Ward deltas need
not be ordered, although every delta is non-negative and the cumulative
objective is non-decreasing. When Ward refinement is needed, its complete
trace and queue diagnostics are available in result$metadata$ward.
A cluster4d_result with additional class rena_plus_cluster_result.
Compute and return the gradient volume that would be used for seed relocation in slic4d_supervoxels. Useful for debugging and visualization.
slic4d_grad_summary( bvec, mask, method = c("correlation", "intensity", "spatial") )slic4d_grad_summary( bvec, mask, method = c("correlation", "intensity", "spatial") )
bvec |
A |
mask |
A 3D |
method |
One of "correlation", "intensity", "spatial". |
A 3D array containing the gradient values.
Cluster a 4D NeuroVec (x,y,z,time) into compact, spatially contiguous
3D supervoxels using an enhanced SLIC-style algorithm with mask-aware seeding,
gradient-based seed relocation, and topology-aware K preservation.
slic4d_supervoxels( bvec, mask, K, compactness = 10, max_iter = 10, n_threads = 0, step_mm = NULL, n_components = 0, feature_norm = c("zscale", "l2", "none"), seed_method = c("mask_poisson", "mask_grid", "grid", "farthest"), seed_relocate = c("none", "correlation", "intensity", "spatial"), seed_relocate_radius = 1L, connectivity = c(26L, 6L), strict_connectivity = TRUE, enforce_connectivity = TRUE, preserve_k = FALSE, topup_iters = 2L, min_size = 0L, verbose = FALSE, .input_contract = NULL )slic4d_supervoxels( bvec, mask, K, compactness = 10, max_iter = 10, n_threads = 0, step_mm = NULL, n_components = 0, feature_norm = c("zscale", "l2", "none"), seed_method = c("mask_poisson", "mask_grid", "grid", "farthest"), seed_relocate = c("none", "correlation", "intensity", "spatial"), seed_relocate_radius = 1L, connectivity = c(26L, 6L), strict_connectivity = TRUE, enforce_connectivity = TRUE, preserve_k = FALSE, topup_iters = 2L, min_size = 0L, verbose = FALSE, .input_contract = NULL )
bvec |
A |
mask |
A 3D |
K |
Finite integer target number of supervoxels, between one and the number of included voxels. |
compactness |
Finite non-negative spatial vs feature tradeoff (like SLIC 'm'). Larger values produce more compact clusters. |
max_iter |
Positive finite integer iteration limit (default 10). |
n_threads |
Non-negative finite integer number of CPU threads. Zero requests RcppParallel's automatic thread count, one forces serial assignment, and values above one request that many threads. Assignment is intentionally serial for masks with fewer than 2,000 included voxels. |
step_mm |
Optional approximate spacing between seeds in millimeters; if NULL, computed as cubic root of bounding-box volume / K. |
n_components |
If > 0, random-project each voxel's time series to this dimension for speed (Johnson-Lindenstrauss style). 0 = use full time series. |
feature_norm |
One of "zscale", "l2", "none". |
seed_method |
One of "mask_poisson" (Poisson disk in mask), "mask_grid" (grid in mask), "grid" (regular grid), "farthest" (farthest point sampling). |
seed_relocate |
One of "correlation" (correlation gradient), "intensity" (mean intensity gradient), "spatial" (spatial gradient using adjoin), "none" (no relocation). |
seed_relocate_radius |
Search radius in voxels for gradient-based seed relocation (default 1). |
connectivity |
Neighborhood connectivity: 6 (face neighbors) or 26 (all neighbors). |
strict_connectivity |
Enforce exactly one connected component per label (default TRUE). |
enforce_connectivity |
Deprecated alias for strict connectivity. When
omitted, it follows |
preserve_k |
Return exactly K non-empty labels when compatible with strict connectivity (default FALSE). See Details. |
topup_iters |
Non-negative number of native refinement iterations before the final connectivity and exact-K repair (default 2). |
min_size |
Minimum component size (voxels) to keep before relabel (default 0). |
verbose |
Logical. |
.input_contract |
Internal prevalidated input receipt used by
|
Connectivity is the final partition constraint. With
strict_connectivity = TRUE, every returned label has exactly one
connected component under the requested neighborhood. If
preserve_k = TRUE, an adjacency-preserving repair reaches exactly K
whenever K is at least the number of connected mask components. When K is
below that topological minimum, strict connectivity takes precedence, the
minimum feasible number of labels is returned, and a warning is emitted.
Returned feature and coordinate centers are recomputed from the final public
labels in the original feature space and physical coordinate system.
A cluster4d_result (also inheriting from
cluster_result) with elements:
clusvol: ClusteredNeuroVol with the final labels
cluster: integer vector of length = #masked voxels
centers: matrix (actual_k x d_feat) center features
coord_centers: matrix (actual_k x 3) spatial centers in mm
Consider using cluster4d with method = "slic" for a
standardized interface across all clustering methods.
## Not run: library(neuroim2) # Basic usage res <- slic4d_supervoxels(bvec, mask, K = 1000, compactness = 15) # With mask-aware seeding and gradient relocation res <- slic4d_supervoxels(bvec, mask, K = 1000, seed_method = "mask_poisson", seed_relocate = "correlation", preserve_k = TRUE) ## End(Not run)## Not run: library(neuroim2) # Basic usage res <- slic4d_supervoxels(bvec, mask, K = 1000, compactness = 15) # With mask-aware seeding and gradient relocation res <- slic4d_supervoxels(bvec, mask, K = 1000, seed_method = "mask_poisson", seed_relocate = "correlation", preserve_k = TRUE) ## End(Not run)
Compresses each voxel time series into a non-DC DCT sketch, uses cosine dissimilarity on a masked 3-D neighborhood graph, and applies Felzenszwalb-Huttenlocher segmentation. Multi-run fits use seeded DCT subspace and mode-weight resampling followed by uniformly weighted consensus. Nonzero sketches are normalized to unit length. A zero-information sketch remains zero and therefore has edge dissimilarity one to every neighbor.
slice_msf( vec, mask, target_k_global = -1, r = 12, compactness = 5, min_size = 80, num_runs = 3, consensus = TRUE, stitch_z = TRUE, nbhd = 8, gamma = 0, k_fuse = NULL, min_size_fuse = NULL, use_features = FALSE, lambda = 0.7, z_mult = 0, seed = 1L, ensemble_fraction = 0.8 )slice_msf( vec, mask, target_k_global = -1, r = 12, compactness = 5, min_size = 80, num_runs = 3, consensus = TRUE, stitch_z = TRUE, nbhd = 8, gamma = 0, k_fuse = NULL, min_size_fuse = NULL, use_features = FALSE, lambda = 0.7, z_mult = 0, seed = 1L, ensemble_fraction = 0.8 )
vec |
A |
mask |
A |
target_k_global |
|
r |
Requested number of non-DC DCT modes. It is capped at |
compactness |
Finite value in |
min_size |
Positive minimum component size for each run. |
num_runs |
Positive number of runs. Values above one require consensus. |
consensus |
Whether to fuse a multi-run ensemble. |
stitch_z |
Whether graph edges may cross axial slices. When |
nbhd |
|
gamma |
Reserved compatibility parameter. It must be zero; positive reliability weighting is rejected because it can collapse non-identical feature vectors to zero-distance edges. |
k_fuse |
Positive FH scale for consensus; defaults to the run scale. |
min_size_fuse |
Positive minimum consensus component size; defaults to
|
use_features |
Include sketch similarity as well as label agreement in multi-run consensus. |
lambda |
Consensus mixture in |
z_mult |
DCT-sketch smoothing fraction in |
seed |
Integer seed used to construct multi-run DCT subspaces. |
ensemble_fraction |
Fraction in |
A slice_msf_cluster_result and cluster4d_result. cluster is in
mask order, centers is K by T, and coord_centers is K by 3. Multi-run
results also contain native runs. metadata$exact_k_repair records the
natural and requested K, pre/post sizes, whether and how repair ran,
connectivity, minimum size, and effective gamma, z smoothing, seed, run
count, and consensus controls for both natural and exact-K calls.
slice_msf() is available for explicit evaluation but is not a recommended
production method. A previous reliability-weighting path collapsed distinct
feature vectors to zero-distance edges, and the former exact-K repair could
create singleton-dominated partitions. Those paths are now rejected or
replaced and covered by regression tests, but release-level recertification
is still pending. See vignette("slice-msf") for the evaluation contract.
Felzenszwalb, P. F., & Huttenlocher, D. P. (2004). Efficient graph-based image segmentation. IJCV, 59(2), 167-181.
Builds neighbor-edge co-association scores from at least two run results and optionally mixes those scores with DCT-sketch similarity.
slice_msf_consensus( run_results, mask, nbhd = 8, k_fuse = 0.3, min_size_fuse = 80, use_features = FALSE, lambda = 0.7, stitch_z = TRUE, gamma = 0 )slice_msf_consensus( run_results, mask, nbhd = 8, k_fuse = 0.3, min_size_fuse = 80, use_features = FALSE, lambda = 0.7, stitch_z = TRUE, gamma = 0 )
run_results |
At least two results from |
mask |
The original |
nbhd |
|
k_fuse |
Positive FH scale for the consensus graph. |
min_size_fuse |
Positive minimum consensus component size. |
use_features |
Whether DCT-sketch similarity contributes to edges. |
lambda |
Mixture in |
stitch_z |
Whether consensus edges may cross axial slices. |
gamma |
Reserved compatibility parameter. It must be zero. |
A list with full-volume consensus labels and complete params.
Low-level diagnostic interface returning native full-volume labels, a signed
adjacent-pair temporal-smoothness diagnostic, and an r_used by voxel DCT
sketch. Temporal smoothness does not affect segmentation.
slice_msf_single( vec, mask, r = 12, k = 0.32, min_size = 80, nbhd = 8, stitch_z = TRUE, gamma = 0, z_mult = 0, dct_frequencies = NULL, dct_weights = NULL )slice_msf_single( vec, mask, r = 12, k = 0.32, min_size = 80, nbhd = 8, stitch_z = TRUE, gamma = 0, z_mult = 0, dct_frequencies = NULL, dct_weights = NULL )
vec |
A |
mask |
A |
r |
Requested number of non-DC DCT modes. It is capped at |
k |
Positive FH segmentation scale. |
min_size |
Positive minimum component size for each run. |
nbhd |
|
stitch_z |
Whether graph edges may cross axial slices. When |
gamma |
Reserved compatibility parameter. It must be zero; positive reliability weighting is rejected because it can collapse non-identical feature vectors to zero-distance edges. |
z_mult |
DCT-sketch smoothing fraction in |
dct_frequencies |
Optional unique non-DC DCT frequencies in |
dct_weights |
Optional positive weights paired with |
A list with full-volume labels, temporal_smoothness, sketch, and
params.
The SNIC function performs a spatially constrained clustering on a NeuroVec instance
using the Simple Non-Iterative Clustering (SNIC) algorithm.
snic(vec, mask, compactness = 5, K = 500, max_iter = 100)snic(vec, mask, compactness = 5, K = 500, max_iter = 100)
vec |
A |
mask |
A |
compactness |
A finite numeric value in |
K |
The number of clusters to find. Default is 500. |
max_iter |
Deprecated inactive argument retained in the function signature for compatibility. SNIC is non-iterative; supplying this argument explicitly is an error. |
The SNIC implementation has been highly optimized using lightweight C++ structs and in-place operations, providing 10x-50x speedup over the original implementation. Key optimizations include:
Elimination of Rcpp::List overhead in priority queue (uses lightweight struct)
In-place centroid updates with no memory allocations
Inline 26-connectivity neighbor iteration
Direct pointer access for array operations
Efficient scalar math (eliminates temporary vector allocations)
Currently NOT parallelized. SNIC uses a sequential priority queue-based algorithm that processes voxels in order of their distance from cluster centers.
Initialization: Gradient-based seed selection using find_initial_points()
Finds K seed points with high gradient and spatial separation
Sequential search through candidate voxels
Priority Queue Processing (C++ implementation):
Maintains a global priority queue of voxels to be assigned
Each voxel assignment depends on previously processed neighbors
Voxels are processed in order of their combined distance metric
Distance Computation: For each voxel, calculates:
Feature distance to nearest cluster center
Spatial distance weighted by compactness parameter
Combined into single priority score
Sequential dependency: Priority queue enforces strict processing order
Global state: Each voxel assignment affects subsequent assignments
Algorithm design: SNIC's key innovation is its non-iterative, sequential nature
Coherent clusters: Sequential processing ensures connected components
Complexity: O(N log N) where N = number of voxels
Memory: O(N) for priority queue and assignments
Speed: Generally faster than iterative methods (supervoxels)
Single pass: Processes each voxel exactly once
Reduce K: Fewer clusters means less competition for voxels
Adjust compactness: Higher values create more local clusters, faster processing
Pre-smooth data: Reduce noise to improve gradient-based initialization
Use smaller masks: Process ROIs separately if possible
Parallel alternative: In the unified API, supervoxels and slic
support parallel = TRUE. The other methods do not advertise a parallel
clustering contract.
Faster than: supervoxels() due to non-iterative nature
Parallel choices: Use one of the two unified methods listed above when a tested sequential/parallel clustering contract is required.
More coherent than: Methods without spatial priority (ensures connectivity)
A list of class snic_cluster_result with the following elements:
An instance of type ClusteredNeuroVol.
A NeuroVol instance representing the spatial gradient of the reference volume.
A vector of contiguous positive cluster labels, one per included mask voxel.
A K-by-T matrix of mean feature values in the original input space.
A matrix of spatial coordinates with each row corresponding to a cluster.
Consider using cluster4d with method = "snic" for a
standardized interface across all clustering methods.
## Not run: mask <- NeuroVol(array(1, c(20,20,20)), NeuroSpace(c(20,20,20))) vec <- replicate(10, NeuroVol(array(runif(202020), c(20,20,20)), NeuroSpace(c(20,20,20))), simplify=FALSE) vec <- do.call(concat, vec) snic_res <- snic(vec, mask, compactness=5, K=100) ## End(Not run)## Not run: mask <- NeuroVol(array(1, c(20,20,20)), NeuroSpace(c(20,20,20))) vec <- replicate(10, NeuroVol(array(runif(202020), c(20,20,20)), NeuroSpace(c(20,20,20))), simplify=FALSE) vec <- do.call(concat, vec) snic_res <- snic(vec, mask, compactness=5, K=100) ## End(Not run)
The spatial_gradient function calculates the spatial gradient of a NeuroVol instance within the specified mask.
spatial_gradient(vol, mask, sigma = 0.5)spatial_gradient(vol, mask, sigma = 0.5)
vol |
A |
mask |
A |
sigma |
A numeric value controlling the spatial weighting function. Default is 0.5. |
A NeuroVol instance containing the spatial gradient values for the input vol.
spatial_laplacian, weighted_spatial_adjacency
## Not run: mask <- neuroim2::NeuroVol(array(1, c(20,20,20)), neuroim2::NeuroSpace(c(20,20,20))) input_vol <- neuroim2::NeuroVol(array(runif(20*20*20), c(20,20,20)), neuroim2::NeuroSpace(c(20,20,20))) gradient_vol <- spatial_gradient(input_vol, mask) ## End(Not run)## Not run: mask <- neuroim2::NeuroVol(array(1, c(20,20,20)), neuroim2::NeuroSpace(c(20,20,20))) input_vol <- neuroim2::NeuroVol(array(runif(20*20*20), c(20,20,20)), neuroim2::NeuroSpace(c(20,20,20))) gradient_vol <- spatial_gradient(input_vol, mask) ## End(Not run)
Provides parameter recommendations based on data size and user priorities. Experimental methods are reported separately and are never returned as the recommended method.
suggest_cluster4d_params( n_voxels, n_timepoints, priority = c("balanced", "speed", "quality", "memory") )suggest_cluster4d_params( n_voxels, n_timepoints, priority = c("balanced", "speed", "quality", "memory") )
n_voxels |
Number of voxels in mask |
n_timepoints |
Number of time points |
priority |
What to optimize for: "speed", "quality", "memory", or "balanced" |
A list with suggested parameters for supported methods plus
experimental_methods and an experimental_note. Experimental methods
are not recommended or assigned suggested parameter sets.
# Get parameter suggestions for a typical fMRI dataset params <- suggest_cluster4d_params(50000, 200, priority = "balanced") print(params$recommended_method) print(params$n_clusters) # Speed-optimized parameters for large dataset speed_params <- suggest_cluster4d_params(100000, 300, priority = "speed") print(speed_params$recommended_method) # Quality-optimized parameters for smaller dataset quality_params <- suggest_cluster4d_params(10000, 150, priority = "quality") print(quality_params$n_clusters) # Memory-efficient parameters memory_params <- suggest_cluster4d_params(200000, 100, priority = "memory") print(memory_params$recommended_method)# Get parameter suggestions for a typical fMRI dataset params <- suggest_cluster4d_params(50000, 200, priority = "balanced") print(params$recommended_method) print(params$n_clusters) # Speed-optimized parameters for large dataset speed_params <- suggest_cluster4d_params(100000, 300, priority = "speed") print(speed_params$recommended_method) # Quality-optimized parameters for smaller dataset quality_params <- suggest_cluster4d_params(10000, 150, priority = "quality") print(quality_params$n_clusters) # Memory-efficient parameters memory_params <- suggest_cluster4d_params(200000, 100, priority = "memory") print(memory_params$recommended_method)
Summarize cluster4d result
## S3 method for class 'cluster4d_result' summary(object, ...)## S3 method for class 'cluster4d_result' summary(object, ...)
object |
A cluster4d_result object |
... |
Additional arguments (ignored) |
A summary list (invisibly)
Cluster feature data on a cortical surface or mesh using a supervoxel-like approach.
supervoxel_cluster_surface( bsurf, K = 500, sigma1 = 1, sigma2 = 5, iterations = 50, connectivity = 6, use_medoid = FALSE )supervoxel_cluster_surface( bsurf, K = 500, sigma1 = 1, sigma2 = 5, iterations = 50, connectivity = 6, use_medoid = FALSE )
bsurf |
A |
K |
Number of clusters. |
sigma1 |
Heat kernel bandwidth for feature similarity (data vectors). |
sigma2 |
Heat kernel bandwidth for spatial similarity (coordinate vectors). |
iterations |
Max iterations. |
connectivity |
Neighborhood size on the surface (e.g., # of nearest mesh neighbors). |
use_medoid |
Whether to use medoids for cluster centers. |
A list with:
A NeuroSurface storing the final clustering result.
Integer vector of cluster assignments (one per vertex).
Matrix of cluster centers.
Matrix of spatial centroid coordinates.
List of vertex indices for each cluster.
Cluster feature matrix (rows = time points) in a "supervoxel" style but over temporal dimension.
supervoxel_cluster_time( feature_mat, K = min(nrow(feature_mat), 100), sigma1 = 1, sigma2 = 3, iterations = 50, TR = 2, filter = list(lp = 0, hp = 0), use_medoid = FALSE, nreps = 5 )supervoxel_cluster_time( feature_mat, K = min(nrow(feature_mat), 100), sigma1 = 1, sigma2 = 3, iterations = 50, TR = 2, filter = list(lp = 0, hp = 0), use_medoid = FALSE, nreps = 5 )
feature_mat |
A matrix (nrows = time points, ncols = features) or vice versa. |
K |
Number of clusters. |
sigma1 |
Heat kernel bandwidth for feature similarity (data vectors). |
sigma2 |
Heat kernel bandwidth for spatial similarity (coordinate vectors). |
iterations |
Maximum number of cluster iterations. |
TR |
Repetition time (seconds). |
filter |
List specifying optional frequency filters, e.g., |
use_medoid |
Whether to use medoids for cluster centers. |
nreps |
Number of repeated initializations. |
A list of cluster results (one per repetition), each of which
has the same structure as supervoxel_cluster_fit().
## Not run: feature_mat <- matrix(rnorm(100 * 10), 100, 10) library(future) plan(multicore) cres <- supervoxel_cluster_time(t(feature_mat), K=5) ## End(Not run)## Not run: feature_mat <- matrix(rnorm(100 * 10), 100, 10) library(future) plan(multicore) cres <- supervoxel_cluster_time(t(feature_mat), K=5) ## End(Not run)
Cluster a NeuroVec instance into a set of spatially constrained clusters.
supervoxels( bvec, mask, K = 500, sigma1 = NULL, sigma2 = 2.5, iterations = 50, connectivity = 27, use_medoid = FALSE, use_gradient = TRUE, alpha = 0.5, parallel = TRUE, grain_size = 100, num_threads = NULL, verbose = FALSE, converge_thresh = 0.001 )supervoxels( bvec, mask, K = 500, sigma1 = NULL, sigma2 = 2.5, iterations = 50, connectivity = 27, use_medoid = FALSE, use_gradient = TRUE, alpha = 0.5, parallel = TRUE, grain_size = 100, num_threads = NULL, verbose = FALSE, converge_thresh = 0.001 )
bvec |
A |
mask |
A |
K |
The number of clusters to find (default 500). |
sigma1 |
The bandwidth of the heat kernel for the data vectors. |
sigma2 |
The bandwidth of the heat kernel for the coordinate vectors. |
iterations |
The maximum number of cluster iterations. |
connectivity |
The number of nearest neighbors defining the neighborhood. |
use_medoid |
Logical; whether to use medoids rather than means for cluster centers. |
use_gradient |
Logical; use the image gradient to initialize clusters if possible. |
alpha |
The relative weighting of data similarity vs spatial similarity;
|
parallel |
Logical; whether to use parallel processing for cluster assignment updates. Default is TRUE. Parallel processing is automatically disabled for small datasets (<1000 voxels). |
grain_size |
Integer; the minimum number of voxels to process per parallel task. Default is 100. Smaller values provide better load balancing but increase overhead. |
num_threads |
Optional integer to override the number of threads used by
RcppParallel (defaults to package/global setting). Ignored if |
verbose |
Logical; whether to print detailed progress messages including convergence metrics. Default is FALSE. |
converge_thresh |
Numeric; convergence threshold as proportion of voxels switching clusters. Algorithm stops when switch ratio falls below this value. Default is 0.001 (0.1% of voxels). |
The algorithm:
Scale input data (bvec) so each feature dimension is centered and scaled.
If use_gradient = TRUE, initialize cluster seeds using gradient-based heuristics.
Run an iterative, spatially-constrained clustering that updates voxel assignments based on
both feature similarity (bandwidth sigma1) and spatial proximity (bandwidth sigma2),
weighted by alpha.
Return the final clusters, plus the feature-space and coordinate-space centers.
Every assignment center must have a positive membership count. If an update
empties one or more labels, distinct voxels are deterministically moved from
non-singleton clusters in descending combined feature/spatial loss order.
Empty all-zero centers are therefore never passed to an assignment kernel.
Since K <= N is required, this reseed policy is feasible and the returned
labels, center rows, and requested K agree on every convergence path.
With parallel = TRUE, voxel assignment uses RcppParallel when there are
more than 1000 included voxels; smaller inputs use the same sequential
scoring kernel. Parallel and sequential kernels implement the same scoring
and deterministic tie rule. Centroid reduction may also run in parallel for
sufficiently large K. metadata$algorithm$parallel_used reports whether the
parallel assignment path actually ran. No architecture-specific fallback is
applied.
A list (of class cluster_result) with elements:
clusvol |
|
cluster |
Integer vector of cluster assignments for each voxel. |
centers |
K-by-T matrix of final cluster means in the original feature space. |
coord_centers |
K-by-3 matrix of final spatial means in physical units. |
metadata |
Algorithm diagnostics, including whether parallel assignment was requested and used and any deterministic empty-label reseeds. |
Consider using cluster4d with method = "supervoxels" for a
standardized interface across all clustering methods.
## Not run: mask <- NeuroVol(array(1, c(20,20,20)), NeuroSpace(c(20,20,20))) bvec <- replicate(10, NeuroVol(array(runif(20*20*20), c(20,20,20)), NeuroSpace(c(20,20,20))), simplify=FALSE) bvec <- do.call(concat, bvec) cres1 <- supervoxels(bvec, mask, K=100, sigma1=1, sigma2=3) ## End(Not run)## Not run: mask <- NeuroVol(array(1, c(20,20,20)), NeuroSpace(c(20,20,20))) bvec <- replicate(10, NeuroVol(array(runif(20*20*20), c(20,20,20)), NeuroSpace(c(20,20,20))), simplify=FALSE) bvec <- do.call(concat, bvec) cres1 <- supervoxels(bvec, mask, K=100, sigma1=1, sigma2=3) ## End(Not run)
Performs spatially-constrained clustering using Fast Low-rank Approximate Superclusters for Hemodynamics (FLASH-3D). This algorithm uses DCT-based temporal hashing and 3D jump-flood propagation for efficient clustering.
supervoxels_flash3d( vec, mask, K, lambda_s = 0.6, lambda_t = 1, lambda_g = 0, rounds = 2L, bits = 64L, dctM = 12L, vox_scale = NULL, barrier = NULL, verbose = FALSE )supervoxels_flash3d( vec, mask, K, lambda_s = 0.6, lambda_t = 1, lambda_g = 0, rounds = 2L, bits = 64L, dctM = 12L, vox_scale = NULL, barrier = NULL, verbose = FALSE )
vec |
A |
mask |
A |
K |
The number of clusters to find |
lambda_s |
Finite non-negative target spatial weight (default 0.6). Multi-round optimization warms up from half this value and finishes at the requested value. |
lambda_t |
Finite non-negative temporal weight for Hamming distance of time-series hashes (default 1.0). |
lambda_g |
Finite non-negative boundary-field weight (default 0.0). If
positive, |
rounds |
Number of outer rounds (seed→flood→recenter). Default 2, typically 2-3 is sufficient. |
bits |
Maximum temporal hash length (64 or 128). The effective number
of non-redundant comparisons is at most |
dctM |
Number of low DCT coefficients to rank-hash (default 12, range 4-32) |
vox_scale |
Voxel size scaling for spatial distance, e.g., c(dx,dy,dz). Default c(1,1,1) |
barrier |
Optional non-negative finite 3D boundary field with the same geometry as the mask. A candidate site is penalized when its seed and the target voxel have different boundary-field values. |
verbose |
Logical indicating whether to print progress messages |
FLASH-3D uses a novel approach combining:
DCT-based temporal feature hashing for fast similarity computation
Jump-flood algorithm for efficient spatial propagation
Blue-noise seeding for optimal initial cluster placement
Annealing of spatial weights to encourage compact clusters
The algorithm is particularly efficient for large-scale fMRI data, offering significant speed improvements over iterative methods while maintaining clustering quality.
A list of class cluster_result with the following elements:
An instance of type ClusteredNeuroVol
An integer vector of cluster assignments for each voxel in mask
A matrix of cluster centers in feature space (K x T)
A matrix of spatial coordinates of cluster centers (K x 3)
The number of clusters
A character string indicating the method used ("FLASH-3D")
Consider using cluster4d with method = "flash3d" for a
standardized interface across all clustering methods.
FLASH-3D algorithm for fast superclustering of fMRI data (2025)
supervoxels, snic, slic4d_supervoxels
## Not run: # Basic usage result <- supervoxels_flash3d(vec, mask, K = 100) # With custom parameters result <- supervoxels_flash3d(vec, mask, K = 100, lambda_s = 0.8, lambda_t = 1.2, bits = 128, dctM = 16) # With barrier for anatomy-aware clustering barrier_vol <- create_anatomical_barrier(mask) result <- supervoxels_flash3d(vec, mask, K = 100, lambda_g = 0.5, barrier = barrier_vol) ## End(Not run)## Not run: # Basic usage result <- supervoxels_flash3d(vec, mask, K = 100) # With custom parameters result <- supervoxels_flash3d(vec, mask, K = 100, lambda_s = 0.8, lambda_t = 1.2, bits = 128, dctM = 16) # With barrier for anatomy-aware clustering barrier_vol <- create_anatomical_barrier(mask) result <- supervoxels_flash3d(vec, mask, K = 100, lambda_g = 0.5, barrier = barrier_vol) ## End(Not run)
Creates distinct temporal patterns for each cluster. Used internally by
generate_synthetic_volume but exported for custom synthetic
data generation.
synthetic_time_patterns( n_clusters, n_time, pattern_types = c("orthogonal", "harmonic", "random") )synthetic_time_patterns( n_clusters, n_time, pattern_types = c("orthogonal", "harmonic", "random") )
n_clusters |
Number of clusters/patterns to generate. |
n_time |
Number of time points. |
pattern_types |
Type of patterns: |
A matrix of dimension n_clusters x n_time with one temporal
pattern per row.
This function tesselates a given mask volume into K clusters using k-means clustering applied to spatial coordinates. It returns a clustered mask volume object.
tesselate(mask, K = 100)tesselate(mask, K = 100)
mask |
A |
K |
An integer value specifying the number of clusters (default: 100). If |
An instance of ClusteredNeuroVol representing the clustered mask volume.
## Not run: # Assuming you have a NeuroVol object 'mask' and you want to create 150 clusters clustered_volume <- tesselate(mask, K = 150) ## End(Not run)## Not run: # Assuming you have a NeuroVol object 'mask' and you want to create 150 clusters clustered_volume <- tesselate(mask, K = 150) ## End(Not run)
Comprehensive test of all available clustering methods on synthetic ground truth data with cubic clusters.
test_all_clustering_methods( noise_levels = c(0, 0.1, 0.5), methods = c("flash3d", "corr_slic", "snic", "slic", "slice_msf", "supervoxels", "g3s", "rena"), n_clusters = 27, seed = 42 )test_all_clustering_methods( noise_levels = c(0, 0.1, 0.5), methods = c("flash3d", "corr_slic", "snic", "slic", "slice_msf", "supervoxels", "g3s", "rena"), n_clusters = 27, seed = 42 )
noise_levels |
Vector of noise standard deviations to test. Default c(0, 0.1, 0.5) tests perfect, low noise, and moderate noise. |
methods |
Vector of method names to test. Default tests all main methods. |
n_clusters |
Number of ground truth clusters (must be perfect cube). Default 27. |
seed |
Random seed for reproducibility. |
A data.frame with columns: method, noise_sd, ari, nmi, accuracy, n_clusters, time, perfect
## Not run: # Test all methods with 27 clusters results <- test_all_clustering_methods() print(results) # Test with 8 clusters (simpler) results <- test_all_clustering_methods(n_clusters = 8) # Test specific methods results <- test_all_clustering_methods( methods = c("flash3d", "corr_slic", "snic"), noise_levels = c(0, 0.2) ) ## End(Not run)## Not run: # Test all methods with 27 clusters results <- test_all_clustering_methods() print(results) # Test with 8 clusters (simpler) results <- test_all_clustering_methods(n_clusters = 8) # Test specific methods results <- test_all_clustering_methods( methods = c("flash3d", "corr_slic", "snic"), noise_levels = c(0, 0.2) ) ## End(Not run)
Runs a clustering method on synthetic ground truth data and reports accuracy metrics.
test_clustering_method( method, noise_sd = 0, n_clusters = 27, seed = 42, verbose = TRUE, ... )test_clustering_method( method, noise_sd = 0, n_clusters = 27, seed = 42, verbose = TRUE, ... )
method |
Clustering method name (e.g., "supervoxels", "snic", "flash3d") |
noise_sd |
Noise level for synthetic data. Default 0 (perfect separability). |
n_clusters |
Number of ground truth clusters (must be perfect cube). Default 27. |
seed |
Random seed for reproducibility. |
verbose |
Print results. Default TRUE. |
... |
Additional arguments passed to cluster4d() |
A list with:
metrics |
Output from clustering_accuracy() |
result |
Full clustering result object |
data |
Synthetic data used |
time |
Elapsed time in seconds |
## Not run: # Test FLASH-3D with 27 cubic clusters test_clustering_method("flash3d") # Test with 8 clusters test_clustering_method("slic", n_clusters = 8) # Test with noise test_clustering_method("snic", noise_sd = 0.5) ## End(Not run)## Not run: # Test FLASH-3D with 27 cubic clusters test_clustering_method("flash3d") # Test with 8 clusters test_clustering_method("slic", n_clusters = 8) # Test with noise test_clustering_method("snic", noise_sd = 0.5) ## End(Not run)
Applies a previously computed SVD compression to new data, ensuring consistency across multiple runs or when adding new voxels.
transform_new_data_svd(new_data, compression_result)transform_new_data_svd(new_data, compression_result)
new_data |
Numeric matrix (N_new x T) with same number of columns as the original training data. |
compression_result |
List returned by |
Compressed and normalized feature matrix (N_new x M) where M is the number of components in the original compression.
# Train on subset of data train_data <- matrix(rnorm(500 * 300), 500, 300) compression <- compress_features_svd(train_data, n_components = 15) # Apply to new data test_data <- matrix(rnorm(100 * 300), 100, 300) compressed_test <- transform_new_data_svd(test_data, compression)# Train on subset of data train_data <- matrix(rnorm(500 * 300), 500, 300) compression <- compress_features_svd(train_data, n_components = 15) # Apply to new data test_data <- matrix(rnorm(100 * 300), 100, 300) compressed_test <- transform_new_data_svd(test_data, compression)
Checks validity and quality of clustering results.
validate_cluster4d(result, vec = NULL, mask = NULL, tolerance = 1e-08)validate_cluster4d(result, vec = NULL, mask = NULL, tolerance = 1e-08)
result |
A cluster4d_result object |
vec |
Original NeuroVec data, required to verify feature centers. |
mask |
Original mask, required to verify geometry, voxel order, and physical coordinate centers. |
tolerance |
Relative numeric tolerance used when independently recomputing centers and coordinate centers. |
A list with valid, errors, warnings, and a compact summary.
Any schema or consistency defect sets valid = FALSE.