Skip to main content

SpectralBrain

SpectralBrain
Spectral Shape Analysis for Brain Structures

PyPI Python CI License DOI


SpectralBrain computes, analyzes, and visualizes spectral shape descriptors of brain structures — cortical surfaces, subcortical meshes, hippocampal subfields and white-matter tract surfaces, all as triangle meshes. It connects spectral geometry (the Laplace–Beltrami operator) to clinical neuroimaging, with one pipeline from FreeSurfer / HippUnfold output through statistically rigorous analysis to publication-ready figures.

SpectralBrain concept: input geometry → Laplace–Beltrami operator → spectral signature → descriptors

The core idea: any input geometry — cortical surface, subcortical/hippocampal mesh, or tract surface — is passed through the Laplace–Beltrami operator to obtain its eigenpairs {λ, φ}, from which pose- and mesh-free spectral descriptors (ShapeDNA, HKS, SI-HKS, WKS, GPS, BKS, functional maps, wavelets) are read out.

Statement of need

Volumetric and thickness measures collapse a structure's shape to a few scalars and are sensitive to registration and voxel size. Intrinsic spectral descriptors derived from the Laplace–Beltrami operator (LBO) — ShapeDNA, the Heat/Wave Kernel Signatures, and relatives — characterize shape independently of pose and parameterization, capturing geometry that volume alone misses. They are well established in geometry processing but scattered across research code, rarely packaged with the I/O, multi-site harmonization, correct multiple-comparison statistics, and rendering that a neuroimaging study needs end to end. SpectralBrain fills that gap as a single, tested library, with a primary focus on the hippocampus in mesial temporal lobe epilepsy, while remaining general to any brain surface mesh.

Key capabilities

  • Spectral descriptors — ShapeDNA, Heat Kernel Signature (HKS), Scale-Invariant HKS, Wave Kernel Signature (WKS), Global Point Signature (GPS), Bates–Kornfeld Signature (BKS) and its inverse, functional maps, and more — all from the LBO eigenpairs of a triangle mesh.
  • Beyond the LBO — a family of complementary operators that produce the same SpectralDecomposition (Dirac, Steklov, Hamiltonian, Hodge, magnetic, connection and sheaf Laplacians, Finsler, biharmonic, persistent Laplacian, graph spectra, classical morphometric spectra) in spectralbrain.spectral.operators.
  • Input-agnostic I/O — FreeSurfer surfaces and morphometry, GIfTI (.surf.gii / .func.gii / .shape.gii), NIfTI / MGZ volumes and labels, HippUnfold v1 & v2 outputs, .ply / .obj / .stl / .vtk and HDF5, with automatic format detection; volumes and label maps become LBO-ready meshes (volume_to_mesh, raw_to_mesh).
  • Cohort loading — BIDS / derivatives, FreeSurfer SUBJECTS_DIR, or an explicit list, loaded in parallel and stacked for group analysis; FreeSurfer measures can be resampled onto a common template; TractSeg bundle masks import directly as isosurface meshes.
  • Statistics done right — vertex-wise tests with genuine family-wise error control (max-statistic permutation), FDR, partial correlations with correct degrees of freedom, TFCE, the analytic DeLong AUC test, BCa bootstrap, ComBat / ComBat-GAM harmonization, and six PyMC Bayesian models.
  • Contiguous clustering & atlas comparison — a distance-dependent Chinese Restaurant Process (ddCRP) with a Normal-Inverse-Wishart collapsed marginal likelihood (spatial and fPCA-functional variants), consensus clustering, data-driven hyperparameter autotuning, and a cluster-vs-atlas suite (ARI/AMI/ NMI/VI, Dice/Jaccard, within-parcel homogeneity) reported against size-matched random parcellations, plus spatially-aware ARI (spARI) and eigenstrapping/ BrainSMASH spatial nulls for bounded surfaces.
  • Publication figures — a template-free six-view 3D renderer (vedo), unfolded flat-maps, Bayesian-posterior plots, advanced 3D tractography (direction- encoded/scalar streamlines, bundle surfaces with HKS/WKS overlays, multi-POV montages), and parcellation-vs-clustering grids (views × labelings) for hippocampi, brains, and bundles.

Installation

pip install spectralbrain

Optional feature sets (extras):

