Skip to content

API Reference

meshmash.pipeline

chunked_hks_pipeline(mesh, query_indices=None, simplify_agg=7, simplify_target_reduction=0.7, overlap_distance=20000, max_vertex_threshold=20000, min_vertex_threshold=200, max_overlap_neighbors=40000, n_components=32, t_min=50000.0, t_max=20000000.0, max_eigenvalue=5e-06, robust=True, mollify_factor=1e-05, truncate_extra=True, drop_first=True, decomposition_dtype=np.float64, compute_hks_kwargs={}, nuc_point=None, distance_threshold=3.0, auxiliary_features=True, n_jobs=-1, verbose=False)

Compute HKS features and aggregate them across overlapping mesh chunks.

.. deprecated:: Prefer condensed_hks_pipeline, which is more memory-efficient because it aggregates features within each chunk before stitching. This function performs aggregation after all chunk features are stitched together, which requires holding the full-mesh feature matrix in memory.

Runs the following pipeline:

  1. Optional mesh simplification via fast-simplification.
  2. Spectral bisection of the mesh into overlapping chunks (MeshStitcher).
  3. Computation of compute_hks per chunk.
  4. Connectivity-constrained Ward agglomeration of vertices into local domains (agglomerate_split_mesh).
  5. Area-weighted aggregation of HKS features to each domain (aggregate_features).

Parameters:

Name Type Description Default
mesh

Input mesh. Either a (vertices, faces) tuple or an object with vertices and faces attributes.

required
query_indices

Vertex indices of interest. If provided, only chunks containing these vertices are processed. None processes all chunks.

None
simplify_agg

Decimation aggressiveness (0–10). Higher values are faster but reduce mesh quality. Low values may prevent reaching simplify_target_reduction.

7
simplify_target_reduction

Fraction of triangles to remove during simplification. None skips simplification.

0.7
overlap_distance

Geodesic radius used to grow each chunk into its overlap region. Larger values reduce boundary artefacts for long timescales but increase compute time.

20000
max_vertex_threshold

Maximum vertices per core chunk before overlapping.

20000
min_vertex_threshold

Minimum component size; smaller components are discarded.

200
max_overlap_neighbors

Cap on overlap region size (number of nearest neighbours); overrides overlap_distance when set.

40000
n_components

Number of HKS timescales. Timescales are log-spaced between t_min and t_max and determine the number of HKS features per vertex.

32
t_min

Minimum diffusion timescale.

50000.0
t_max

Maximum diffusion timescale.

20000000.0
max_eigenvalue

Maximum Laplacian eigenvalue used in the HKS computation.

5e-06
robust

If True, use the robust Laplacian for HKS (recommended).

True
mollify_factor

Mollification factor for the robust Laplacian.

1e-05
truncate_extra

If True, discard eigenpairs that overshoot max_eigenvalue.

True
drop_first

If True, drop the first (area-proportional) eigenpair.

True
decomposition_dtype

Floating-point dtype for the eigendecomposition.

float64
compute_hks_kwargs dict

Extra keyword arguments forwarded to compute_hks.

{}
nuc_point

Coordinates of the nucleus/reference point. If provided, a distance_to_nucleus column is added to the condensed node table.

None
distance_threshold

Ward linkage-distance threshold used to cut the agglomeration tree into local domains.

3.0
auxiliary_features

If True, append condensed node-table columns (centroid, area, etc.) to the aggregated feature DataFrame.

True
n_jobs Optional[int]

Number of parallel workers for Parallel. -1 uses all available cores.

-1
verbose

Verbosity level.

False

Returns:

Type Description
Result

The mesh after simplification.

Result

The mapping from the original mesh to the simplified mesh. Has length of the number of vertices in the original mesh; each element contains the index that the vertex maps to in the simplified mesh.

Result

The mesh stitcher object. Contains information about the mesh chunks and their overlaps.

Result

The HKS features for each vertex in the simplified mesh.

Result

The aggregated HKS features for each domain in the mesh.

Result

The labels for each vertex in the simplified mesh, indicating which domain it belongs to.

Result

Timing information for each step of the pipeline.

Notes

This pipeline consists of the following steps:

1. Mesh simplification, using https://github.com/pyvista/fast-simplification.
2. Mesh splitting, using a routine which iteratively does spectral bisection of
   the mesh until all chunks are below the `max_vertex_threshold`. These chunks
   are then grown to overlap using the `overlap_distance` parameter.
3. Computation of the heat kernel signature of Sun et al (2008). This routine
   uses the robust laplacian of Crane et al. (2020) for more stable results. It
   also leverages the band-by-band eigensolver method of Vallet and Levy (2008).
4. Agglomeration of the mesh into local domains which are bounded in the
   variance of the HKS features. This uses the implementation of Ward's method
   in scikit-learn which allows for a connectivity constraint.
5. Aggregation of the computed features to the local domains. This takes the
   area-weighted mean of the features for each domain.

compute_condensed_hks(mesh, n_components=32, t_min=50000.0, t_max=20000000.0, max_eigenvalue=1e-05, robust=True, mollify_factor=1e-05, truncate_extra=True, drop_first=True, decomposition_dtype=np.float32, compute_hks_kwargs={}, distance_threshold=3.0)

Compute HKS features and aggregate them on a single (unsplit) mesh.

This is a lightweight helper used internally by condensed_hks_pipeline to process individual submeshes. For large meshes, use the pipeline functions instead.

Parameters:

Name Type Description Default
mesh

Input mesh accepted by interpret_mesh.

required
n_components

Number of HKS timescales.

32
t_min

Minimum diffusion timescale.

50000.0
t_max

Maximum diffusion timescale.

20000000.0
max_eigenvalue

Maximum Laplacian eigenvalue for the HKS computation.

1e-05
robust

If True, use the robust Laplacian.

True
mollify_factor

Mollification factor for the robust Laplacian.

1e-05
truncate_extra

If True, discard eigenpairs past max_eigenvalue.

True
drop_first

If True, drop the first (area-proportional) eigenpair.

True
decomposition_dtype

Floating-point dtype for the eigendecomposition.

float32
compute_hks_kwargs dict

Extra keyword arguments forwarded to compute_hks.

{}
distance_threshold

Ward linkage-distance threshold for agglomeration.

3.0

Returns:

Name Type Description
condensed_features DataFrame

Per-domain aggregated HKS feature DataFrame indexed by domain label (including -1 for unassigned vertices).

labels ndarray

Per-vertex domain label array of length V.

condensed_hks_pipeline(mesh, simplify_agg=7, simplify_target_reduction=0.7, overlap_distance=20000, max_vertex_threshold=20000, min_vertex_threshold=200, max_overlap_neighbors=60000, n_components=32, t_min=50000.0, t_max=20000000.0, max_eigenvalue=1e-05, robust=True, mollify_factor=1e-05, truncate_extra=True, drop_first=True, decomposition_dtype='float32', compute_hks_kwargs={}, nuc_point=None, distance_threshold=3.0, auxiliary_features=True, n_jobs=-1, verbose=False)

Compute HKS features and produce a condensed node-edge graph of a mesh.

This is the primary entry point for the HKS pipeline. It is more memory-efficient than chunked_hks_pipeline because features are aggregated within each submesh chunk before the results are combined, rather than stitching the full per-vertex feature matrix first.

Parameters:

Name Type Description Default
mesh

Input mesh. Either a (vertices, faces) tuple or an object with vertices and faces attributes.

required
simplify_agg

Decimation aggressiveness (0–10). Higher values are faster but reduce mesh quality. Low values may prevent reaching simplify_target_reduction.

7
simplify_target_reduction

Fraction of triangles to remove during simplification. None skips simplification.

0.7
overlap_distance

