Metadata-Version: 2.4
Name: niftimesh
Version: 0.1.1
Summary: Watertight, smooth STL reconstruction from NIfTI segmentations (boolean-CSG peel or independent organs).
Author: Justin
License: Apache-2.0
Project-URL: Homepage, https://github.com/77even/NiftiMesh
Project-URL: Repository, https://github.com/77even/NiftiMesh
Project-URL: Issues, https://github.com/77even/NiftiMesh/issues
Keywords: nifti,stl,segmentation,marching-cubes,mesh,medical-imaging,csg,vtk,meshlib,3d-reconstruction,surface
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Healthcare Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: numpy>=1.21
Requires-Dist: scipy>=1.7
Requires-Dist: vtk>=9.1
Requires-Dist: nibabel>=3.2
Provides-Extra: csg
Requires-Dist: meshlib>=3.0; extra == "csg"
Provides-Extra: sitk
Requires-Dist: SimpleITK>=2.0; extra == "sitk"
Provides-Extra: all
Requires-Dist: meshlib>=3.0; extra == "all"
Requires-Dist: SimpleITK>=2.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: meshlib>=3.0; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

<div align="center">

# NiftiMesh

**Watertight, smooth STL reconstruction from NIfTI segmentations.**

[![PyPI](https://img.shields.io/pypi/v/niftimesh.svg?cacheSeconds=300)](https://pypi.org/project/niftimesh/)
[![Python](https://img.shields.io/pypi/pyversions/niftimesh.svg?cacheSeconds=300)](https://pypi.org/project/niftimesh/)
[![Downloads](https://img.shields.io/pypi/dm/niftimesh.svg?cacheSeconds=300)](https://pypi.org/project/niftimesh/)
[![Release](https://img.shields.io/github/v/release/77even/NiftiMesh.svg?cacheSeconds=300)](https://github.com/77even/NiftiMesh/releases/latest)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)

</div>

Turn a multi-label `.nii.gz` segmentation into one clean, closed STL surface per
label — **solid, watertight, manifold, self-intersection-free**. In `csg` mode,
adjacent regions share their interface seam *bit-identically*, so the parts
assemble seamlessly in 3D Slicer / Mimics.

<img src="https://raw.githubusercontent.com/77even/NiftiMesh/main/assets/comparison.png" width="100%">
<img src="https://raw.githubusercontent.com/77even/NiftiMesh/main/assets/closeup.png" width="100%">

*Left → right: naive marching cubes (voxel staircase) · a typical 3D Slicer
default export · NiftiMesh (smooth, watertight, seamless).*

## What it's for

A multi-label segmentation volume → per-label STL meshes. Two modes:

- **`csg`** — for **one structure split by internal interfaces**: lung lobes /
  segments, Couinaud liver segments. Neighbouring labels share their cut seam
  exactly (no crack, no black line).
- **`independent`** — for **disjoint organs** (liver + spleen + kidneys, vessels):
  each label becomes its own closed, smoothed surface.

You define the output names — nothing is hard-coded to any anatomy.

## Install

```bash
pip install "niftimesh[csg]"   # csg mode (needs meshlib)
pip install niftimesh          # independent + naive modes only
```

Python ≥ 3.9. NIfTI is read via `nibabel` (bundled) or `SimpleITK` if installed.
Prebuilt wheels are also attached to each
[GitHub Release](https://github.com/77even/NiftiMesh/releases/latest).

## Usage

```bash
# names from a JSON file: {"1": "left_lower_lobe", "2": "left_upper_lobe", ...}
niftimesh seg.nii.gz out/ --mode csg --label-names names.json --suffix _3d

# omit --label-names to get label_1.stl, label_2.stl, ...
niftimesh organs.nii.gz out/ --mode independent
```

```python
from niftimesh import nifti_to_stl

nifti_to_stl("seg.nii.gz", "out/", mode="csg",
             label_names={1: "left_lower_lobe", 2: "left_upper_lobe"})

# in-memory: numpy (z, y, x) label volume -> {label: vtkPolyData}
from niftimesh import reconstruct
meshes = reconstruct(seg, spacing=(0.84, 0.84, 1.0), mode="independent")
```

## License

[Apache 2.0](LICENSE) © 2026 Justin