pip install "spectralbrain[bayesian]"   # PyMC, nutpie, NumPyro, BlackJAX, ArviZ
pip install "spectralbrain[viz]"        # vedo, fury, trimesh, cmcrameri, …
pip install "spectralbrain[gpu]"        # torch, CuPy, JAX (CUDA)
pip install "spectralbrain[neuro]"      # nilearn, dipy, pybids, templateflow, …
pip install "spectralbrain[operators]"  # gudhi, ripser, POT, networkx, … (non-LBO operators)
pip install "spectralbrain[tuning]"     # optuna (ddCRP autotuning; random fallback)
pip install "spectralbrain[full]"       # everything above

Requires Python 3.11–3.12.

API at a glance

The core API is on the top-level package; heavier statistics and visualization live in submodules you import explicitly (mirroring scipy.stats):

import spectralbrain as sb               # meshes, descriptors, I/O
import spectralbrain.statistics as sbstats   # frequentist + Bayesian
import spectralbrain.viz as sbviz             # 3D / 2D figures

Quick start

1 — Mesh → eigenpairs → descriptors

import spectralbrain as sb

# A BrainMesh from vertices (N, 3) and faces (M, 3).
vertices, faces = sb.io.load_gifti_surface("path/to/surf/gii")
mesh   = sb.BrainMesh(vertices, faces)
decomp = mesh.decompose(k=100)                       # 100 LBO eigenpairs

hks = sb.compute_hks(decomp, t_values=[1.0, 10.0, 100.0])   # (N, 3)
wks = sb.compute_wks(decomp, n_energies=50)                 # (N, 50)
dna = sb.compute_shapedna(decomp)                           # (k-1,) global

SpectralBrain is mesh-only. Point clouds live in the sibling library pointsbrain, which builds a point-cloud SpectralDecomposition and then reuses every descriptor, statistic and figure of this library unchanged.

2 — Compare two shapes

d = sb.shapedna_distance(dna_a, dna_b)   # pose-invariant spectral distance

3 — Vertex-wise group statistics with FWER control

import spectralbrain.statistics as sbstats

# controls, patients : (n_subjects, n_vertices) descriptor fields
res = sbstats.vertexwise_permutation(
    controls, patients,
    n_permutations=5000,
    correction="max",      # family-wise error via the max-statistic null
    seed=0,
)
significant = res.significant          # boolean mask, FWER-controlled

correction="fdr" and "none" are also available; vertexwise_ttest defaults to Welch's t-test.

4 — Compare two classifiers (analytic DeLong)

auc_new, auc_ref, p = sbstats.auc_comparison_delong(y_true, scores_new, scores_ref)

5 — Six-view 3D render (template-free)

import spectralbrain.viz as sbviz

fig = sbviz.plot_hippocampus_sixview(
    mesh, scalars=hks[:, 1],
    cmap="plasma", scalar_bar_title="HKS(t=10)",
    save="hipp_sixview.png",
)
# Pick any subset/order of the six canonical views:
fig = sbviz.plot_hippocampus_sixview(mesh, scalars=hks[:, 1],
                                     views=("superior", "left_lateral"))

Views: anterior, posterior, inferior, superior, left_lateral, right_lateral. It renders any surface — HippUnfold v2 den-8k, an aseg ROI mesh, or a whole cortical hemisphere — with no bundled template, so scalar↔vertex correspondence is guaranteed.

6 — Bayesian sparse regression (extra: [bayesian])

from spectralbrain.statistics import HorseshoeRegression

model = HorseshoeRegression(tau_prior=0.5).fit(X, y, sampler="nuts")
importance = model.feature_importance()   # sparse posterior shrinkage

7 — Contiguous ddCRP clustering + atlas comparison

The sampler maintains incremental per-component sufficient statistics (the cluster scatter is never recomputed inside the candidate loop) and caches the NIW marginal per cluster, so it scales to dense surfaces (~1-3 s/draw at ~7k vertices). Pass n_components to PCA-whiten the descriptors for a further speedup and better conditioning.

import spectralbrain.statistics as sbstats

# H : (V, d) per-vertex descriptors (e.g. fused HKS/WKS); vertices/faces from the mesh.
res = sbstats.cluster_ddcrp(H, faces=faces, vertices=vertices,
                            decay_kind="exponential")   # decay uses real edge distances
print(res)                                              # ClusterResult(method='ddcrp', n_clusters=…)

# Tune hyperparameters from the data (optuna if installed, else random search):
tuned = sbstats.autotune_ddcrp(H, faces=faces, vertices=vertices, n_trials=40)
final = tuned.cluster_result                            # refit ClusterResult

# Is the partition more atlas-like than a size-matched random parcellation?
report = sbstats.cluster_atlas_concordance(final.labels, atlas_labels,
                                           faces=faces, coords=vertices, n_null=1000)
