Skip to content

Core Classes

The core classes provide the foundational architecture for neuromorphological data management in ossify.

Cell

Cell

Cell(name: Optional[Union[int, str]] = None, morphsync: Optional[MorphSync] = None, meta: Optional[dict] = None, annotation_layers: Optional[list] = None)

Methods:

  • add_layer

    Add a initialized layer to the MorphSync.

  • add_mesh

    Add a mesh layer to the MorphSync.

  • add_skeleton

    Add a skeleton layer to the MorphSync.

  • add_graph

    Add the core graph layer to a MeshWork object.

  • add_point_annotations

    Add point annotations to the MeshWork object. This is intended for annotations which are typically sparse and represent specific features, unlike general point clouds that represent the morphology of the cell.

  • add_point_layer

    Add point layer to the MeshWork object. This is intended for general point clouds that represent the morphology of the cell, unlike annotations which are typically sparse and represent specific features.

  • apply_mask

    Create a new Cell with vertices masked out.

  • copy

    Create a deep copy of the Cell.

  • transform

    Apply a spatial transformation to all spatial layers in the Cell.

  • get_features

    Map feature columns from various sources to a target layer.

  • mask_context

    Create a masked version of the MeshWork object in a context state.

  • remove_layer

    Remove a morphological layer from the Cell.

  • remove_annotation

    Remove an annotation layer from the Cell.

  • describe

    Generate a hierarchical summary description of the cell and its layers.

Attributes:

name property

name: str

Get the name of the cell (typically a segment id)

meta property

meta: dict

Get the metadata associated with the cell.

layers property

layers: LayerManager

Get the non-annotation layers of the cell.

skeleton property

Skeleton layer for the cell, if present. Otherwise, None.

graph property

Graph layer for the cell, if present. Otherwise, None.

mesh property

Mesh layer for the cell, if present. Otherwise, None.

annotations property

annotations: LayerManager

Annotation Manager for the cell, holding all annotation layers.

s property

Alias for skeleton.

g property

Alias for graph.

m property

Alias for mesh.

a property

Alias for annotations.

l property

Alias for layers.

features property

features: DataFrame

Return a DataFrame listing all feature columns across all layers. Each feature is a row, with the layer name and feature name as columns.

add_layer

Add a initialized layer to the MorphSync.

Parameters:

Raises:

  • ValueError

    If the layer already exists or if the layer type is incorrect.

add_mesh

add_mesh(vertices: Union[ndarray, DataFrame, MeshLayer], faces: Optional[Union[ndarray, DataFrame]] = None, features: Optional[Union[dict, DataFrame]] = None, *, vertex_index: Optional[Union[str, ndarray]] = None, linkage: Optional[Link] = None, spatial_columns: Optional[list] = None) -> Self

Add a mesh layer to the MorphSync.

Parameters:

  • vertices (Union[ndarray, DataFrame, MeshLayer]) –

    The vertices of the mesh, or a MeshLayer object.

  • faces (Union[ndarray, DataFrame], default: None ) –

    The faces of the mesh. If faces are provided as a dataframe, faces should be in dataframe indices.

  • features (Optional[Union[dict, DataFrame]], default: None ) –

    Additional features for the mesh. If passed as dictionary, the key is the feature name and the values are an array of feature values.

  • vertex_index (Optional[Union[str, ndarray]], default: None ) –

    The column to use as a vertex index for the mesh, if vertices are a dataframe.

  • linkage (Optional[Link], default: None ) –

    The linkage information for the mesh.

  • spatial_columns (Optional[list], default: None ) –

    The spatial columns for the mesh, if vertices are a dataframe.

Returns:

add_skeleton

add_skeleton(vertices: Union[ndarray, DataFrame, SkeletonLayer], edges: Optional[Union[ndarray, DataFrame]] = None, features: Optional[Union[dict, DataFrame]] = None, root: Optional[int] = None, *, vertex_index: Optional[Union[str, ndarray]] = None, linkage: Optional[Link] = None, spatial_columns: Optional[list] = None, inherited_properties: Optional[dict] = None) -> Self

Add a skeleton layer to the MorphSync.