Geodesic radius used to grow each chunk into its overlap region.

20000
max_vertex_threshold

Maximum vertices per core chunk before overlapping.

20000
min_vertex_threshold

Minimum component size; smaller components are discarded.

200
max_overlap_neighbors

Cap on overlap region size (number of nearest neighbours); overrides overlap_distance when set.

60000
n_components

Number of HKS timescales. Timescales are log-spaced between t_min and t_max and determine the number of HKS features per vertex.

32
t_min

Minimum diffusion timescale.

50000.0
t_max

Maximum diffusion timescale.

20000000.0
max_eigenvalue

Maximum Laplacian eigenvalue used in the HKS computation.

1e-05
robust

If True, use the robust Laplacian for HKS (recommended).

True
mollify_factor

Mollification factor for the robust Laplacian.

1e-05
truncate_extra

If True, discard eigenpairs that overshoot max_eigenvalue.

True
drop_first

If True, drop the first (area-proportional) eigenpair.

True
decomposition_dtype

Floating-point dtype for the eigendecomposition.

'float32'
compute_hks_kwargs dict

Extra keyword arguments forwarded to compute_hks.

{}
nuc_point

Coordinates of the nucleus/reference point. If provided, a distance_to_nucleus column is added to the condensed node table.

None
distance_threshold

Ward linkage-distance threshold used to cut the agglomeration tree into local domains.

3.0
auxiliary_features

If True, append condensed node-table columns (centroid, area, etc.) to the aggregated feature DataFrame.

True
n_jobs Optional[int]

Number of parallel workers for Parallel. -1 uses all available cores.

-1
verbose

Verbosity level.

False

Returns:

Name Type Description
simple_mesh CondensedHKSResult

The simplified mesh as a (vertices, faces) tuple.

mapping CondensedHKSResult

Array of length V_original mapping each original vertex to its index in the simplified mesh. -1 for discarded vertices.

stitcher CondensedHKSResult

Fitted MeshStitcher for the simplified mesh.

simple_labels CondensedHKSResult

Per-vertex domain label array for the simplified mesh.

labels CondensedHKSResult

Per-vertex domain label array for the original mesh.

condensed_features CondensedHKSResult

Per-domain aggregated feature DataFrame (log-HKS + optional auxiliary features), indexed by domain label.

condensed_nodes CondensedHKSResult

Node table of the condensed mesh graph; see condense_mesh_to_graph.

condensed_edges CondensedHKSResult

Edge table of the condensed mesh graph.

timing_info CondensedHKSResult

Dictionary with wall-clock times (seconds) for each pipeline step.

Notes

This pipeline consists of the following steps:

  1. Mesh simplification via fast-simplification.
  2. Spectral bisection into overlapping chunks (MeshStitcher).
  3. Per-chunk: compute_hks, Ward agglomeration, and area-weighted aggregation (compute_condensed_hks). Aggregating before stitching keeps memory use proportional to the chunk size rather than the full mesh.
  4. Global label reconciliation across chunks (fix_split_labels).
  5. Assembly of the condensed node-edge graph (condense_mesh_to_graph).

meshmash.morphometry_pipeline

component_morphometry_pipeline(mesh, labels, select_label, post_synapse_mappings=None, vertex_features=None, split_laplacian='graph', split_threshold=None, split_min_size=10, bound_volume_threshold=None, verbose=False)

Measure morphometric properties of labeled mesh components.

For each connected component whose vertices carry select_label, estimates volume, surface area, sphericity, PCA principal values, and medoid position. Components may be recursively split by spectral bisection if their Fiedler eigenvalue exceeds split_threshold.

Parameters:

Name Type Description Default
mesh

Input mesh accepted by interpret_mesh. Vertex coordinates are expected to be in nanometres.

required
labels

Per-vertex integer label array of length V.

required
select_label

The label value whose components are to be measured.

required
post_synapse_mappings

Array of vertex indices (length = number of known post-synapses). If provided, a n_post_synapses column is added to the results table counting how many synapses map to each component.

None
vertex_features

Reserved for future use; currently unused.

None
split_laplacian

Laplacian variant used for spectral bisection when split_threshold is set. Only 'graph' is currently supported.

'graph'
split_threshold

Fiedler eigenvalue threshold for recursive splitting. A component is split into two sub-components when its Fiedler eigenvalue is below this value (smaller Fiedler eigenvalue indicates a more elongated / weakly connected component). None disables splitting.

None
split_min_size

Minimum number of vertices each split sub-component must have for the split to be accepted.

10
bound_volume_threshold

If set, skip components whose axis-aligned bounding-box volume exceeds this value (in μm³).

None
verbose

If True, display a progress bar.

False

Returns:

Name Type Description
results

DataFrame indexed by component_id with morphometric columns: size_nm3, area_nm2, sphericity, x, y, z (medoid), pca_val_1/2/3, max_dt_nm, mean_dt_nm, n_vertices, n_faces, and optionally n_post_synapses.

corrected_components

Per-vertex component label array (same length as labels), updated to reflect any splits. Vertices not in a valid measured component receive label -1.

meshmash.decompose

decompose_laplacian(L, M, n_components=100, op_inv=None, sigma=-1e-10, tol=1e-10, ncv=None, prefactor=None)

Solve the generalised eigenvalue problem for a mesh Laplacian.

Computes the n_components smallest-magnitude eigenpairs of :math:L \phi = \lambda M \phi using ARPACK shift-invert mode. For small matrices the dense solver eigh is used instead.

Parameters:

Name Type Description Default
L sparray

Sparse cotangent-weight Laplacian matrix, shape (V, V).

required
M sparray

Sparse diagonal mass (area) matrix, shape (V, V).

required
n_components int

Number of smallest eigenvalues/eigenvectors to compute.

100
op_inv Optional[LinearOperator]

Pre-factored inverse operator to accelerate the ARPACK solve. If None and prefactor is also None, no pre-factorisation is performed.

None
sigma float

Shift applied in shift-invert mode. A small negative value ensures the solver targets the smallest non-negative eigenvalues.

-1e-10
tol float

Convergence tolerance passed to eigsh.

1e-10
ncv Optional[int]

Number of Lanczos vectors. None lets ARPACK choose.

None
prefactor Optional[str]

Pre-factorisation strategy. Currently only 'lu' (sparse LU via splu) is supported.

None

Returns:

Name Type Description
eigenvalues ndarray

Array of eigenvalues sorted in ascending order, shape (n_components,).

eigenvectors ndarray

Array of corresponding eigenvectors, shape (V, n_components).

decompose_mesh(mesh, n_components=100, op_inv=None, sigma=-1e-10, tol=1e-10, robust=True, mollify_factor=1e-05, prefactor=None)

Compute the Laplacian eigendecomposition of a mesh.

Builds the cotangent Laplacian and mass matrix with cotangent_laplacian, then delegates to decompose_laplacian.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
n_components int

Number of smallest eigenpairs to compute.

100
op_inv Optional[LinearOperator]

Pre-factored inverse operator; see decompose_laplacian.

None
sigma float

Shift for ARPACK shift-invert mode.

-1e-10
tol float

Convergence tolerance.

1e-10
robust bool

If True, use the robust Laplacian (see cotangent_laplacian).

True
mollify_factor float

Mollification factor for the robust Laplacian.

1e-05
prefactor Optional[str]

Pre-factorisation strategy; see decompose_laplacian.

None

Returns:

Name Type Description
eigenvalues ndarray

Sorted eigenvalues, shape (n_components,).

eigenvectors ndarray

Corresponding eigenvectors, shape (V, n_components).

decompose_laplacian_by_bands(L, M, max_eigenvalue=1e-09, band_size=50, truncate_extra=True, verbose=False)