print(report["metrics"]["ari"], report["ari_null"]["z"], report["spARI"]["spARI"])

8 — Tracts in 3D and parcellation-vs-clustering grids (extra: [viz])

import spectralbrain.viz as sbviz

# (a) advanced 3D tractography from several POVs (FURY; DEC orientation colours)
sl, _ = sbviz.load_streamlines("CST_left.trk", to_space="world")   # needs dipy
fig, _ = sbviz.streamlines_multiview(sl, views=("left", "anterior", "superior", "oblique"),
                                     out_path="cst_multiview.pdf")

# bundle surface from a TractSeg mask, with an HKS overlay
V, F = sbviz.mask_to_mesh(mask, affine=affine)
hks = sbviz.spectral_overlay(V, F, kind="hks")
sbviz.render_bundle_surface(V, F, scalars=hks, view="oblique", out_path="cst_hks.png")

# (b) 3D grid: columns = views, rows = a reference parcellation then each clustering
fig, meta = sbviz.plot_parcellation_vs_clusters(
    vertices, faces, parcellation=atlas_labels,
    clusterings={"ddCRP": res, "Leiden": leiden_res},   # ClusterResult or label arrays
    views=["left_lateral", "anterior", "superior"],
    save="parcellation_vs_clusters.png",
)

The grid works identically for hippocampi, whole brains, and bundle surfaces — it operates on any (vertices, faces) mesh plus a dict of per-vertex labelings.

Loading a cohort

import spectralbrain as sb

# BIDS / derivatives (one file per subject):
files = sb.discover_bids("/data/derivatives/hippunfold",
                         "sub-{sub}/surf/sub-{sub}_hemi-L_*thickness.shape.gii")
group = sb.load_group(files, mode="maps", n_jobs=8)
res   = sb.group_comparison(group, group.covariate("group"), test="ttest")

# FreeSurfer SUBJECTS_DIR, resampled to a common template:
group = sb.load_group_freesurfer("/data/fs", measure="thickness",
                                 template="fsaverage", n_jobs=8)

# TractSeg bundle masks → meshes ready for .decompose():
bundles = sb.load_tractseg("/data/sub-01/tractseg_output", output="mesh")
decomp  = bundles["CST_left"].decompose(k=80)

mode="pipeline" runs load → decompose → descriptor per subject (with an optional GPU backend=); mode="maps" stacks vertex-corresponded fields.

Compute backends

Eigen-decomposition and Bayesian sampling run on pluggable backends:

from spectralbrain.core.backends import TorchBackend       # or CupyBackend, JaxBackend
decomp = mesh.decompose(k=200, backend=TorchBackend())  # GPU eigsolve

Bayesian models accept sampler="auto" | "nuts" | "nutpie" | "numpyro" | "blackjax".

Structure & workflow

From inputs to inference, SpectralBrain is one coherent pipeline — load geometry → build the LBO & decompose → compute descriptors → group statistics → assess & visualize — assembled from a small set of focused, independently usable subpackages.

SpectralBrain workflow: inputs, main five-step workflow, and modular subpackage structure

(a) inputs — geometry, operator, cohort, atlas, spectral descriptors, and inference; (b) the five-step main workflow, ending in a lateralization effect-size read-out; (c) the modular structure — core · spectral · io · statistics · viz (compute backends now live in core).

The pipeline in practice

The five stages above are not just a diagram — they run end to end on real study designs. The figure below carries two analyses through the whole pipeline side by side and adds a parallel Bayesian lane, so the same data are assessed with both frequentist tools (max-statistic permutation, TFCE, DeLong AUC) and Bayesian ones (hierarchical models, horseshoe priors, HDI + ROPE, LOO).

SpectralBrain end-to-end demonstration: hippocampal lateralization, cortical morphometry, and a Bayesian inference lane carried across the five pipeline stages

An end-to-end walkthrough. Columns are worked analyses — hippocampal lateralization in MTLE-HS (HippUnfold den-8k surfaces, L vs R), cortical morphometry (MTLE-HS vs. controls, FreeSurfer / Schaefer-200), and a Bayesian lane (hierarchical model → horseshoe priors → variable selection → posterior effect size with HDI + ROPE → posterior-predictive check and LOO model comparison). Rows are the five pipeline stages — load geometry → decompose → descriptors → group statistics → assess — tied on the left to the subpackages that implement them (io · core · spectral · statistics · viz). Panels are illustrative, generated from synthetic example data to show the shape and flow of an analysis, not empirical results.

Documentation map

spectralbrain/
├── runtime.py            types, logging, seeds, progress, containers, joblib, RAM/VRAM guards
├── core/                 BrainMesh, SpectralDecomposition, GeometricObject, compute backends
├── io/                   loaders/savers, meshing, parcellation, cohorts, TractSeg, preprocessing
├── spectral/
│   ├── lbo/              descriptors, distances, wavelets, collections, anisotropic, eigenmodes
│   └── operators/        Dirac/Steklov, Hamiltonian, Hodge/Ricci/sheaf, persistent, Finsler, graphs, …
├── statistics/
│   ├── analysis.py       vertex-wise inference, effect sizes, RSA, networks, EDA/QC, recommendations
│   ├── bayesian.py       Bayesian models + MCMC samplers
│   ├── normative.py      harmonisation, normative models, method comparison
│   ├── surrogates.py     bootstrap, null models, synthetic data
│   └── clustering/       clustering methods, ddCRP, cluster-vs-atlas statistics
├── utils/                atlases, example data, helpers
└── viz/                  graphics · bayes · clusters · spectral · hipp · render3d
Subpackage What it provides
spectralbrain (top level) BrainMesh, decompose, all compute_* LBO descriptors, distances, I/O, cohort loading
spectralbrain.core BrainMesh, SpectralDecomposition, the GeometricObject protocol, CPU / Torch / CuPy / JAX eigensolvers
spectralbrain.io loaders/savers, BIDS & FreeSurfer discovery, load_group, template resampling, volume → mesh, TractSeg import, parcellation
spectralbrain.spectral.lbo Laplace–Beltrami descriptors, distances, wavelets, functional maps, spectral deformation, eigenmodes
spectralbrain.spectral.operators non-LBO spectral operators (lazy-loaded; extra [operators])
spectralbrain.statistics vertex-wise tests, TFCE, effect sizes, RSA, classification, EDA/QC, ComBat(-GAM), normative models, bootstrap & null models, Bayesian models and samplers, clustering
spectralbrain.viz one module per analysis module (graphics, bayes, clusters, spectral, hipp) on a shared 3D engine (render3d)

Upgrading from 0.0.x? The old → new import table is in CHANGELOG.md.

Validation

examples/example_clustering_tracts.py is a runnable end-to-end pipeline (HippUnfold hippocampus -> HKS/WKS -> ddCRP -> atlas stats -> 3D figures; synthetic fallback if no data). validation/validate_spari.py checks the spatially-aware Rand index: analytical properties (identity, label invariance, symmetry, reduction to the exact ARI as the spatial scale vanishes, chance level, locality monotonicity) run anywhere, plus an R cell-for-cell bridge (--with-r) against the published spARI package that justifies flipping validated_against_R=True.

Development

git clone https://github.com/rdneuro/spectralbrain
cd spectralbrain
uv sync --group dev          # or: pip install -e ".[full]" + dev tools
uv run pytest                # run the test suite
uv run ruff check src/ tests/

Citing

If SpectralBrain contributes to your work, please cite it. Someday, maybe, if we feel lucky, a JOSS paper will be submited; until then, cite the archived release on Zenodo:

Debona, R. SpectralBrain: Spectral Shape Analysis for Brain Structures. Zenodo. https://doi.org/10.5281/zenodo.21090748

The DOI 10.5281/zenodo.21090748 always resolves to the latest release. See CITATION.cff for a machine-readable citation — GitHub's "Cite this repository" button reads it.

License

MIT — see LICENSE.

Metadata

Release files for spectralbrain 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spectralbrain 0.1.0
File Size Uploaded
spectralbrain-0.1.0.tar.gz 5.1 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for spectralbrain 0.1.0
File Interpreter ABI Platform
spectralbrain-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 5.5 MB

Release files / spectralbrain-0.1.0.tar.gz

Download URL spectralbrain-0.1.0.tar.gz
Size 5.1 MB
Tags Source
SHA-256 checksum
How to use checksums
deb80177cea034c2c93ac1a9f5ae22e5739c9215d71b8a27201a2aea7d1f7df8
BLAKE2b-256 checksum
How to use checksums
e2a360cc3ff67ea7370978034b3a4a63eed9f9e65298d89bd8a4743c284e47d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / spectralbrain-0.1.0-py3-none-any.whl

Download URL spectralbrain-0.1.0-py3-none-any.whl
Size 455.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7a072889f1ca57d09959daf4496b9dea2e744db9e2c3317fccdbba8d5fef441c
BLAKE2b-256 checksum
How to use checksums
d1c7dcfd9daa78d0170b36cc52e68c772e606c68e3ee0310a6c8c60bb1e46b10
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page