Parameters:

  • vertices (Union[ndarray, DataFrame, SkeletonLayer]) –

    The vertices of the skeleton, or a SkeletonLayer object.

  • edges (Union[ndarray, DataFrame], default: None ) –

    The edges of the skeleton.

  • features (Optional[Union[dict, DataFrame]], default: None ) –

    The features for the skeleton.

  • root (Optional[int], default: None ) –

    The root vertex for the skeleton, required of the edges are not already consistent with a single root.

  • vertex_index (Optional[Union[str, ndarray]], default: None ) –

    The vertex index for the skeleton.

  • linkage (Optional[Link], default: None ) –

    The linkage information for the skeleton. Typically, you will define the source vertices for the skeleton if using a graph-to-skeleton mapping.

  • spatial_columns (Optional[list], default: None ) –

    The spatial columns for the skeleton, if vertices are a dataframe.

Returns:

add_graph

add_graph(vertices: Union[ndarray, DataFrame, SkeletonLayer], edges: Optional[Union[ndarray, DataFrame]] = None, features: Optional[Union[dict, DataFrame]] = None, *, vertex_index: Optional[Union[str, ndarray]] = None, spatial_columns: Optional[list] = None, linkage: Optional[Link] = None) -> Self

Add the core graph layer to a MeshWork object. Additional graph layers can be used, but they must be added separately and with unique names.

Parameters:

Returns:

add_point_annotations

add_point_annotations(name: str, vertices: Optional[Union[ndarray, DataFrame]] = None, spatial_columns: Optional[list] = None, *, vertex_index: Optional[Union[str, ndarray]] = None, features: Optional[Union[dict, DataFrame]] = None, linkage: Optional[Link] = None, vertices_from_linkage: bool = False) -> Self

Add point annotations to the MeshWork object. This is intended for annotations which are typically sparse and represent specific features, unlike general point clouds that represent the morphology of the cell.

Parameters:

  • name (str) –

    The name of the annotation layer.

  • vertices (Union[ndarray, DataFrame], default: None ) –

    The vertices of the annotation layer.

  • spatial_columns (Optional[list], default: None ) –

    The spatial columns for the annotation layer.

  • vertex_index (Optional[Union[str, ndarray]], default: None ) –

    The vertex index for the annotation layer.

  • features (Optional[Union[dict, DataFrame]], default: None ) –

    The features for the annotation layer.

  • linkage (Optional[Link], default: None ) –

    The linkage information for the annotation layer. Typically, you will define the target vertices for annotations.

  • vertices_from_linkage (bool, default: False ) –

    If True, the vertices will be inferred from the linkage mapping rather than the provided vertices. This is useful if you want to create an annotation layer that directly maps to another layer without providing separate vertex coordinates.

Returns:

add_point_layer

add_point_layer(name: str, vertices: Union[ndarray, DataFrame], spatial_columns: Optional[list] = None, *, vertex_index: Optional[Union[str, ndarray]] = None, features: Optional[Union[dict, DataFrame]] = None, linkage: Optional[Link] = None) -> Self

Add point layer to the MeshWork object. This is intended for general point clouds that represent the morphology of the cell, unlike annotations which are typically sparse and represent specific features.

Parameters:

  • name (str) –

    The name of the point layer.

  • vertices (Union[ndarray, DataFrame]) –

    The vertices of the point layer.

  • spatial_columns (Optional[list], default: None ) –

    The spatial columns for the point layer.

  • vertex_index (Optional[Union[str, ndarray]], default: None ) –

    The vertex index for the annotation layer.

  • features (Optional[Union[dict, DataFrame]], default: None ) –

    The features for the annotation layer.

  • linkage (Optional[Link], default: None ) –

    The linkage information for the annotation layer. Typically, you will define the target vertices for annotations.

Returns:

apply_mask

apply_mask(layer: str, mask: ndarray, as_positional: bool = False) -> Self

Create a new Cell with vertices masked out.

Parameters:

  • layer (str) –

    The layer name that the mask is based on.

  • mask (ndarray) –

    The mask to apply. Values that are True are preserved, while values that are False are discarded. Can be a boolean array or an array of vertices.

  • as_positional (bool, default: False ) –

    If mask is an array of vertices, this sets whether indices are in dataframe indices or as_positional indices.

Returns:

copy

copy() -> Self

Create a deep copy of the Cell.

transform

transform(transform: Union[ndarray, callable], inplace: bool = False) -> Self

Apply a spatial transformation to all spatial layers in the Cell.

Parameters:

  • transform (Union[ndarray, callable]) –

    If an array, must be the same shape as the vertices of the layer(s). If a callable, must take in a (N, 3) array and return a (N, 3) array.

  • inplace (bool, default: False ) –

    If True, modify the current Cell. If False, return a new Cell.