Compute eigenpairs of a mesh Laplacian up to a maximum eigenvalue using a band-by-band approach.

Instead of computing all eigenpairs at once (which is slow for large meshes), this routine incrementally solves bands of band_size eigenpairs, advancing the ARPACK shift to stay near the frontier of already-computed eigenvalues. The result is equivalent to calling decompose_laplacian with a sufficiently large n_components but uses less memory and is faster in practice.

Parameters:

Name Type Description Default
L sparray

Sparse cotangent-weight Laplacian matrix, shape (V, V).

required
M sparray

Sparse diagonal mass (area) matrix, shape (V, V).

required
max_eigenvalue float

Stop once the largest computed eigenvalue exceeds this value.

1e-09
band_size int

Number of eigenpairs computed per ARPACK call. Does not affect the result, only performance.

50
truncate_extra bool

If True, discard any eigenpairs whose eigenvalue exceeds max_eigenvalue (the last band may overshoot by up to band_size pairs).

True
verbose Union[bool, int]

Verbosity level. 0 or False is silent; >=1 shows a progress bar; >=2 also prints per-band diagnostics.

False

Returns:

Name Type Description
eigenvalues ndarray

Sorted eigenvalues, shape (K,) where K depends on max_eigenvalue.

eigenvectors ndarray

Corresponding eigenvectors, shape (V, K).

Notes

The band-shifting heuristic follows Section 4.1 of [1].

References

[1] B. Vallet and B. Levy, "Spectral Geometry Processing with Manifold Harmonics", Computer Graphics Forum, 27(2):251-260, 2008.

get_hks_filter(t_max=None, t_min=None, n_scales=32, dtype=np.float64)

Build a heat-kernel spectral filter for use with spectral_geometry_filter.

Returns a callable that converts an array of Laplacian eigenvalues into a 2-D array of HKS filter coefficients.

Parameters:

Name Type Description Default
t_max Optional[float]

Largest diffusion timescale.

None
t_min Optional[float]

Smallest diffusion timescale.

None
n_scales int

Number of timescales (= number of output HKS features). Scales are spaced logarithmically between t_min and t_max.

32
dtype dtype

Floating-point dtype for the output coefficients.

float64

Returns:

Type Description
Callable[[ndarray], ndarray]

Callable that accepts a 1-D eigenvalue array of length K and returns a (n_scales, K) coefficient array.

construct_bspline_basis(e_min, e_max, n_components)

Construct a set of B-spline basis functions spanning an eigenvalue range.

Parameters:

Name Type Description Default
e_min float

Left boundary of the eigenvalue domain.

required
e_max float

Right boundary of the eigenvalue domain.

required
n_components int

Number of basis functions (= number of output geometry-vector features).

required

Returns:

Type Description
list[BSpline]

List of n_components cubic BSpline basis elements, each non-zero over a compact sub-interval of [e_min, e_max].

construct_bspline_filter(e_min, e_max, n_components)

Build a B-spline spectral filter for use with spectral_geometry_filter.

Creates a bank of n_components cubic B-spline basis functions covering [e_min, e_max] via construct_bspline_basis and wraps them in a callable that converts eigenvalues to filter coefficients.

Parameters:

Name Type Description Default
e_min float

Left boundary of the eigenvalue domain.

required
e_max float

Right boundary of the eigenvalue domain.

required
n_components int

Number of basis functions (= number of output features).

required

Returns:

Type Description
Callable[[ndarray], ndarray]

Callable that accepts a 1-D eigenvalue array of length K and returns a (n_components, K) coefficient array. Values outside the support of each basis element are set to 0.

spectral_geometry_filter(mesh, filter=None, max_eigenvalue=1e-08, band_size=50, truncate_extra=True, drop_first=True, decomposition_dtype=np.float64, robust=True, mollify_factor=1e-05, point_laplacian=False, n_neighbors=30, verbose=False)

Apply a spectral filter to the geometry of a mesh.

Parameters:

Name Type Description Default
mesh Mesh

The input mesh. Must be a tuple of vertices and faces as arrays, or be an object with a vertices and faces attribute.

required
filter Optional[Callable[[ndarray], ndarray]]

A function that takes 1D array of eigenvalues, and returns a 2D array of filter coefficients, where the first dimension is the number of filters, and the second is the number of eigenvalues. If None, the eigenvectors and eigenvalues themselves will be returned, and no filtering will be applied.

None
max_eigenvalue float

The maximum eigenvalue to compute the eigendecomposition up to.

1e-08
band_size int

The number of eigenvalues to compute at a time using the band-by-band algorithm from [1]. This number should not affect the results, but may affect the speed.

50
truncate_extra bool

If True, truncate the filter to the max_eigenvalue exactly. Due the the band-by-band algorithm, the filter may overshoot the max_eigenvalue by at most one band.

True
drop_first bool

If True, drop the first eigenvalue and eigenvector. This should be 0 and the constant eigenvector scaled by vertex areas, so it is often not useful.

True
robust bool

If True, use the robust laplacian computation described in [2].

True
mollify_factor float

The factor to use for the mollification when computing the robust laplacian. If robust is False, this parameter is ignored.

1e-05
verbose Union[bool, int]

If >0, print out additional information about the computation. Higher values give more information.

False

Returns:

Type Description
Union[ndarray, tuple[ndarray, ndarray]]

A 2D array of features, where the first dimension is the number of vertices, and the second is the number of features.

Notes

Numerical errors are often due to a malformed mesh and therefore a malformed Laplacian. For this reason, it is recommended to use the robust Laplacian computation is used. Alternatively, make sure you are inputting a manifold mesh.

References

[1] Spectral Geometry Processing with Manifold Harmonics, Vallet and Levy, 2008 [2] A Laplacian for Nonmanifold Triangle Meshes, Sharp and Crane, 2020

compute_hks(mesh, max_eigenvalue=1e-08, t_max=None, t_min=None, n_components=32, band_size=50, truncate_extra=False, drop_first=False, robust=True, mollify_factor=1e-05, decomposition_dtype=np.float64, point_laplacian=False, n_neighbors=30, verbose=False)

Compute the Heat Kernel Signature (HKS) for each vertex of a mesh.

The HKS is a multi-scale, intrinsic shape descriptor based on the diagonal of the heat kernel at a set of diffusion timescales. It captures local geometry from fine detail (small t) to global structure (large t).

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
max_eigenvalue float

Maximum Laplacian eigenvalue to include in the computation. Larger values capture finer geometric detail at increased cost.

1e-08
t_min Optional[float]

Smallest diffusion timescale.

None
t_max Optional[float]

Largest diffusion timescale.

None
n_components int

Number of diffusion timescales. Scales are spaced logarithmically between t_min and t_max, and each scale produces one feature per vertex.

32
band_size int

Number of eigenpairs per ARPACK band; see spectral_geometry_filter.

50
truncate_extra bool

Whether to discard eigenpairs that overshoot max_eigenvalue.

False
drop_first bool

If True, drop the first (near-zero) eigenpair before applying the filter. The first eigenvector is proportional to vertex areas and is typically uninformative.

False
robust bool

If True, use the robust Laplacian (see cotangent_laplacian).

True
mollify_factor float

Mollification factor for the robust Laplacian.

1e-05
decomposition_dtype Optional[dtype]

Floating-point dtype for the eigendecomposition.

float64
point_laplacian bool

If True, build a point-cloud Laplacian instead of the mesh cotangent Laplacian (useful for point clouds without face data).

False
n_neighbors int

Number of neighbours used when point_laplacian=True.

30
verbose Union[bool, int]

Verbosity level passed to spectral_geometry_filter.

False

Returns:

Type Description
ndarray

Per-vertex HKS feature array of shape (V, n_components).

Notes

