spectralbrain.spectral.distances#

Spectral distance metrics between shapes and between points.

Two categories of distance:

Shape-to-shape — compare two different shapes via their eigenvalue spectra (no point correspondence needed):

Point-to-point — distances within a single shape, computed from the eigenpairs of that shape:

All point-to-point distances share a unifying form:

\[d^2(x, y) = \sum_i g(\lambda_i)\, (\varphi_i(x) - \varphi_i(y))^2\]

where g(λ) is a spectral filter that defines the metric.

Functions

aggregate_to_networks(connectome, ...[, ...])

Aggregate a parcel-level connectome to network level.

biharmonic_distance(decomp, *[, indices])

Biharmonic distance — parameter-free intrinsic metric.

build_geometric_connectome(parcel_descriptors, *)

Build a ROI × ROI geometric connectome from parcel descriptors.

commute_time_distance(decomp, *[, indices, ...])

Commute-time distance from random walk theory.

descriptor_distance(desc_a, desc_b, *[, method])

Distance between two descriptor distributions.

diffusion_distance(decomp, t, *[, indices])

Diffusion distance — multi-scale intrinsic metric.

diffusion_distance_multiscale(decomp, ...[, ...])

Diffusion distance at multiple time scales.

shapedna_distance(dna_a, dna_b, *[, metric, ...])

Simple distance between two ShapeDNA vectors.

wesd(dna_a, dna_b, *[, p, normalize])

Weighted Spectral Distance between two ShapeDNA vectors.

wesd_matrix(dna_collection, *[, p, normalize])

Pairwise WESD matrix for a collection of ShapeDNA vectors.

spectralbrain.spectral.distances.aggregate_to_networks(connectome, parcel_labels, network_assignments, *, aggregation='mean')[source]#

Aggregate a parcel-level connectome to network level.

Parameters:
  • connectome (ndarray, shape (R, R)) – Parcel-level distance matrix.

  • parcel_labels (list) – Parcel labels (from build_geometric_connectome()).

  • network_assignments (dict of {parcel_label: network_name}) – Mapping from each parcel to its canonical network.

  • aggregation (str) – "mean" or "median" within each block.

Returns:

  • network_matrix (ndarray, shape (K, K))

  • network_names (list of str)

Return type:

tuple[ndarray, list]

spectralbrain.spectral.distances.biharmonic_distance(decomp, *, indices=None)[source]#

Biharmonic distance — parameter-free intrinsic metric.

\[d_B^2(x, y) = \sum_{i=1}^{k} \frac{(\varphi_i(x) - \varphi_i(y))^2}{\lambda_i^2}\]

Smooth, locally isotropic, globally shape-aware, robust to topological noise. No tuneable parameters.

Parameters:
  • decomp (SpectralDecomposition)

  • indices (ndarray of int, optional) – Compute distances only from these source vertices.

Returns:

ndarray, shape (M, N) or (N, N)

Return type:

ndarray[tuple[Any, …], dtype[floating]]

References

Lipman Y, Rustamov RM, Funkhouser TA. Biharmonic distance. ACM TOG 29(3):27, 2010.

spectralbrain.spectral.distances.build_geometric_connectome(parcel_descriptors, *, method='wasserstein', **kwargs)[source]#

Build a ROI × ROI geometric connectome from parcel descriptors.

For each pair of parcels, computes the distance between their descriptor distributions.

Parameters:
  • parcel_descriptors (dict of {label: ndarray}) – Mapping from parcel label to descriptor array. Each value is shape (N_parcel, T) or (N_parcel,).

  • method (str) – Distance method (see descriptor_distance()).

  • **kwargs – Extra args for the distance function.

Returns:

  • matrix (ndarray, shape (R, R)) – Symmetric distance matrix.

  • labels (list) – Ordered parcel labels corresponding to matrix rows/columns.

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], list]

Examples

>>> parcels = sb.io.apply_parcellation(verts, faces, labels)
>>> descs = {}
>>> for lab, (v, f) in parcels.items():
...     mesh = BrainMesh(v, f)
...     decomp = mesh.decompose(k=30)
...     descs[lab] = compute_hks(decomp, n_times=20)
>>> C, labs = build_geometric_connectome(descs, method="wasserstein")
spectralbrain.spectral.distances.commute_time_distance(decomp, *, indices=None, warn_large=True)[source]#

Commute-time distance from random walk theory.

\[d_{CT}^2(x, y) = \sum_{i=1}^{k} \frac{(\varphi_i(x) - \varphi_i(y))^2}{\lambda_i}\]

Warning

