Metadata-Version: 2.4
Name: morph_spines
Version: 1.1.0
Summary: Package to load and write morphologies with spines
Author-email: Open Brain Institute <info@openbraininstitute.org>
Maintainer-email: Open Brain Institute <info@openbraininstitute.org>
License-Expression: Apache-2.0
Project-URL: repository, https://github.com/openbraininstitute/morph-spines
Project-URL: changelog, https://github.com/openbraininstitute/morph-spines/blob/main/CHANGELOG.rst
Classifier: Development Status :: 5 - Production/Stable
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: h5py>=3.10.0
Requires-Dist: trimesh>=4.0.0
Requires-Dist: neurom>=4.0.4
Requires-Dist: numpy>=1.24
Requires-Dist: scipy>=1.10
Requires-Dist: pandas>=2.0
Requires-Dist: morphio>=3.3
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: nbmake; extra == "test"
Provides-Extra: scripts
Requires-Dist: tables; extra == "scripts"
Requires-Dist: open3d; python_version < "3.13" and extra == "scripts"
Dynamic: license-file

# morph-spines

A Python library for loading, writing, and accessing neuron morphologies with dendritic spine data
from HDF5 files. It provides structured access to spine skeletons, meshes, and spatial
transformations.


## Quick example

### Loading

```python
from morph_spines import load_morphology_with_spines

m = load_morphology_with_spines("neuron.h5", spines_are_centered=True, load_meshes=True)

# Access spine meshes
mesh = m.spines.spine_mesh(0)
print(mesh.vertices.shape, mesh.faces.shape)

# Get only the head region of a spine
head_mesh = m.spines.spine_mesh(0, include_neck=False)

# Spine type classification
spine_type = m.spines.spine_type(0)
```

### Writing

```python
from morph_spines import write_spine_table, write_morphology, write_soma_mesh

# Write a spine table (pandas DataFrame with mandatory columns)
write_spine_table("output.h5", "neuron_01", spine_table_df)

# Write neuron morphology skeleton
write_morphology("output.h5", "neuron_01", points, structure)

# Write soma mesh
write_soma_mesh("output.h5", "neuron_01", vertices, triangles)
```

### Validation

```python
from morph_spines import validate_morph_with_spines_file

# Check file structure only (groups, datasets, metadata)
result = validate_morph_with_spines_file("neuron.h5")

# Also check data integrity (shapes, dtypes, value ranges, cross-references)
result = validate_morph_with_spines_file("neuron.h5", check_data_integrity=True)

print(result)          # Human-readable summary
assert result.is_valid # Use programmatically

### Merging

```python
from pathlib import Path
from morph_spines import merge_morphologies_with_spines

# Merge multiple files without renaming
merge_morphologies_with_spines(
    source_files=[Path("neuron_A.h5"), Path("neuron_B.h5")],
    output_path=Path("merged.h5"),
)

# Merge with renaming (neuron keys and/or spines library names)
src1 = Path("neuron_A.h5")
src2 = Path("neuron_B.h5")
merge_morphologies_with_spines(
    source_files=[src1, src2],
    output_path=Path("merged.h5"),
    rename_map={
        (src1, "morph_001"): "circuit_neuron_42",
        (src2, "morph_001"): "circuit_neuron_43",
    },
)

# Merge without meshes (smaller output)
merge_morphologies_with_spines(
    source_files=[Path("a.h5"), Path("b.h5")],
    output_path=Path("merged_no_meshes.h5"),
    include_meshes=False,
)
```


## Installation

```bash
pip install morph-spines
```

For development:

```bash
git clone https://github.com/openbraininstitute/morph-spines.git
cd morph-spines
pip install -e ".[test]"
```


## Features

- Load and write neuron morphologies with spine data from/to HDF5 files
- Merge multiple morph-with-spines files into one, with optional renaming of neuron keys and
  spines library names
- Access the spine table with per-spine properties (position, orientation, section placement)
- Access spine skeletons (via NeuroM/MorphIO) and meshes (via trimesh)
- Write spine tables, morphologies, soma meshes, spine meshes, and spine skeletons
- Validate spine tables against the format specification before writing
- Validate entire morph-with-spines files (structure and optionally data integrity)
- Head/neck triangle classification with filtering (`include_head`, `include_neck`)
- Support for branched spines with multiple heads
- Spine type classification (thin, mushroom, stubby, filopodium, branched, etc.)
- Lazy or eager mesh loading
- Coordinate transformations between local spine and global neuron frames


## Upgrading from v0.x

Version 1.0 drops support for reading spine tables stored as pandas DataFrames (v0.1 format)
inside HDF5 files. If you have files in the old format, convert them before loading:

```bash
python scripts/h5_dataframe_to_h5_datasets_group.py old_file.h5 new_file.h5
```

The conversion script requires the `tables` package:

```bash
pip install morph-spines[scripts]
```


## File format

The morphology-with-spines format is documented in
[`examples/data/README.md`](examples/data/README.md).


## Development

Run tests:

```bash
pytest
```

Lint:

```bash
ruff check src/ tests/
```

Type check:

```bash
mypy src/
```


## Examples

See the [`examples/`](examples/) folder for Jupyter notebooks demonstrating visualization and
usage.


## License

Copyright (c) 2025-2026 Open Brain Institute.

Licensed under Apache-2.0.