The band-by-band eigensolver from [1] is used for efficiency. The robust Laplacian from [2] is recommended for real-world meshes.

References

[1] J. Sun, M. Ovsjanikov, and L. Guibas, "A Concise and Provably Informative Multi-Scale Signature Based on Heat Diffusion", Computer Graphics Forum, 28(5):1383-1392, 2009. [2] N. Sharp and K. Crane, "A Laplacian for Nonmanifold Triangle Meshes", Computer Graphics Forum, 39(5), 2020.

compute_geometry_vectors(mesh, max_eigenvalue=1e-08, n_components=32, band_size=50, truncate_extra=False, drop_first=False, robust=True, mollify_factor=1e-05, decomposition_dtype=np.float64, verbose=False)

Compute spectral geometry descriptors using a B-spline spectral filter.

Similar in spirit to compute_hks, but instead of heat-kernel exponentials the spectrum is partitioned by a bank of cubic B-spline basis functions. Each basis function acts as a band-pass filter, yielding one feature per vertex per band.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
max_eigenvalue float

Maximum Laplacian eigenvalue to include. Determines the upper boundary of the B-spline domain.

1e-08
n_components int

Number of B-spline basis functions (= number of output features per vertex).

32
band_size int

Number of eigenpairs per ARPACK band; see spectral_geometry_filter.

50
truncate_extra bool

Whether to discard eigenpairs that overshoot max_eigenvalue.

False
drop_first bool

If True, drop the first (near-zero) eigenpair.

False
robust bool

If True, use the robust Laplacian (see cotangent_laplacian).

True
mollify_factor float

Mollification factor for the robust Laplacian.

1e-05
decomposition_dtype Optional[dtype]

Floating-point dtype for the eigendecomposition.

float64
verbose Union[bool, int]

Verbosity level passed to spectral_geometry_filter.

False

Returns:

Type Description
ndarray

Per-vertex geometry-vector feature array of shape (V, n_components).

Notes

The B-spline filter bank follows [1].

References

[1] R. Litman and A. M. Bronstein, "Learning spectral descriptors for deformable shape correspondence", IEEE Transactions on Pattern Analysis and Machine Intelligence, 36(1):171-180, 2013.

meshmash.laplacian

area_matrix(mesh)

Compute the diagonal lumped-area matrix for a triangle mesh.

Each diagonal entry is the area associated with that vertex, approximated as one third of the sum of adjacent face areas.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh.

required

Returns:

Name Type Description
M dia_array

Sparse diagonal area matrix of shape (V, V) in DIA format.

cotangent_laplacian(mesh, robust=False, mollify_factor=1e-05)

Compute the cotangent Laplacian and lumped-area matrix for a triangle mesh.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh.

required
robust bool

If True, use the robust Laplacian from robust_laplacian.mesh_laplacian (requires the robust-laplacian package). This handles degenerate geometry such as zero-area faces and near-duplicate vertices more reliably than the standard cotangent formula.

False
mollify_factor float

Mollification parameter passed to robust_laplacian.mesh_laplacian. Only used when robust=True.

1e-05

Returns:

Name Type Description
L csc_array

Sparse cotangent-weight stiffness matrix of shape (V, V) in CSC format.

M dia_array

Sparse diagonal lumped-area matrix of shape (V, V) in DIA format.

Notes

The robust Laplacian is described in:

[1] N. Sharp and K. Crane, "A Laplacian for Nonmanifold Triangle Meshes", Computer Graphics Forum (SGP), 39(5):69-80, 2020.

compute_vertex_areas(mesh, robust=False, mollify_factor=1e-05)

Compute per-vertex areas for a triangle mesh.

A thin wrapper around cotangent_laplacian that returns only the diagonal of the lumped-area matrix M.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh.

required
robust bool

If True, use the robust Laplacian to compute vertex areas.

False
mollify_factor float

Mollification parameter forwarded to cotangent_laplacian when robust=True.

1e-05

Returns:

Type Description
ndarray

Array of per-vertex areas of length V.

meshmash.split

MeshStitcher(mesh, verbose=False, n_jobs=-1)

Split a mesh into overlapping chunks and apply functions across them.

Coordinates the full split-compute-stitch workflow:

  1. Call split_mesh to partition the mesh into overlapping submeshes.
  2. Call apply (or apply_on_features / subset_apply) to run a function on each submesh in parallel.
  3. Results are stitched back to the full mesh using stitch_features.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
verbose Union[bool, int]

Verbosity level. 0 / False is silent; >=1 prints progress; >=2 prints extra diagnostics.

False
n_jobs Optional[int]

Number of parallel workers for Parallel. -1 uses all available CPU cores.

-1

split_mesh(max_vertex_threshold=20000, min_vertex_threshold=100, overlap_distance=20000, max_rounds=100000, max_overlap_neighbors=None, verify_connected=True)

Partition the mesh and build overlapping submesh chunks.

Calls fit_mesh_split to produce non-overlapping core chunks, then expands each chunk by including all vertices reachable within overlap_distance along mesh edges. The resulting submeshes, their overlap vertex indices, and the per-vertex submesh mapping are stored on self for use by apply, apply_on_features, and stitch_features.

Parameters:

Name Type Description Default
max_vertex_threshold int

Maximum vertices per non-overlapping core chunk; passed to fit_mesh_split.

20000
min_vertex_threshold int

Minimum connected-component size; smaller components are discarded.

100
overlap_distance float

Maximum geodesic edge distance used to expand each core chunk into its overlapping neighbourhood.

20000
max_rounds int

Maximum bisection rounds; passed to fit_mesh_split.

100000
max_overlap_neighbors Optional[int]

If set, limits each chunk's overlap to at most this many additional vertices (ranked by distance). None keeps all vertices within overlap_distance.

None
verify_connected bool

If True, assert that every overlapping submesh forms a single connected component.

True

Returns:

Type Description
list[Mesh]

List of overlapping submeshes as (vertices, faces) tuples, one per chunk.

stitch_features(features_by_submesh, fill_value=np.nan)

Combine per-submesh feature arrays into a single full-mesh array.

Each vertex in the overlap region is covered by multiple submeshes. This method assigns each vertex the value computed by the submesh that "owns" it (i.e. submesh_mapping[vertex] == submesh_index).

Parameters:

Name Type Description Default
features_by_submesh list[ndarray]

List of 2-D feature arrays, one per submesh, aligned to the submesh vertex ordering. None entries are skipped.

required
fill_value float

Value used to pre-fill the output array before writing submesh results. Vertices in chunks where the function returned None retain this value.

nan

Returns:

Type Description
ndarray

Full-mesh feature array of shape (V, n_features).

apply(func, *args, fill_value=np.nan, stitch=True, **kwargs)

Apply a function to each submesh and (optionally) stitch results.

func must have signature func(submesh, *args, **kwargs) and return a 2-D array aligned to the submesh vertices, or None to indicate failure.

Parameters:

Name Type Description Default
func Callable[..., Any]

Callable to apply to each submesh.

required
*args

Positional arguments forwarded to func after submesh.

()
fill_value float

Fill value for uncomputed vertices; see stitch_features.

nan
stitch bool

If True (default), stitch results into a full-mesh array via stitch_features. If False, return the raw list of per-submesh results.

True
**kwargs

Keyword arguments forwarded to func.

{}

Returns:

Type Description
Union[ndarray, list]

Stitched full-mesh feature array of shape (V, n_features) when stitch=True, or the raw list of per-submesh results when stitch=False.

subset_apply(func, indices, *args, reindex=False, fill_value=np.nan, **kwargs)

Apply a function only to submeshes that contain indices.

Useful when features are only needed for a subset of vertices; submeshes that do not overlap with indices are skipped.

Parameters:

Name Type Description Default
func Callable[..., Any]

