3-D anatomical surface analysis: symmetry, non-rigid registration, atlas construction and asymmetry mapping
Project description
๐ง pyclarcs
Python toolkit for the automated analysis of 3-D anatomical surfaces, with a focus on endocranial and bilateral structures.
clarcs is a command-line tool built around two core algorithms:
- Symmetry-plane estimation โ Combรจs et al., CVPR 2008
- Non-rigid surface registration โ EM-ICP with symmetric correspondences, TGD geodesic prior, and RKHS Wu-kernel M-step (Combรจs & Prima, CVIU 2019)
Combined into a full population-analysis pipeline: symmetry โ alignment โ non-rigid registration โ atlas โ asymmetry mapping.
Table of contents
- Installation
- Supported formats
- Commands
- Typical pipelines
- Python API
- Data โ PaleoBRAIN dataset
- Registration benchmark
- Repository structure
- Scientific references
- Licence
Installation
pip install pyclarcs
Or from source:
git clone https://github.com/rdebroiz/pyclarcs
cd pyclarcs
pip install -e ".[dev]"
Dependencies (installed automatically):
| Package | Role |
|---|---|
numpy โฅ 1.21 |
Numerics |
scipy โฅ 1.7 |
KD-tree, sparse linear algebra, graph shortest paths |
vtk โฅ 9.0 |
Surface I/O and mesh processing |
numba โฅ 0.57 |
JIT-compiled kernels (4ร speedup on EM stages) |
click โฅ 8.0 |
CLI framework |
Supported formats
Format is inferred from the file extension.
| Extension | Format | Read | Write |
|---|---|---|---|
.vtk |
VTK legacy PolyData (ASCII or binary) | โ | โ |
.vtp |
VTK XML PolyData | โ | โ |
.vtu |
VTK XML UnstructuredGrid (converted to PolyData) | โ | โ |
.ply |
Stanford PLY | โ | โ |
.stl |
STereoLithography | โ | โ |
.obj |
Wavefront OBJ | โ | โ |
Note โ Asymmetry and deformation fields (VECTORS point data) require
.vtkor.vtp.
Commands
Commands are grouped by purpose.
Preprocessing
| Command | Description |
|---|---|
clarcs reorient |
Permute coordinate axes |
clarcs recenter |
Align symmetry plane to x = 0 |
clarcs centerofmass |
Translate to match a reference's centre of mass |
clarcs normalize |
Uniformly scale + translate to match a reference |
clarcs downsample |
Decimate to a target vertex count or ratio |
Symmetry analysis
| Command | Description |
|---|---|
clarcs symplane |
Estimate the bilateral symmetry plane |
clarcs mirror |
Reflect a surface across its symmetry plane |
clarcs asymmetry |
Compute the pointwise asymmetry field |
Non-rigid registration
| Command | Description |
|---|---|
clarcs nlregister |
Non-rigid EM-ICP registration onto a reference |
Atlas & population analysis
| Command | Description |
|---|---|
clarcs atlas |
Build a mean shape atlas from a population |
clarcs project-asym |
Build atlas + project per-subject asymmetries onto it |
Typical pipelines
Preprocessing and registration
# 1. Align symmetry plane to x = 0
clarcs recenter target.vtk target-rc.vtk --save-plane
# 2. Match size and centre of mass to the reference
clarcs normalize target-rc.vtk target-rcs.vtk --target reference.vtk
# 3. Non-rigid EM-ICP registration
clarcs nlregister target-rcs.vtk reference.vtk target-registered.vtk \
--deformation target-deformation.vtk
Atlas construction
# Build a mean shape atlas from a directory of preprocessed surfaces
clarcs atlas subjects/ atlas.vtk --save-registered
# Lower resolution first (useful for large surfaces)
clarcs downsample subjects/B01.ply subjects/B01-5k.ply --target-n 5000
Asymmetry analysis on an atlas
# All-in-one: build atlas, compute subject asymmetries, project onto atlas
clarcs project-asym subjects/ mean-asym.vtp --save-atlas atlas.vtp \
--save-stats --save-individual
# Incremental (reuse pre-computed atlas and asymmetry fields)
clarcs asymmetry B01.ply B01-asym.vtk
clarcs project-asym subjects/ mean-asym.vtp \
--atlas atlas.vtp \
--registered-dir registered/ \
--asymmetry-dir asymmetry/
data/run_pipeline.py automates the preprocessing + registration sequence
on the bundled test surfaces:
python data/generate_samples.py # create test surfaces (once)
python data/run_pipeline.py results/
Python API
Symmetry plane
from pyclarcs.io import load_surface, save_plane_vtk
from pyclarcs.principal_axes import best_principal_axis_plane
from pyclarcs.coarse import coarse_symmetry
from pyclarcs.fine import em_icp_sym, em_icp_sym_corres
points, polygons = load_surface("surface.vtk")
plane = best_principal_axis_plane(points)
plane = coarse_symmetry(points, plane)
plane = em_icp_sym(points, plane)
plane = em_icp_sym_corres(points, plane)
plane.save("plane.pl")
Non-rigid registration
from pyclarcs.io import load_surface, load_surface_with_normals, save_surface
from pyclarcs.nonrigid import register, apply_deformation
mov_pts, mov_poly, mov_normals = load_surface_with_normals("target.vtk")
ref_pts, ref_poly, ref_normals = load_surface_with_normals("reference.vtk")
# Symmetric correspondences + TGD prior + RKHS M-step are all on by default
def_field = register(
mov_pts, mov_normals,
ref_pts, ref_normals,
mov_poly, ref_poly,
)
warped = apply_deformation(mov_pts, def_field)
save_surface("registered.vtk", warped, mov_poly)
Atlas construction
from pyclarcs.io import load_surface_with_normals, save_surface
from pyclarcs.atlas import build_atlas
subjects = [load_surface_with_normals(p) for p in sorted(paths)]
atlas_pts, atlas_poly, registered = build_atlas(subjects, atlas_iter=3)
save_surface("atlas.vtk", atlas_pts, atlas_poly)
Asymmetry projection
from pyclarcs.io import load_vector_field
from pyclarcs.atlas import project_asymmetry_to_atlas
import numpy as np
# registered[i]: atlas vertices in subject i's space (from build_atlas)
# asym_fields[i]: asymmetry field at subject i's vertices (from clarcs asymmetry)
projected = project_asymmetry_to_atlas(registered, asym_fields, subject_pts)
mean_asym = np.stack(projected).mean(axis=0) # (N, 3) mean field on atlas
Data โ PaleoBRAIN dataset
75 brain surfaces (B01โB75) and 75 endocasts (E01โE75) from the PaleoBRAIN project (Balzeau A., 2025, doi:10.48579/PRO/KZMMLM).
# Download first 10 subjects (brains + endocasts), resample to 5 000 vertices
python data/download_paleobrain.py --n 10 --target-n 5000
# Brains only, all 75
python data/download_paleobrain.py --type brain
Registration benchmark
MNI pial endocranium (10 k vertices), synthetic deformation of 8 Gaussian bumps ร 5 mm amplitude. RMS before: 2.28 mm.
| Configuration | RMS after | Improvement |
|---|---|---|
| Baseline (Laplacian) | 0.333 mm | 85.4 % |
| + Symmetric correspondences + TGD | 0.267 mm | 88.3 % |
| + RKHS M-step (default) | 0.190 mm | 91.6 % |
See docs/nlregister.md for full details and parameters.
Repository structure
pyclarcs/
โโโ pyproject.toml
โโโ README.md
โโโ docs/ โ per-command documentation
โ โโโ reorient.md
โ โโโ symplane.md
โ โโโ recenter.md
โ โโโ centerofmass.md
โ โโโ normalize.md
โ โโโ mirror.md
โ โโโ downsample.md
โ โโโ nlregister.md
โ โโโ atlas.md
โ โโโ asymmetry.md
โ โโโ project-asym.md
โโโ data/
โ โโโ generate_samples.py โ generate synthetic + MNI test surfaces
โ โโโ download_paleobrain.py โ download PaleoBRAIN dataset
โ โโโ benchmark_compare.py โ compare clarcs / CPD / BCPD
โ โโโ run_pipeline.py โ run the full pipeline end-to-end
โโโ src/pyclarcs/
โโโ _cli.py โ CLI entry-point (clarcs command)
โโโ symmetry.py โ SymmetryPlane class
โโโ principal_axes.py โ inertia tensor initialisation
โโโ io.py โ multi-format surface I/O (VTK 9+)
โโโ coarse.py โ coarse ICP with trimmed estimator
โโโ fine.py โ EM-ICP annealing + doubly-stochastic
โโโ alignment.py โ rigid transforms (recenter, rescale, โฆ)
โโโ mesh.py โ adjacency, TGD, Wu kernel graph
โโโ nonrigid.py โ register(), _em_icp(), _build_hierarchy()
โโโ atlas.py โ build_atlas(), project_asymmetry_to_atlas()
โโโ _numba_kernels.py โ JIT-compiled inner loops (internal)
Scientific references
Combรจs B., Hennessy R., Waddington J., Roberts N., Prima S. Automatic symmetry plane estimation of bilateral objects in point clouds. IEEE CVPR 2008. Anchorage, United States.
Abadie A., Combรจs B., Haegelen C., Prima S. CLARCS, a C++ Library for Automated Registration and Comparison of Surfaces: Medical Applications. MeshMed @ MICCAI 2011. Toronto, Canada, pp. 117โ126.
Combรจs B., Prima S. New algorithms for the deformable registration of brain images. Medical Image Analysis / CVIU 2019.
Balzeau A. (2025). Database of 75 endocasts and 75 brains obtained on the same sample of volunteers. doi:10.48579/PRO/KZMMLM
Licence
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyclarcs-0.4.1.tar.gz.
File metadata
- Download URL: pyclarcs-0.4.1.tar.gz
- Upload date:
- Size: 58.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
376d39ee09b4e5b31d2adc30dbf4eeace96c430ad60e867661cf79fff9a8a47d
|
|
| MD5 |
9da9d525b5c509c134f12d71cb786665
|
|
| BLAKE2b-256 |
afbaceb8829021a9088f49b0f18f92dec27952023c4dcf30ad372547a47211a9
|
File details
Details for the file pyclarcs-0.4.1-py3-none-any.whl.
File metadata
- Download URL: pyclarcs-0.4.1-py3-none-any.whl
- Upload date:
- Size: 58.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33eabfdf88dd55ebf0f3257c22c5d3812f18c536aa2851813dbc815241fc892f
|
|
| MD5 |
ff03015a5ba4c84f08915edcdc1c610c
|
|
| BLAKE2b-256 |
8e12a1070da4d523a95407b0f2731eb181c7a55d5f08e01a7b8d33d574d73562
|