Returns:

  • Self

    The transformed Cell.

get_features

get_features(features: Union[str, list], target_layer: str, source_layers: Optional[Union[str, list]] = None, agg: Union[str, dict] = 'median') -> DataFrame

Map feature columns from various sources to a target layer.

Parameters:

  • features (Union[str, list]) –

    The features to map from the source layer.

  • target_layer (str) –

    The target layer to map all features to.

  • source_layers (Optional[Union[str, list]], default: None ) –

    The source layers to map the features from. Unnecessary if features are unique.

  • agg (Union[str, dict], default: 'median' ) –

    The aggregation method to use when mapping the features. Anything pandas groupby.agg takes, as well as "majority" which will is a majority vote across the mapped indices via the stats.mode function.

Returns:

  • DataFrame

    The mapped features for the target layer.

mask_context

mask_context(layer: str, mask: ndarray) -> Generator[Self, None, None]

Create a masked version of the MeshWork object in a context state.

Parameters:

  • layer (str) –

    The name of the layer to which the mask applies.

  • mask (array or None) –

    A boolean array with the same number of elements as mesh vertices. True elements are kept, False are masked out.

Example

with mesh.mask_context("layer_name", mask) as masked_mesh: result = my_favorite_function(masked_mesh)

remove_layer

remove_layer(name: str) -> Self

Remove a morphological layer from the Cell.

Parameters:

  • name (str) –

    The name of the layer to remove

Returns:

  • Self

    The Cell object for method chaining

Raises:

  • ValueError

    If the layer does not exist or is a core layer that cannot be removed

remove_annotation

remove_annotation(name: str) -> Self

Remove an annotation layer from the Cell.

Parameters:

  • name (str) –

    The name of the annotation to remove

Returns:

  • Self

    The Cell object for method chaining

Raises:

describe

describe(html: bool = False) -> None

Generate a hierarchical summary description of the cell and its layers.

Provides a tree-like overview including: - Cell name and basic info - Layers section with expandable details - Annotations section with expandable details

Parameters:

  • html (bool, default: False ) –

    If True, create expandable HTML widgets in Jupyter. If False, print formatted string (default).

Returns:

  • None

    Always returns None (prints text or displays HTML widgets)

Examples:

>>> cell.describe()  # Prints formatted string
>>> cell.describe(html=True)  # Shows HTML widgets in Jupyter

Link(mapping: Union[list[int], str], source: Optional[str] = None, target: Optional[str] = None, map_value_is_index: bool = True)

Represents the linkage mapping information.

Parameters:

  • mapping (Union[list[int], str]) –

    The mapping information between the source and target layers. The mapping will have the same length as the source vertices and the values will be the corresponding target vertex indices. If map_value_is_index is True, the mapping values should the dataframe index for target vertices (i.e. df.index), if False they are the positional indices (0-N). If a string, the mapping is the column name in the target's vertex dataframe.

  • source (Optional[str], default: None ) –

    The name of the source layer, typically the one with more vertices than the target. E.g. a graph or mesh to a skeleton, or a graph or skeleton to point annotations. If not provided, will be set to the layer name of the object this is being added to. Either source or target can be undefined, but not both.

  • target (Optional[str], default: None ) –

    The name of the target layer, typically the one with fewer vertices. E.g. a skeleton from a graph or mesh, or point annotations from a skeleton. If not provided, will be set to the layer name of the object this is being added to. Either source or target can be undefined, but not both.

  • map_value_is_index (bool, default: True ) –

    If True, assumes the values in the list or the mapping are a non-positional dataframe index.

Methods:

mapping_to_index

mapping_to_index(vertex_data: DataFrame) -> ndarray

Map positional values to index values


Manager Classes

These classes are used internally by Cell to organize and access different types of data layers. Users should not need to interact with these directly.

LayerManager

LayerManager

LayerManager(managed_layers: Optional[dict] = None, validation: Union[str, Callable] = 'any', context: str = 'layer', initial_layers: Optional[list] = None)

Unified manager for both morphological layers and annotations with flexible validation.

Initialize the unified layer manager.

Parameters:

  • managed_layers (dict, default: None ) –

    Dictionary to store layers in. If None, creates new dict.

  • validation (str or callable, default: 'any' ) –

    Type validation mode: - 'any': Accept any layer type - 'point_cloud_only': Only accept PointCloudLayer - callable: Custom validation function

  • context (str, default: 'layer' ) –

    Context name for error messages ('layer', 'annotation', etc.)

  • initial_layers (list, default: None ) –

    Initial layers to add (with validation)

