Skip to main content

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

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 .vtk or .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/

The data/ scripts generate the test surfaces used in the examples above:

clarcs download mni data/           # download MNI pial surfaces (once)
python data/generate_synth_data.py  # generate synthetic ellipsoids + registration pairs

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_synth_data.py      โ† generate synthetic ellipsoids + registration pairs
โ””โ”€โ”€ 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

pyclarcs-0.4.4.tar.gz (62.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyclarcs-0.4.4-py3-none-any.whl (62.5 kB view details)

Uploaded Python 3

File details

Details for the file pyclarcs-0.4.4.tar.gz.

File metadata

  • Download URL: pyclarcs-0.4.4.tar.gz
  • Upload date:
  • Size: 62.6 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

Hashes for pyclarcs-0.4.4.tar.gz
Algorithm Hash digest
SHA256 51b75c0f214637cc877c79b1f4599883570323000299961621f0a68e0f4182f1
MD5 d7b19c4e31bd242caf90ae1fcf72fbbd
BLAKE2b-256 5d77c374c98135044981423b8b6d03d404a7a1cafef9c80d0f082178ac94ed0a

See more details on using hashes here.

File details

Details for the file pyclarcs-0.4.4-py3-none-any.whl.

File metadata

  • Download URL: pyclarcs-0.4.4-py3-none-any.whl
  • Upload date:
  • Size: 62.5 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

Hashes for pyclarcs-0.4.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ecb3c80e13d798c47585cd17c070dd27983e0e4f619b2b7bbf77708a3b5931ad
MD5 a4b6f664c914dc31fd3d60cbf626bc64
BLAKE2b-256 07c9bcc7297ec9978079cbe60cbe9e6af3cf7cb1254628d4674cec23d6ef28f8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page