Callable with signature func(submesh, *args, **kwargs).

required
indices ndarray

Vertex indices of interest. Only submeshes that contain at least one of these vertices are processed.

required
*args

Positional arguments forwarded to func.

()
reindex bool

If True, return only the rows of the stitched result corresponding to indices. If False (default), return the full-mesh array.

False
fill_value float

Fill value for vertices whose submesh was not processed.

nan
**kwargs

Keyword arguments forwarded to func.

{}

Returns:

Type Description
ndarray

Full-mesh feature array of shape (V, n_features) or, when reindex=True, shape (len(indices), n_features).

apply_on_features(func, X, *args, fill_value=np.nan, **kwargs)

Apply a function that takes both a submesh and a feature slice.

Like apply, but also passes the slice of X corresponding to each submesh as the second argument to func. The expected signature is func(submesh, submesh_features, *args, **kwargs).

Parameters:

Name Type Description Default
func Callable[..., Any]

Callable with signature func(submesh, submesh_features, *args, **kwargs).

required
X ndarray

Full-mesh feature array of shape (V, F). Each submesh receives the rows indexed by its overlap vertex indices.

required
*args

Additional positional arguments forwarded to func.

()
fill_value float

Fill value for uncomputed vertices.

nan
**kwargs

Keyword arguments forwarded to func.

{}

Returns:

Type Description
ndarray

Stitched full-mesh result array of shape (V, n_out_features).

graph_laplacian_split(adj, dtype=np.float32)

Bisect a mesh using the Fiedler vector of the graph Laplacian.

Computes the second smallest eigenvector (Fiedler vector) of the unnormalised graph Laplacian and partitions vertices by the sign of their Fiedler coefficient.

Parameters:

Name Type Description Default
adj csr_array

Sparse adjacency matrix of the mesh graph, shape (V, V).

required
dtype type

Floating-point dtype used for the eigensolver.

float32

Returns:

Name Type Description
indices1 ndarray

Indices of vertices in the first partition (Fiedler coefficient >= 0).

indices2 ndarray

Indices of vertices in the second partition (Fiedler coefficient < 0).

bisect_adjacency(adj, n_retries=7, check=True)

Bisect a mesh graph into two parts using the graph-Laplacian Fiedler vector.

Calls graph_laplacian_split and retries if the result is degenerate (one empty partition or disconnected nodes). Uses recursion up to n_retries times.

Parameters:

Name Type Description Default
adj csr_array

Sparse adjacency matrix of shape (V, V).

required
n_retries int

Maximum number of retry attempts when the split fails to produce two non-empty, connected partitions.

7
check bool

If True, verify that no vertex becomes isolated (zero-degree) after splitting and retry if so.

True

Returns:

Name Type Description
sub_adjs tuple[csr_array, csr_array]

Pair of sub-adjacency matrices (adj1, adj2) for each partition.

submesh_indices tuple[ndarray, ndarray]

Pair of index arrays (indices1, indices2) mapping each partition's rows back to the original adj.

fit_mesh_split(mesh, max_vertex_threshold=20000, min_vertex_threshold=100, max_rounds=100000, verbose=False)

Partition a mesh into non-overlapping chunks using recursive bisection.

Repeatedly bisects each chunk using the Fiedler vector of the graph Laplacian until every chunk has at most max_vertex_threshold vertices. Chunks belonging to connected components with fewer than min_vertex_threshold vertices are dropped (their vertices receive label -1). The returned labels are ordered so that the largest chunk has label 0.

Parameters:

Name Type Description Default
mesh Union[Mesh, ndarray, csr_array]

Input mesh, adjacency matrix, or vertex array accepted by interpret_mesh / mesh_to_adjacency.

required
max_vertex_threshold int

Stop bisecting a chunk once it contains at most this many vertices.

20000
min_vertex_threshold int

Discard connected components with fewer than this many vertices; their vertices receive label -1.

100
max_rounds int

Maximum number of bisection steps before the algorithm terminates regardless of remaining chunk sizes.

100000
verbose Union[bool, int]

If truthy, print queue size every 50 rounds.

False

Returns:

Type Description
ndarray

Per-vertex integer label array of shape (V,). Labels run 0, 1, …, K-1 ordered from largest to smallest chunk; vertices not assigned to any chunk have label -1.

bisect_laplacian(L, M)

Bisect a mesh into two parts using the cotangent-Laplacian Fiedler vector.

Computes the second eigenvector of the generalised eigenproblem L v = λ M v via decompose_laplacian and partitions vertices by its sign.

Parameters:

Name Type Description Default
L sparray

Cotangent Laplacian matrix of shape (V, V) as returned by cotangent_laplacian.

required
M sparray

Diagonal mass matrix of shape (V, V) as returned by cotangent_laplacian.

required

Returns:

Name Type Description
sub_laps tuple[tuple[sparray, diags_array], tuple[sparray, diags_array]]

Pair of (L_sub, M_sub) tuples for each partition, where M_sub is a diags_array of the diagonal mass entries for that partition.

submesh_indices tuple[ndarray, ndarray]

Pair of index arrays (indices1, indices2) mapping each partition's rows back to the original L.

fit_mesh_split_lap(mesh, max_vertex_threshold=20000, min_vertex_threshold=100, max_rounds=100000, robust=True, mollify_factor=1e-05, verbose=False)

Partition a mesh into chunks using recursive cotangent-Laplacian bisection.

Like fit_mesh_split but uses the Fiedler vector of the cotangent Laplacian (instead of the graph Laplacian) for each bisection step, which can produce more geometrically uniform partitions on irregular meshes.

Parameters:

Name Type Description Default
mesh Union[Mesh, ndarray, csr_array]

Input mesh accepted by interpret_mesh.

required
max_vertex_threshold int

Stop bisecting a chunk once it contains at most this many vertices.

20000
min_vertex_threshold int

Discard connected components with fewer than this many vertices; their vertices receive label -1.

100
max_rounds int

Maximum number of bisection steps before the algorithm terminates.

100000
robust bool

If True, use the robust cotangent Laplacian variant; passed to cotangent_laplacian.

True
mollify_factor float

Mollification factor passed to cotangent_laplacian.

1e-05
verbose Union[bool, int]

If truthy, print queue information each round.

False

Returns:

Type Description
ndarray

Per-vertex integer label array of shape (V,). Labels run 0, 1, …, K-1 ordered from largest to smallest chunk; vertices not assigned to any chunk have label -1.

apply_mesh_split(mesh, split_mapping)

Separate a mesh into submeshes according to a per-vertex split mapping.

Only faces whose all three vertices share the same label are retained in that submesh. Faces that span label boundaries are dropped.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
split_mapping ndarray

Per-vertex integer label array of length V as produced by fit_mesh_split. Vertices with label -1 are excluded.

required

Returns:

Type Description
list[Mesh]

List of (vertices, faces) tuples, one per unique non-negative label, with remapped face indices.

get_submesh_borders(submesh)

Return the vertex indices that lie on boundary edges of a submesh.

Uses :mod:pyvista boundary-edge extraction to find edges shared by fewer than two faces.

Parameters:

Name Type Description Default
submesh Mesh

A manifold triangular mesh accepted by mesh_to_poly.

required

Returns:

Type Description
ndarray

Sorted array of vertex indices located on boundary edges.

fit_overlapping_mesh_split(mesh, overlap_distance=20000, vertex_threshold=20000, max_rounds=1000)

Split a mesh and grow each chunk geodesically to create overlapping regions.

First calls fit_mesh_split to partition the mesh, then expands each chunk by including all vertices reachable within overlap_distance along mesh edges (using shortest-path distances).

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
overlap_distance float

Maximum geodesic distance from the core chunk within which additional vertices are included in the overlap region.