Degenerates on large graphs (N > 50 k) — converges to a function of vertex degree only (von Luxburg et al. 2010). Use biharmonic distance instead for large meshes.

Parameters:
Returns:

ndarray, shape (M, N) or (N, N)

Return type:

ndarray[tuple[Any, …], dtype[floating]]

spectralbrain.spectral.distances.descriptor_distance(desc_a, desc_b, *, method='wasserstein', **kwargs)[source]#

Distance between two descriptor distributions.

Used to build the geometric connectome: for each pair of parcels, compute the distance between their descriptor distributions.

Parameters:
  • desc_a (ndarray, shape (N_a,) or (N_a, T)) – Descriptor values at vertices of parcel A.

  • desc_b (ndarray, shape (N_b,) or (N_b, T)) – Descriptor values at vertices of parcel B.

  • method (str) – "wasserstein" — 1D Wasserstein (Earth Mover’s Distance). "mmd" — Maximum Mean Discrepancy with Gaussian kernel. "euclidean" — L2 between distribution means. "cosine" — cosine distance between means. "correlation" — 1 − Pearson r between aggregated features.

Returns:

float

Return type:

float

Notes

For 1D descriptors (ScalarMap), Wasserstein is exact and O(N log N). For multi-dimensional descriptors (DescriptorMatrix), the columns are treated independently and distances are averaged.

spectralbrain.spectral.distances.diffusion_distance(decomp, t, *, indices=None)[source]#

Diffusion distance — multi-scale intrinsic metric.

\[D_t^2(x, y) = \sum_{i=1}^{k} e^{-2\lambda_i t}\, (\varphi_i(x) - \varphi_i(y))^2\]

Small t ≈ geodesic; large t ≈ global diffusion.

Parameters:
Returns:

ndarray, shape (M, N) or (N, N)

Return type:

ndarray[tuple[Any, …], dtype[floating]]

References

Coifman RR, Lafon S. Diffusion maps. Applied and Computational Harmonic Analysis 21(1):5–30, 2006.

spectralbrain.spectral.distances.diffusion_distance_multiscale(decomp, t_values, *, indices=None)[source]#

Diffusion distance at multiple time scales.

Parameters:
Returns:

ndarray, shape (T, M, N) or (T, N, N) – Distance matrix per time scale.

Return type:

ndarray

spectralbrain.spectral.distances.shapedna_distance(dna_a, dna_b, *, metric='euclidean', cov_inv=None)[source]#

Simple distance between two ShapeDNA vectors.

Parameters:
  • dna_a (ndarray, shape (d,))

  • dna_b (ndarray, shape (d,))

  • metric (str) – "euclidean" — L2 distance. "mahalanobis" — requires cov_inv. "cosine" — 1 − cos(a, b).

  • cov_inv (ndarray, shape (d, d), optional) – Inverse covariance matrix for Mahalanobis.

Returns:

float

Return type:

float

spectralbrain.spectral.distances.wesd(dna_a, dna_b, *, p=2.0, normalize=True)[source]#

Weighted Spectral Distance between two ShapeDNA vectors.

A pseudometric with convergence guarantees — the series converges for p > d/2 where d is the dimension of the manifold (d = 2 for surfaces, so p > 1 suffices).

\[\text{WESD}^p(\Omega_1, \Omega_2) = \left( \sum_{i=1}^{k} \frac{|\lambda_i^{(1)} - \lambda_i^{(2)}|} {\lambda_i^{(1)} \cdot \lambda_i^{(2)}} \right)^{1/p}\]
Parameters:
  • dna_a (ndarray, shape (d,)) – ShapeDNA eigenvalue sequences (skip λ₀).

  • dna_b (ndarray, shape (d,)) – ShapeDNA eigenvalue sequences (skip λ₀).

  • p (float) – Exponent (must be > 1 for 2D surfaces).

  • normalize (bool) – Map to [0, 1) via WESD / (1 + WESD).

Returns:

float – WESD distance.

Return type:

float

References

Konukoglu E, Glocker B, Criminisi A, Pohl KM. WESD — Weighted Spectral Distance for measuring shape dissimilarity. IEEE TPAMI 35(9):2284–2297, 2013.

spectralbrain.spectral.distances.wesd_matrix(dna_collection, *, p=2.0, normalize=True)[source]#

Pairwise WESD matrix for a collection of ShapeDNA vectors.

Parameters:
  • dna_collection (ndarray, shape (S, d)) – S shapes, each with d-dimensional ShapeDNA.

  • p (float)

  • normalize (bool)

Returns:

ndarray, shape (S, S) – Symmetric WESD distance matrix.

Return type:

ndarray[tuple[Any, …], dtype[floating]]