spectralbrain.io.meshing#
Deterministic volume → surface meshing for well-conditioned LBO analysis.
The Laplace–Beltrami operator (and the descriptors built on it — ShapeDNA, HKS, WKS, …) is sensitive to triangle quality, not to vertex count. A mesh extracted directly from a binary label volume by plain marching cubes carries artefacts that corrupt the spectrum: the voxel staircase, sliver triangles (whose vanishing angles make cotangent weights blow up or turn negative), non-uniform sampling, and — for multi-label sources — non-manifold, multi-part, high-genus surfaces.
This module turns a volume into an LBO-ready mesh through deterministic, shape-agnostic geometry processing (no learned prior, so it never regularises pathological anatomy toward a “normal” shape):
- label → scalar fieldbinary mask → signed distance field (SDF)
(or Gaussian-smoothed occupancy)
Gaussian smoothing : band-limit the boundary, topology preserved
marching cubes : sub-voxel, staircase-free iso-surface
- topology cleanuplargest connected component, manifold repair,
watertight (closed structures only)
Taubin smoothing (λ/μ) : volume-preserving denoise
isotropic remeshing : ACVD → uniform, well-shaped triangles
Public API#
- volume_to_mesh
Volume (or label volume) →
(vertices, faces).raw=Truereproduces the legacy plain-marching-cubes path exactly;raw=False(default) applies the improvement pipeline.- refine_mesh
Apply steps 4–6 to an existing mesh (e.g. a surface that is already triangulated but poorly conditioned for the LBO).
Both are re-exported at spectralbrain.io and the package top level;
spectralbrain.BrainMesh.from_volume() is the object-oriented entry point.
Notes
closed=True (the default) is appropriate for closed anatomical structures
(hippocampus, subcortical nuclei): it uses an SDF, keeps a single connected
component, and repairs the surface to a watertight 2-manifold. closed=False
is the correct choice for open / branching / multi-part structures (e.g.
white-matter bundle masks): it skips the watertight and single-component steps
so that legitimate anatomy is never amputated.
Optional dependencies (lazily imported, with install hints): trimesh
(topology + Taubin), pyacvd + pyvista (isotropic remeshing),
pymeshfix (watertight repair). scikit-image and scipy are core.
Functions
|
Improve an existing triangle mesh for Laplace–Beltrami analysis (steps 4–6). |
|
Extract a mesh from a (label) volume, improved by default for the LBO. |
- spectralbrain.io.meshing.refine_mesh(vertices, faces, *, closed=True, keep_largest=None, watertight=None, taubin_iterations=12, taubin_lambda=0.5, taubin_nu=0.53, remesh=None, target_edge_mm=0.7, n_points=None, return_info=False)[source]#
Improve an existing triangle mesh for Laplace–Beltrami analysis (steps 4–6).
Applies topology cleanup, Taubin smoothing and isotropic remeshing to an already-triangulated surface. Use this when a mesh is available but poorly conditioned for the LBO (slivers, non-uniform sampling, small handles).
- Parameters:
vertices (ndarray, shape (N, 3))
faces (ndarray, shape (F, 3))
closed (bool) – Whether the surface should be a closed 2-manifold (True for anatomical closed structures; False for open/branching/multi-part surfaces). When True, defaults enable largest-component selection, watertight repair and remeshing; when False these default off so real anatomy is not amputated.
keep_largest (bool, optional) – Keep only the largest connected component. Default:
closed.watertight (bool, optional) – Repair to a watertight 2-manifold. Default:
closed.taubin_iterations (int) – Number of (λ, μ) Taubin cycles.
0disables smoothing.taubin_lambda (float) – Taubin factors (shrink-free requires
nu > lambda; trimesh uses the magnitude of the negative step asnu).taubin_nu (float) – Taubin factors (shrink-free requires
nu > lambda; trimesh uses the magnitude of the negative step asnu).remesh (bool, optional) – Apply isotropic ACVD remeshing. Default:
closed.target_edge_mm (float) – Desired mean edge length; sets the ACVD target vertex count.
n_points (int, optional) – Explicit ACVD target vertex count (overrides
target_edge_mm).return_info (bool) – If True, also return a provenance dict.
- Returns:
(vertices, faces) or (vertices, faces, info)
- Return type:
tuple[ndarray, ndarray] | tuple[ndarray, ndarray, dict[str, Any]]
- spectralbrain.io.meshing.volume_to_mesh(volume, affine, *, raw=False, label=None, level=0.5, step_size=1, closed=True, field_mode='sdf', presmooth_vox=0.5, sigma_vox=0.6, pad=4, return_info=False, **refine_kwargs)[source]#
Extract a mesh from a (label) volume, improved by default for the LBO.
- Parameters:
volume (ndarray, shape (X, Y, Z)) – Intensity or integer-label volume.
affine (ndarray, shape (4, 4)) – Voxel-to-world affine.
raw (bool) – If
True, skip all improvement and reproduce the legacy path exactly: plain marching cubes on the (optionally label-binarised) volume atlevelviaspectralbrain.core.marching_cubes(). IfFalse(default), run the deterministic improvement pipeline.label (int or sequence of int, optional) – Restrict to these label id(s) (mask =
np.isin(volume, label)). WhenNone, the volume is thresholded atlevel(raw path) or its>leveloccupancy is used (improved path).level (float) – Iso-level / threshold for the raw path and for label-free binarisation.
step_size (int) – Marching-cubes step for the raw path (larger = coarser/faster).
closed (bool) – Treat the structure as a closed 2-manifold (see
refine_mesh()). For open / branching / multi-part structures (e.g. white-matter bundle masks) passclosed=False.field_mode ({"sdf", "gaussian"}) – Scalar-field construction for the improved path. Forced to
"gaussian"whenclosed=False(an SDF iso-surface is ill-suited to open sheets).presmooth_vox (float) – Field-construction parameters (see
_mask_to_field()).sigma_vox (float) – Field-construction parameters (see
_mask_to_field()).pad (int) – Field-construction parameters (see
_mask_to_field()).return_info (bool) – If True, also return a provenance dict.
**refine_kwargs – Forwarded to
refine_mesh()(e.g.taubin_iterations,remesh,target_edge_mm,n_points,keep_largest,watertight).
- Returns:
(vertices, faces) or (vertices, faces, info)
- Return type:
tuple[ndarray, ndarray] | tuple[ndarray, ndarray, dict[str, Any]]
Notes
raw=Falsechanges the mesh relative to plain marching cubes (denser, smoother, uniformly triangulated, genus-0 for closed structures). This is a deliberate default so that meshes fed to the LBO are well-conditioned; passraw=Truefor byte-for-byte legacy behaviour.