20000
vertex_threshold int

Maximum number of vertices per non-overlapping core chunk passed to fit_mesh_split.

20000
max_rounds int

Maximum bisection rounds; see fit_mesh_split.

1000

Returns:

Type Description
list[ndarray]

List of vertex index arrays (one per chunk), each containing the core vertices plus their overlap neighbourhood.

meshmash.graph

compute_edge_widths(mesh, mollify_factor=0.0)

Compute per-edge width estimates from the incircle radii of adjacent faces.

For each face the incircle radius is computed from Heron's formula, then that radius is accumulated onto the three edges of the face. The resulting value at each edge is a geometric proxy for the local "width" of the surface at that boundary.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by mesh_to_poly.

required
mollify_factor float

Small additive offset applied to each edge length before computing face radii. Prevents division by zero on degenerate faces.

0.0

Returns:

Type Description
csr_array

Sparse CSR matrix of shape (V, V) containing accumulated incircle-radius values on each edge.

condense_mesh_to_graph(mesh, labels, add_component_features=False)

Condense a vertex-labeled mesh into a node-edge graph representation.

Each unique label becomes a node; adjacent regions (labels that share at least one mesh edge) become connected by an edge. Edge weights reflect the total boundary length between regions.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by mesh_to_poly.

required
labels ndarray

Per-vertex integer label array of length V. Vertices with label -1 are excluded.

required
add_component_features bool

If True, add a component column to the node table indicating which connected component (in the original mesh graph) each label region belongs to.

False

Returns:

Name Type Description
node_table DataFrame

DataFrame indexed by label with columns x, y, z (centroid), area (summed vertex areas), and n_vertices. If add_component_features=True, also includes component and component_area.

edge_table DataFrame

DataFrame with columns source_group, target_group, boundary_length (sum of edge-width values), and count (number of mesh edges crossing the boundary).

meshmash.agglomerate

multicut_ward(X, connectivity=None, distance_thresholds=None)

Compute Ward cluster labels at multiple distance thresholds.

Builds the Ward linkage tree once with ward_tree, then cuts it at each threshold in distance_thresholds without rebuilding. This is more efficient than fitting a separate AgglomerativeClustering for each threshold.

Parameters:

Name Type Description Default
X ArrayLike

Feature matrix of shape (N, F).

required
connectivity Optional[sparray]

Optional sparse connectivity matrix of shape (N, N) constraining which samples may be merged (passed to ward_tree).

None
distance_thresholds Optional[list[float]]

List of linkage-distance thresholds at which to cut the tree. Each threshold yields one column in the output.

None

Returns:

Type Description
ndarray

Integer label array of shape (N, len(distance_thresholds)). Column i contains cluster labels for threshold i.

agglomerate_mesh(mesh, features, distance_thresholds=None)

Apply connectivity-constrained Ward clustering to vertex features on a mesh.

Handles vertices with non-finite feature values by masking them out and running clustering only on the valid sub-mesh, then filling -1 back into the invalid positions.

Parameters:

Name Type Description Default
mesh

Input mesh accepted by interpret_mesh.

required
features

Per-vertex feature matrix of shape (V, F).

required
distance_thresholds

Single threshold or list of thresholds passed to multicut_ward. None assigns each vertex a unique label (i.e. no clustering).

None

Returns:

Type Description
ndarray

Integer label array of shape (V, T) where T is the number of thresholds. Vertices with non-finite features receive label -1. Returns None if no vertices have finite features or the sub-mesh has no faces.

fix_split_labels(agg_labels, submesh_mapping)

Remap per-submesh local labels to globally unique integers.

When each submesh independently assigns cluster labels 0, 1, 2, …, the same integer can refer to different clusters in different submeshes. This function treats each (submesh_id, local_label) pair as a unique cluster and remaps them to a single contiguous range 0, 1, 2, ….

Parameters:

Name Type Description Default
agg_labels ndarray

Per-vertex label array of shape (V, T) where T is the number of distance thresholds. Vertices not belonging to any submesh have label -1 and are left unchanged.

required
submesh_mapping ndarray

Per-vertex integer array of length V indicating which submesh each vertex belongs to (-1 for unassigned vertices).

required

Returns:

Type Description
ndarray

Modified agg_labels with globally unique integers, same shape as the input.

fix_split_labels_and_features(agg_labels, submesh_mapping, features_by_submesh)

Remap per-submesh labels to globally unique integers and align feature DataFrames.

Like fix_split_labels, but also re-indexes the per-submesh feature DataFrames so that their row indices match the new global label integers and concatenates them into a single DataFrame.

Parameters:

Name Type Description Default
agg_labels ndarray

Per-vertex label array of length V. Vertices not belonging to any submesh have label -1 and are left unchanged.

required
submesh_mapping ndarray

Per-vertex integer array of length V indicating which submesh each vertex belongs to (-1 for unassigned vertices).

required
features_by_submesh list[DataFrame]

List of per-submesh feature DataFrames, one per submesh, indexed by local cluster label.

required

Returns:

Name Type Description
agg_labels ndarray

Modified agg_labels with globally unique integers, same length as the input.

condensed_features DataFrame

Concatenated feature DataFrame indexed by global label, including a row for the null label -1.

agglomerate_split_mesh(splitter, features, distance_thresholds)

Apply Ward clustering across submeshes and return globally unique labels.

Applies agglomerate_mesh to each submesh via MeshStitcher.apply_on_features, then calls fix_split_labels to make the cluster labels globally unique across all submeshes.

Parameters:

Name Type Description Default
splitter MeshStitcher

A fitted MeshStitcher.

required
features ndarray

Per-vertex feature matrix of shape (V, F) for the full mesh.

required
distance_thresholds Union[list, int, float]

Single threshold or list of thresholds passed to multicut_ward.

required

Returns:

Type Description
ndarray

Integer label array of shape (V,) if a single threshold was given, or (V, T) for a list of T thresholds. Unassigned vertices have label -1.

aggregate_features(features, labels=None, weights=None, func='mean')

Aggregate per-vertex features to per-label summaries.

Groups vertices by labels and applies func (or an area-weighted mean when weights is provided) to produce one row per unique label. The result is reindexed to include every integer from -1 to labels.max(), inserting NaN for any missing labels.

Parameters:

Name Type Description Default
features Union[ndarray, DataFrame]

Per-vertex feature matrix of shape (V, F), as an array or DataFrame.

required
labels Optional[ndarray]

Integer label array of length V. -1 is treated as the null label. If None, the features are returned unchanged.

None
weights Optional[ndarray]

Per-vertex weight array of length V used for area-weighted aggregation when func="mean". None falls back to an unweighted mean.

None
func str

Aggregation function name recognised by DataFrameGroupBy.agg (e.g. "mean", "median"). Ignored when weights is provided.

'mean'

Returns:

Type Description
DataFrame

DataFrame of shape (labels.max() + 2, F) indexed from -1 to labels.max(), where each row contains the aggregated features for that label.

blow_up_features(agg_features_df, labels)

Expand per-label aggregated features back to per-vertex features.

Inverse of aggregate_features. Looks up each vertex's label in agg_features_df to produce a per-vertex DataFrame.

Parameters:

Name Type Description Default
agg_features_df DataFrame

Per-label feature DataFrame indexed by label integer, as returned by aggregate_features.

required
labels ndarray

Per-vertex label array of length V.

required

Returns:

Type Description
DataFrame

Per-vertex feature DataFrame of shape (V, F) with a reset integer index. Vertices with label -1 receive NaN values.

meshmash.utils

mesh_to_poly(mesh)

Convert a mesh to a PolyData object.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh. Accepts a (vertices, faces) tuple, a PolyData, or any object with vertices and faces attributes.

required

Returns:

