spectralbrain.BrainPointCloud#
- class spectralbrain.BrainPointCloud(points, metadata=None)[source]#
Bases:
objectUnstructured 3D point cloud for brain structures.
Implements
GeometricObject. No face connectivity — the Laplacian is built from a neighbourhood graph (kNN, ε-ball, or Belkin–Niyogi).- Parameters:
points (ndarray, shape (N, 3)) – Coordinates in world space (mm, RAS).
metadata (dict, optional) – Provenance (subject, hemisphere, structure, source, …).
Examples
>>> pc = BrainPointCloud.from_freesurfer_seg( ... "aseg.mgz", label_id=17, jitter=True) >>> decomp = pc.decompose(k=50, method="robust")
Methods
__init__(points[, metadata])Initialise from a (N, 3) coordinate array.
cluster([method, n_clusters, ...])Atlas-free spatial clustering of the point cloud.
compute_laplacian([method, k, epsilon, ...])Construct a graph Laplacian on the point cloud.
compute_normals([k, orient_to_centroid])Estimate per-point normals via local PCA.
decompose([k, laplacian_method, backend])Compute the spectral decomposition.
denoise([k, threshold_sigma])Remove density outliers (statistical outlier removal).
from_atlas_volume(atlas_path, label_id, *[, ...])Extract a point cloud from an arbitrary atlas NIfTI.
from_freesurfer_seg(seg_path, label_id, *[, ...])Load a FreeSurfer segmentation and extract a structure.
from_raw(raw_path, label_id, *[, ...])End-to-end: raw T1w/T2w/FLAIR → segment → point cloud.
from_surface(surface_path, *[, subsample, ...])Load a surface file and use its vertices as a point cloud.
from_tract_mask(mask_path, *[, threshold, ...])Extract a point cloud from a TractSeg binary tract mask.
from_tractography(trk_path, *[, sampling, ...])Extract a point cloud from tractography streamlines.
from_volume(label_volume, affine, label_id, *)Extract a point cloud from a volumetric label map.
local_curvature([k])Estimate per-point curvature from local PCA eigenvalues.
subsample(n, *[, seed])Return a subsampled copy via farthest-point sampling.
Approximate surface area via convex hull.
Attributes
Return the point coordinates array.
Cached spatial index.
Return the number of points in the cloud.
- classmethod from_atlas_volume(atlas_path, label_id, *, jitter=True, seed=None, subsample=None, metadata=None)[source]#
Extract a point cloud from an arbitrary atlas NIfTI.
The atlas volume must be in the same space as the subject (template space or registered native).
- Parameters:
atlas_path (PathLike) – NIfTI label volume (e.g. Schaefer in MNI).
label_id (int) – Atlas region ID.
jitter (as in
from_volume().)seed (as in
from_volume().)subsample (as in
from_volume().)metadata (dict, optional)
- Returns:
BrainPointCloud
- Return type:
- classmethod from_freesurfer_seg(seg_path, label_id, *, jitter=True, jitter_scale=0.25, seed=None, subsample=None, metadata=None)[source]#
Load a FreeSurfer segmentation and extract a structure.
Handles
aseg.mgz,aparc+aseg.mgz,ThalamicNuclei.v13.T1.mgz,amygNucVolumes.v22.mgz,hippoSfVolumes-T1.v22.mgz, or any integer label volume.- Parameters:
seg_path (PathLike) – Path to
.mgz/.nii.gzsegmentation.label_id (int) – Target label code.
jitter (as in
from_volume().)jitter_scale (as in
from_volume().)seed (as in
from_volume().)subsample (as in
from_volume().)metadata (dict, optional)
- Returns:
BrainPointCloud
- Return type:
- classmethod from_raw(raw_path, label_id, *, output_dir=None, gpu=None, jitter=True, seed=None, subsample=None, metadata=None)[source]#
End-to-end: raw T1w/T2w/FLAIR → segment → point cloud.
Chains skull-stripping and segmentation via Singularity containers, then extracts the target structure as a point cloud. No DL dependencies on host.
- Parameters:
raw_path (PathLike) – Raw anatomical NIfTI (any contrast).
label_id (int) – Target structure label.
output_dir (PathLike, optional) – Working directory for intermediate files.
gpu (bool, optional)
jitter (as in
from_volume().)seed (as in
from_volume().)subsample (as in
from_volume().)metadata (dict, optional)
- Returns:
BrainPointCloud
- Return type:
- classmethod from_surface(surface_path, *, subsample=None, seed=None, metadata=None)[source]#
Load a surface file and use its vertices as a point cloud.
Works with FreeSurfer surfaces (.white, .pial, .inflated), GIfTI (.surf.gii), HippUnfold outputs, or any mesh format.
- Parameters:
- Returns:
BrainPointCloud
- Return type:
- classmethod from_tract_mask(mask_path, *, threshold=0.5, jitter=True, seed=None, subsample=None, metadata=None)[source]#
Extract a point cloud from a TractSeg binary tract mask.
TractSeg outputs one NIfTI per tract (72 tracts). Each non-zero voxel becomes a point.
- Parameters:
mask_path (PathLike) – Binary tract mask NIfTI (from TractSeg).
threshold (float) – Binarisation threshold for probabilistic masks.
jitter (as in
from_volume().)seed (as in
from_volume().)subsample (as in
from_volume().)metadata (dict, optional)
- Returns:
BrainPointCloud
- Return type:
- classmethod from_tractography(trk_path, *, sampling='uniform', points_per_streamline=10, subsample=None, seed=None, metadata=None)[source]#
Extract a point cloud from tractography streamlines.
- Parameters:
trk_path (PathLike) –
.trk(TrackVis) or.tck(MRtrix) file.sampling (str) –
"all"— every point from every streamline."endpoints"— first + last point per streamline."midpoints"— middle point per streamline."uniform"— uniformly resample each streamline to points_per_streamline points.points_per_streamline (int) – For
sampling="uniform": points per streamline.subsample (int, optional) – FPS subsampling after extraction.
seed (int, optional)
metadata (dict, optional)
- Returns:
BrainPointCloud
- Return type:
- classmethod from_volume(label_volume, affine, label_id, *, jitter=True, jitter_scale=0.25, seed=None, subsample=None, metadata=None)[source]#
Extract a point cloud from a volumetric label map.
The most direct pathway:
mgz → np.array → point cloud. No marching cubes, no mesh reconstruction. Voxel centroids in world space become points.- Parameters:
label_volume (ndarray, shape (X, Y, Z)) – Integer label volume (e.g. from
aseg.mgz).affine (ndarray, shape (4, 4)) – Voxel-to-world affine.
label_id (int) – Target label (e.g. 17 = left hippocampus in aseg).
jitter (bool) – Add sub-voxel Gaussian noise to break grid artefacts.
jitter_scale (float) – Jitter σ in voxel units.
seed (int, optional) – RNG seed for jitter.
subsample (int, optional) – If set, apply FPS to reduce to this many points.
metadata (dict, optional)
- Returns:
BrainPointCloud
- Return type:
Examples
>>> data, affine = sb.io.load_nifti("aseg.mgz") >>> pc = BrainPointCloud.from_volume(data, affine, label_id=17)
- cluster(method='hdbscan', *, n_clusters=None, min_cluster_size=50, eps=None, **kwargs)[source]#
Atlas-free spatial clustering of the point cloud.
Assigns each point to a cluster without relying on any atlas or parcellation. Useful for data-driven subregion discovery.
- Parameters:
method (str) –
"hdbscan"— density-based, handles irregular shapes, auto-detects number of clusters (recommended)."spectral"— spectral clustering on kNN graph."kmeans"— simple, fast, spherical assumption."dbscan"— density-based, fixed epsilon.n_clusters (int, optional) – For methods that require it (spectral, kmeans).
min_cluster_size (int) – For HDBSCAN.
eps (float, optional) – For DBSCAN.
**kwargs – Passed to the underlying clustering algorithm.
- Returns:
labels (ndarray, shape (N,), int) – Cluster assignment per point.
-1= noise (HDBSCAN / DBSCAN).- Return type:
- compute_laplacian(method='robust', *, k=30, epsilon=None, sigma=None, robust_mollify=1e-05)[source]#
Construct a graph Laplacian on the point cloud.
- Parameters:
method (str) –
"knn"— Gaussian-weighted kNN graph Laplacian."belkin_niyogi"— heat-kernel weighted Laplacian with provable convergence to the continuous LBO (Belkin & Niyogi, JCSS 2008)."robust"— Sharp & Crane tufted Laplacian (robust to noise and non-uniform density).k (int) – Number of neighbours for kNN and Belkin–Niyogi.
epsilon (float, optional) – Bandwidth for ε-ball graph.
None= auto from mean kNN distance.sigma (float, optional) – Gaussian kernel bandwidth.
None= auto (median distance heuristic).robust_mollify (float) – Mollification for the robust method.
- Returns:
L (SparseMatrix, shape (N, N))
M (MassMatrix, shape (N, N))
- Return type:
- compute_normals(k=15, *, orient_to_centroid=True)[source]#
Estimate per-point normals via local PCA.
The normal at each point is the eigenvector of the local covariance matrix corresponding to the smallest eigenvalue (the direction of least variance in the neighbourhood).
- decompose(k=50, *, laplacian_method='robust', backend=None, **kwargs)[source]#
Compute the spectral decomposition.
- Parameters:
k (int) – Number of eigenpairs.
laplacian_method (str) – Passed to
compute_laplacian().backend (Backend, optional)
**kwargs – Extra args for
compute_laplacian()andbackend.eigsh().
- Returns:
SpectralDecomposition
- Return type:
- denoise(k=10, threshold_sigma=2.5)[source]#
Remove density outliers (statistical outlier removal).
- Parameters:
- Returns:
BrainPointCloud – Cleaned copy.
- Return type:
- local_curvature(k=15)[source]#
Estimate per-point curvature from local PCA eigenvalues.
The ratio λ₀ / (λ₀ + λ₁ + λ₂) of the smallest eigenvalue to the sum is a measure of local planarity — smaller values mean flatter (lower curvature), larger values mean more curved.
- Parameters:
k (int) – Neighbours for local PCA.
- Returns:
curvature (ndarray, shape (N,)) – Normalised planarity measure (0 = flat, 1 = isotropic).
linearity (ndarray, shape (N,)) – (λ₀ - λ₁) / λ₀ — high for tube-like structures.
- Return type:
tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]
- subsample(n, *, seed=None)[source]#
Return a subsampled copy via farthest-point sampling.
- Parameters:
- Returns:
BrainPointCloud
- Return type:
- surface_area()[source]#
Approximate surface area via convex hull.
For point clouds without face topology, the convex hull area is a rough proxy. Used for eigenvalue normalisation.
- Return type: