Skip to content

Working with Meshes

Meshes represent the full 3D surface of a neuron — millions of vertices and triangular faces from the EM segmentation. Use meshes when you need surface area, volume, or detailed geometric information. For topology and branching analysis, the skeleton is usually more appropriate.

Shared Features

Meshes inherit many common features from the PointMixin class. For information about features, masking, transformations, spatial queries, and cross-layer mapping, see Shared Layer Features.

What is a Mesh Layer?

A MeshLayer contains: - Vertices: 3D coordinates of points on the surface - Faces: Triangular faces connecting vertices (as indices)
- Surface properties: Face connectivity, area calculations, trimesh integration

Inspecting Mesh Layers

Quick Overview with describe()

The describe() method provides a comprehensive summary of mesh layers, showing vertex/face counts, features, and connections to other layers:

# Individual mesh layer
cell.mesh.describe()

Output:

# Cell: my_neuron  
# Layer: mesh (MeshLayer)
├── 2847 vertices, 5691 faces
├── features: [compartment, surface_area]
└── Links: skeleton <-> mesh

The output shows: - Cell context: Which cell this mesh belongs to - Layer type: Confirms this is a MeshLayer
- Metrics: Vertex and face counts - features: Available data columns beyond spatial coordinates - Links: Connections to other layers (<-> = bidirectional, = unidirectional)

Layer Manager Overview

You can also inspect all morphological layers at once using cell.layers.describe() to see how your mesh fits with other layers like skeletons and graphs.

Creating Mesh Layers

Basic Mesh Creation

import numpy as np
import ossify

# Create a simple tetrahedron
vertices = np.array([
    [0, 0, 0],    # Vertex 0
    [1, 0, 0],    # Vertex 1  
    [0, 1, 0],    # Vertex 2
    [0, 0, 1],    # Vertex 3
])

# Faces as triangles (indices into vertices)
faces = np.array([
    [0, 1, 2],    # Bottom face
    [0, 1, 3],    # Side face 1
    [0, 2, 3],    # Side face 2  
    [1, 2, 3],    # Top face
])

# Add to cell
cell = ossify.Cell(name="mesh_example")
cell.add_mesh(vertices=vertices, faces=faces)

print(f"Mesh has {cell.mesh.n_vertices} vertices and {len(cell.mesh.faces)} faces")

Mesh with features

# Add vertex features during creation
region_features = np.array([0, 0, 1, 1])  # Two regions

cell.add_mesh(
    vertices=vertices,
    faces=faces,
    features={"region": region_features}
)

Mesh-Specific Properties

Face Data Access

mesh = cell.mesh

# Access face data (unique to meshes)
faces_array = mesh.faces               # Faces with vertex indices
faces_positional = mesh.faces_positional  # Faces with positional indices

print(f"Number of faces: {len(mesh.faces)}")

Surface Area Calculations

# Total surface area
total_area = mesh.surface_area()

# Surface area for specific vertices
vertex_subset = mesh.vertex_index[:2]  # First two vertices
partial_area = mesh.surface_area(
    vertices=vertex_subset,
    as_positional=False,     # Using vertex indices
    inclusive=True           # Include faces touching any vertex
)

# Surface area for faces fully covered by vertices
exclusive_area = mesh.surface_area(
    vertices=vertex_subset,
    as_positional=False,
    inclusive=False         # Only faces with all vertices in subset
)

Trimesh Integration

Ossify integrates with the trimesh library for advanced mesh operations:

# Get as trimesh object
tmesh = mesh.as_trimesh

# Trimesh provides many useful properties
print(f"Is watertight: {tmesh.is_watertight}")
print(f"Volume: {tmesh.volume}")
print(f"Center of mass: {tmesh.center_mass}")

# Get edges from trimesh
edge_indices = mesh.edges               # With vertex indices
edge_positions = mesh.edges_positional  # With positional indices

Graph Representation

Meshes can be treated as graphs for connectivity analysis:

# Get sparse graph representation for mesh connectivity
csgraph = mesh.csgraph  # Weighted by edge lengths

# Get edge connectivity (derived from faces)
edge_indices = mesh.edges               # With vertex indices
edge_positions = mesh.edges_positional  # With positional indices

Key Mesh-Specific Methods

Mesh Creation

  • cell.add_mesh(vertices, faces, features=None, spatial_columns=None, vertex_index=None) - Add mesh to cell

Mesh-Specific Properties

  • mesh.faces - Face indices using vertex indices
  • mesh.faces_positional - Face indices using positional indices
  • mesh.surface_area(vertices=None, as_positional=True, inclusive=False) - Calculate surface area
  • mesh.as_trimesh - Get as trimesh.Trimesh object
  • mesh.as_tuple - Get (vertices, faces) tuple for external libraries
  • mesh.edges - Edge connectivity derived from faces (with vertex indices)
  • mesh.edges_positional - Edge connectivity derived from faces (with positional indices)
  • mesh.csgraph - Sparse graph representation for connectivity analysis

Additional Features

For comprehensive information about vertex access, features, masking, transformations, spatial queries, and cross-layer mapping, see Shared Layer Features.