Type Description
PolyData

Triangle mesh as a PolyData.

mesh_to_edges(mesh)

Extract all edges from a mesh as vertex index pairs.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by mesh_to_poly.

required

Returns:

Type Description
ndarray

Array of edge vertex index pairs, shape (E, 2).

mesh_to_adjacency(mesh)

Build a sparse weighted adjacency matrix from a mesh.

Edge weights are Euclidean edge lengths. The returned matrix is upper triangular (each undirected edge appears once).

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by mesh_to_poly.

required

Returns:

Type Description
csr_array

Sparse CSR adjacency matrix of shape (V, V) with edge-length weights.

poly_to_mesh(poly)

Convert a PolyData to a (vertices, faces) tuple.

Parameters:

Name Type Description Default
poly PolyData

Triangle surface mesh as a PolyData.

required

Returns:

Name Type Description
vertices Mesh

Array of vertex positions, shape (V, 3).

faces Mesh

Array of triangle face indices, shape (F, 3).

fix_mesh(mesh, **kwargs)

Repair a mesh using :mod:pymeshfix.

Attempts to close holes and remove self-intersections so that the result is a manifold surface. Additional keyword arguments are forwarded to MeshFix.repair.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by mesh_to_poly.

required
**kwargs

Keyword arguments forwarded to MeshFix.repair.

{}

Returns:

Name Type Description
vertices Mesh