Methods:

  • get

    Get a layer by name with optional default.

  • describe

    Generate a detailed description of all managed layers.

Attributes:

  • names (list) –

    Return a list of managed layer names.

names property
names: list

Return a list of managed layer names.

get
get(name: str, default: Any = None)

Get a layer by name with optional default.

describe
describe() -> None

Generate a detailed description of all managed layers.

Shows each layer with its metrics, features, and links - same level of detail as individual layer describe() methods.

Returns:

  • None

    Always returns None (prints formatted text)

AnnotationManager

AnnotationManager module-attribute

AnnotationManager = partial(LayerManager, validation='point_cloud_only', context='annotation')

Usage Examples

Creating and Working with Cells

import ossify
import numpy as np

# Create an empty cell
cell = ossify.Cell(name="example_neuron")

# Add a skeleton layer
vertices = np.random.rand(100, 3) * 1000  # Random 3D points
edges = np.column_stack([np.arange(99), np.arange(1, 100)])  # Linear chain
cell.add_skeleton(vertices=vertices, edges=edges, root=0)

# Add a mesh layer  
mesh_vertices = np.random.rand(200, 3) * 1000
faces = np.random.randint(0, 200, (150, 3))  # Random triangular faces
cell.add_mesh(vertices=mesh_vertices, faces=faces)

# Add point annotations
annotation_points = np.random.rand(50, 3) * 1000
cell.add_point_annotations(
    name="synapses", 
    vertices=annotation_points
)

Layer Access and Management

# Access layers by name
skeleton = cell.layers["skeleton"]  
mesh = cell.layers["mesh"]

# Access via properties
skeleton = cell.skeleton
mesh = cell.mesh

# Access annotations
synapses = cell.annotations["synapses"]
synapse_locations = cell.annotations.synapses  # Alternative syntax

# List all available layers
print("Morphological layers:", cell.layers.names)
print("Annotation layers:", cell.annotations.names)
print("All features across layers:")
print(cell.features)

Data Linking and Mapping

# Create a link between skeleton and annotations
from ossify import Link

# Map synapses to nearest skeleton vertices
link = Link(
    mapping=skeleton_vertex_ids,  # Array mapping synapses to skeleton vertices
    source="synapses",
    target="skeleton"
)

cell.add_point_annotations(
    name="linked_synapses",
    vertices=annotation_points,
    linkage=link
)

# Map features between layers
compartment_features = cell.get_features(
    features=["compartment"], 
    target_layer="skeleton",
    source_layers=["mesh"],
    agg="majority"  # Use majority vote for mapping
)

Masking and Filtering

# Apply a mask to create a subset
axon_mask = skeleton.get_feature("is_axon") == True
axon_cell = cell.apply_mask("skeleton", axon_mask)

# Temporary masking with context manager
with cell.mask_context("skeleton", axon_mask) as masked_cell:
    # Work with axon-only data
    axon_length = masked_cell.skeleton.cable_length()
    print(f"Axon length: {axon_length:.2f}")

# The original cell is unchanged after exiting context

Spatial Transformations

# Apply a transformation matrix
transform_matrix = np.array([
    [1, 0, 0],    # Scale x by 1
    [0, 1, 0],    # Scale y by 1  
    [0, 0, 2]     # Scale z by 2
])

# Transform all spatial layers
transformed_cell = cell.transform(transform_matrix)

# Or apply in-place
cell.transform(transform_matrix, inplace=True)

# Apply custom transformation function
def rotate_90_degrees(vertices):
    \"\"\"Rotate 90 degrees around z-axis\"\"\"
    rotation = np.array([
        [0, -1, 0],
        [1,  0, 0], 
        [0,  0, 1]
    ])
    return vertices @ rotation.T

rotated_cell = cell.transform(rotate_90_degrees)

Key Design Principles

Consistent Interface: All layer types share common methods for transformations, masking, and feature management.

Method Chaining: Most methods return self to enable fluent interfaces: cell.add_skeleton(...).add_mesh(...)

Non-destructive Operations: Operations like apply_mask() return new objects, preserving the original data.

Flexible Indexing: Support both DataFrame indices (arbitrary integers) and positional indices (0-based arrays).

Performance Tips

  • Use mask_context() for temporary operations to avoid copying data
  • Leverage the LinkageSystem for efficient cross-layer operations
  • Cache expensive computations using layer properties like csgraph