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):

  1. label → scalar fieldbinary mask → signed distance field (SDF)

    (or Gaussian-smoothed occupancy)

  2. Gaussian smoothing : band-limit the boundary, topology preserved

  3. marching cubes : sub-voxel, staircase-free iso-surface

  4. topology cleanuplargest connected component, manifold repair,

    watertight (closed structures only)

  5. Taubin smoothing (λ/μ) : volume-preserving denoise

  6. isotropic remeshing : ACVD → uniform, well-shaped triangles

Public API#

volume_to_mesh

Volume (or label volume) → (vertices, faces). raw=True reproduces 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

refine_mesh(vertices, faces, *[, closed, ...])

Improve an existing triangle mesh for Laplace–Beltrami analysis (steps 4–6).

volume_to_mesh(volume, affine, *[, raw, ...])

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. 0 disables smoothing.

  • taubin_lambda (float) – Taubin factors (shrink-free requires nu > lambda; trimesh uses the magnitude of the negative step as nu).

  • taubin_nu (float) – Taubin factors (shrink-free requires nu > lambda; trimesh uses the magnitude of the negative step as nu).

  • 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 at level via spectralbrain.core.marching_cubes(). If False (default), run the deterministic improvement pipeline.

  • label (int or sequence of int, optional) – Restrict to these label id(s) (mask = np.isin(volume, label)). When None, the volume is thresholded at level (raw path) or its >level occupancy 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) pass closed=False.

  • field_mode ({"sdf", "gaussian"}) – Scalar-field construction for the improved path. Forced to "gaussian" when closed=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=False changes 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; pass raw=True for byte-for-byte legacy behaviour.