Array of repaired vertex positions, shape (V', 3).

faces Mesh

Array of repaired triangle face indices, shape (F', 3).

project_points_to_mesh(points, mesh, distance_threshold=None, return_distances=False)

project_points_to_mesh(
    points: ArrayLike,
    mesh: Mesh,
    distance_threshold: Optional[float] = None,
    return_distances: Literal[False] = ...,
) -> np.ndarray
project_points_to_mesh(
    points: ArrayLike,
    mesh: Mesh,
    distance_threshold: Optional[float] = None,
    *,
    return_distances: Literal[True],
) -> tuple[np.ndarray, np.ndarray]

Find the nearest mesh vertex for each query point.

Parameters:

Name Type Description Default
points ArrayLike

Query point coordinates, shape (N, 3).

required
mesh Mesh

Target mesh accepted by mesh_to_poly.

required
distance_threshold Optional[float]

If provided, query points whose nearest vertex is farther than this distance are assigned an index of -1.

None
return_distances bool

If True, also return the distance to the nearest vertex for each query point.

False

Returns:

Name Type Description
indices Union[ndarray, tuple[ndarray, ndarray]]

Indices of the nearest vertex in the mesh for each query point, shape (N,). Entries are -1 where the nearest vertex exceeds distance_threshold.

distances Union[ndarray, tuple[ndarray, ndarray]]

Only returned when return_distances=True. Euclidean distances to the nearest vertex, shape (N,).

component_size_transform(mesh, indices=None)

Return the connected-component size for each vertex.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by mesh_to_poly.

required
indices Optional[ndarray]

Subset of vertex indices to return sizes for. If None, sizes are returned for all vertices.

None

Returns:

Type Description
ndarray

Array of component sizes (number of vertices in the same connected component), one value per entry in indices (or per vertex if indices is None).

get_label_components(mesh, labels)

Label connected components of a mesh that share the same vertex label.

Two vertices belong to the same component only if they are connected by an edge and carry the same label value.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by mesh_to_poly.

required
labels ArrayLike

Per-vertex label array of length V.

required

Returns:

Type Description
ndarray

Per-vertex component label array of length V. Vertices with different vertex labels will never share a component label.

subset_mesh_by_indices(mesh, indices)

Extract a submesh containing only the specified vertices.

Only faces whose all three vertices are in indices are kept. Face indices are remapped to the new, compact vertex numbering.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
indices ndarray

Vertex indices to keep, or a boolean mask of length V.

required

Returns:

Name Type Description
vertices Mesh

Subset of vertex positions, shape (len(indices), 3).

faces Mesh

Remapped face index array containing only retained faces.

rough_subset_mesh_by_indices(mesh, indices)

Extract a submesh keeping faces where any vertex is in indices.

Unlike subset_mesh_by_indices, a face is retained whenever at least one of its vertices is in indices. This can introduce additional vertices beyond those in indices.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
indices ndarray

Seed vertex indices.

required

Returns:

Name Type Description
submesh Mesh

(vertices, faces) tuple for the extracted submesh.

vertex_indices ndarray

Final set of vertex indices (in the original mesh) that were included, which may be a superset of indices.

largest_mesh_component(mesh)

Return the largest connected component of a mesh.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh.

required

Returns:

Name Type Description
vertices Mesh

Vertices of the largest component.

faces Mesh

Faces of the largest component, with remapped indices.

shuffle_label_mapping(x)

Randomly permute integer labels while preserving the set of label values.

Useful for randomising colours when visualising label arrays.

Parameters:

Name Type Description Default
x ArrayLike

Array of integer labels.

required

Returns:

Type Description
ndarray

Array of the same shape as x with label integers randomly permuted.

compute_distances_to_point(points, center_point)

Compute the Euclidean distance from each point to a reference point.

Parameters:

Name Type Description Default
points ArrayLike

Query point coordinates, shape (N, d).

required
center_point ArrayLike

Reference point, shape (d,).

required

Returns:

Type Description
ndarray

Array of distances, shape (N,).

edges_to_lines(edges)

Convert an edge array to a :mod:pyvista lines connectivity array.

:mod:pyvista encodes lines as a flat array where each cell is prefixed by its vertex count. This function prepends 2 to each edge so the result can be passed directly to PolyData.

Parameters:

Name Type Description Default
edges ndarray

Edge vertex index pairs, shape (E, 2).

required

Returns:

Type Description
ndarray

Flat connectivity array of length 3 * E, alternating between the cell size 2 and the two vertex indices.

combine_meshes(meshes)

Concatenate a list of meshes into a single mesh.

Vertex arrays are stacked and face index arrays are shifted so that each submesh's faces still point to the correct vertices.

Parameters:

Name Type Description Default
meshes list[Mesh]

List of meshes accepted by interpret_mesh.

required

Returns:

Name Type Description
vertices Mesh

Combined vertex array.

faces Mesh

Combined face index array with adjusted indices.

mesh_connected_components(mesh, size_threshold=100, sort_by_size=False)

Yield each connected component of a mesh as a separate mesh.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh.

required
size_threshold Optional[int]

Minimum number of vertices a component must have to be yielded. Set to None to yield all components.

100
sort_by_size bool

If True, yield components in descending order of vertex count.

False

Yields:

Type Description
Mesh

(vertices, faces) tuple for each retained component.

mesh_n_connected_components(mesh)

Return the number of connected components in a mesh.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh.

required

Returns:

Type Description
int

Number of connected components.

threshold_mesh_by_component_size(mesh, size_threshold=100)

Remove connected components smaller than a vertex-count threshold.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh.

required
size_threshold int

Minimum number of vertices a component must have to be retained.

100

Returns:

Name Type Description
mesh Mesh

Filtered (vertices, faces) tuple containing only vertices and faces belonging to components that meet the threshold.

indices ndarray

Indices of the retained vertices in the original mesh, shape (V',).

expand_labels(condensed_labels, mapping)

Expand per-vertex labels from a reduced mesh back to the original mesh.

Parameters:

Name Type Description Default
condensed_labels ndarray

Per-vertex label array for the simplified/reduced mesh, shape (V_simple,).

required
mapping ndarray

Array of length V_original mapping each original vertex to its index in the reduced mesh. Entries of -1 indicate vertices that have no corresponding reduced-mesh vertex.

required

Returns:

Type Description
ndarray

Per-vertex label array for the original mesh, shape (V_original,). Vertices with mapping == -1 receive label -1.

graph_to_adjacency(graph)

Convert a (vertices, edges) graph tuple to an unweighted adjacency matrix.

Parameters:

Name Type Description Default
graph tuple[ndarray, ndarray]

Tuple of (vertices, edges) where vertices has shape (V, d) and edges has shape (E, 2).

required

Returns:

Type Description
csr_array

Sparse CSR adjacency matrix of shape (V, V) with entries of 1 for each edge.

scale_mesh(mesh, scale)

Return a new mesh with all vertex positions scaled by scale.

Parameters:

Name Type Description Default
mesh Mesh

Input mesh accepted by interpret_mesh.

required
scale float

Scalar factor to multiply all vertex coordinates by.

required

Returns:

Name Type Description
vertices Mesh

Scaled vertex positions.

faces Mesh

Unchanged face index array.

meshmash.io

interpret_path(path, **kwargs)

Parse a path into a cloudfiles.CloudFiles handle and filename.

Supports local paths as well as cloud storage URIs such as gs:// and file://.

Parameters:

Name Type Description Default
path Union[str, Path]

Path to a file or directory. If the path has no file extension, it is treated as a directory and the returned filename is None. gs:/ prefixes are normalised to gs://.

required
**kwargs

Additional keyword arguments forwarded to cloudfiles.CloudFiles.

{}

Returns:

Name Type Description
cf CloudFiles

cloudfiles.CloudFiles instance pointing at the parent directory.

file_name Optional[str]

The base filename, or None if path is a directory.

save_condensed_features(path, features, labels, feature_dtype=np.float32, label_dtype=np.int32, check_header=True)

Save per-label features and per-vertex labels to a compressed .npz file.

A header.txt file containing tab-separated column names is written alongside the data file (or validated against an existing one when check_header=True).

Parameters:

Name Type Description Default
path Union[str, Path]

Destination file path (local or gs:// URI). Parsed by interpret_path.

required
features DataFrame

DataFrame of per-label features. Rows should be indexed -1, 0, 1, ….

required
labels ndarray

Per-vertex label array mapping each vertex to a row index in features.

required
feature_dtype type

Numeric dtype used to store the feature values.

float32
label_dtype type

Numeric dtype used to store the label array.

int32
check_header bool

If True, validate (or write) a header.txt file recording the column names of features.

True

read_condensed_features(path)

Load per-label features and per-vertex labels from a file written by save_condensed_features.

Parameters:

Name Type Description Default
path Union[str, Path]

Path to the .npz file (local or gs:// URI).

required

Returns:

Name Type Description
features DataFrame

DataFrame of per-label features indexed -1, 0, 1, ….

labels ndarray

Per-vertex label array.

save_condensed_edges(path, edges, check_header=True)

Save a condensed edge table to a compressed .npz file.

The source and target columns are stored as int32; all remaining columns are stored as float32.

Parameters:

Name Type Description Default
path Union[str, Path]

Destination file path (local or gs:// URI).

required
edges DataFrame

DataFrame with at least source and target integer columns plus any number of numeric edge-feature columns.

required
check_header bool

If True, validate (or write) a header.txt recording the names of the edge-feature columns.

True

read_condensed_edges(path)

Load an edge table from a file written by save_condensed_edges.

Parameters:

Name Type Description Default
path Union[str, Path]

Path to the .npz file (local or gs:// URI).

required

Returns:

Type Description
tuple[DataFrame, DataFrame]

DataFrame with source, target, and edge-feature columns.

save_condensed_graph(path, nodes, edges, nodes_dtype=np.float32, edges_dtype=np.int32, check_header=True)

Save both the condensed node and edge tables to a single .npz file.

Column names for each table are written to separate header files (nodes_header.txt and edges_header.txt) in the same directory.

Parameters:

Name Type Description Default
path Union[str, Path]

Destination file path (local or gs:// URI).

required
nodes DataFrame

DataFrame of per-label node features indexed 0, 1, ….

required
edges DataFrame

DataFrame of inter-label edge features.

required
nodes_dtype type

Numeric dtype used for the node feature values.

float32
edges_dtype type

Numeric dtype used for the edge values.

int32
check_header bool

If True, validate (or write) the column-name header files.

True

read_condensed_graph(path)

Load node and edge tables from a file written by save_condensed_graph.

Parameters:

Name Type Description Default
path Union[str, Path]

Path to the .npz file (local or gs:// URI).

required

Returns:

Name Type Description
nodes DataFrame

DataFrame of per-label node features.

edges DataFrame

DataFrame of inter-label edge features.

save_id_to_mesh_map(path, id_to_mesh_map)

Save an ID-to-mesh-index mapping array to a compressed .npz file.

Parameters:

Name Type Description Default
path Union[str, Path]

Destination file path (local or gs:// URI).

required
id_to_mesh_map ndarray

Integer array of shape (N, 2) where each row is [object_id, mesh_vertex_index].

required

read_id_to_mesh_map(path)

Load a mapping array from a file written by save_id_to_mesh_map.

Parameters:

Name Type Description Default
path Union[str, Path]

Path to the .npz file (local or gs:// URI).

required

Returns:

Type Description
ndarray

Integer array of shape (N, 2).

save_array(path, array)

Save a numpy array to a compressed .npz file.

Parameters:

Name Type Description Default
path Union[str, Path]

Destination file path (local or gs:// URI).

required
array ndarray

Array to save.

required

read_array(path)

Load a numpy array from a file written by save_array.

Parameters:

Name Type Description Default
path Union[str, Path]

Path to the .npz file (local or gs:// URI).

required

Returns:

Type Description
ndarray

The stored array.

meshmash.datasets

Sample datasets for meshmash.

Use pip install meshmash[datasets] to enable downloading.

fetch_sample_mesh(name='microns_dendrite_sample')

Download (once) and return a sample mesh as (vertices, faces).

The file is cached in the OS-appropriate user cache directory (e.g. ~/.cache/meshmash on Linux/macOS) and reused on subsequent calls.

Parameters:

Name Type Description Default
name str

Dataset name, without file extension. Available meshes:

  • "microns_neuron_sample" — full neuron mesh (MICrONs dataset, root_id 864691136371550856).
  • "microns_dendrite_sample" — small dendrite piece from the same neuron.
'microns_dendrite_sample'

Returns:

Name Type Description
vertices (ndarray, shape(V, 3))

Vertex positions.

faces (ndarray, shape(F, 3))

Triangle face indices.

Examples:

>>> from meshmash import fetch_sample_mesh
>>> vertices, faces = fetch_sample_mesh()
>>> vertices.shape
(N, 3)

meshmash.types

interpret_mesh(mesh)

Normalize a mesh input to a (vertices, faces) tuple.

Parameters:

Name Type Description Default
mesh

Either a (vertices, faces) tuple of arrays, or an object with vertices and faces attributes (e.g. trimesh.Trimesh).

required

Returns:

Name Type Description
vertices ndarray

Array of vertex positions, shape (V, 3).

faces ndarray

Array of triangle face indices, shape (F, 3).

Raises:

Type Description
ValueError

If mesh is neither a tuple nor an object with vertices and faces attributes.

meshmash.wrap

wrap_mesh(input_mesh, alpha=250.0, offset=5.0, alpha_fraction=None, offset_fraction=None)

Parameters:

Name Type Description Default
alpha float

Ball size in physical (mesh) units. If provided, overrides alpha_fraction.

250.0
offset float

Offset distance in physical (mesh) units. If provided, overrides offset_fraction.

5.0
alpha_fraction float

Ball size as a fraction of the largest bounding-box diagonal (used when alpha is None).

None
offset_fraction float

Offset distance as a fraction of the largest bounding-box diagonal (used when offset is None).

None