Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

115 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Brain Morphing Pipeline

This project is an artifact from the master's thesis of Sander Tøkje Hauge and Martin Hegnum Johannessen.

Tentative thesis title: Exploring Cross-Species Neuroanatomy in Augmented Reality.

Tentative subtitle: A reproducible pipeline and Nevrolens extension for interactive cross-species neuroanatomy on Meta Quest 3.

The thesis is completed at NTNU through TDT4900 - Computer Science, Master's Thesis, with delivery in June 2026.

Cross-species cortical surface morphing for neuroscience visualization in Nevrolens.

The pipeline starts from neuroatlas-prep part meshes, builds pair-specific anatomical correspondence, extracts and aligns cortical surfaces, instantiates region labels, and exports OBJ morph frames.

Naming Note

This repository uses both deformation and morphing terminology. Deformation alters a single object's form through stretching or bending, whereas morphing smoothly transforms one entirely different object into another. The current pipeline is technically closer to deformation because it deforms one mesh toward another through correspondence fields. The project name keeps "morphing" because the intended end goal is a smooth cross-species morph from one neuroanatomical surface to another.

Supported Species

Species Atlas Input source
Mouse Allen CCFv3 neuroatlas-prep
Rat Waxholm Space v4 neuroatlas-prep
Marmoset MBM v3 vL neuroatlas-prep
Macaque D99 v2.0 neuroatlas-prep
Human CerebrA Brain neuroatlas-prep

Setup

Requires Python 3.11, just, and neuroatlas-prep outputs.

Install just on macOS:

brew install just

If Homebrew is not available, install through Cargo:

cargo install just
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

If python does not resolve to .venv/bin/python, run scripts through .venv/bin/python or fix the shell PATH/alias first.

Run The Pipeline

The normal entry point is the just recipe. It isolates generated files under output/pair_runs/{source}_to_{target}/ and runs Scripts 1-5.

just morph rat marmoset

The recipe uses .venv/bin/python, so create and install the virtual environment first.

Add --render-video to run Script 6 after frame export:

just morph-video rat marmoset

Direct Python usage is also supported:

python scripts/run_pipeline.py --source rat --target marmoset --frames 30 --clean

To run stages manually:

python scripts/1_build_correspondence.py --create --source rat --target marmoset
python scripts/2_extract_cortical_surfaces.py --species rat marmoset
python scripts/3_align_cortical_surfaces.py --source rat --target marmoset
python scripts/4_instantiate_anatomy.py --species rat marmoset
python scripts/5_morph_cortical_surfaces.py --source rat --target marmoset

Render a video manually after frames exist:

python scripts/6_render_morph_video.py --source rat --target marmoset

Pipeline Stages

Script Purpose Main output
1_build_correspondence.py Build or validate pair-specific anatomical correspondence output/1_correspondence/*.json
2_extract_cortical_surfaces.py Prepare pair-aware cortical meshes and part metadata output/2_cortical_surfaces/ or pair-run equivalent
3_align_cortical_surfaces.py Align source to target with ICP output/3_aligned_meshes/
4_instantiate_anatomy.py Convert part metadata into per-region vertex sets output/4_anatomy/*_regions.json
5_morph_cortical_surfaces.py Build correspondence/deformation field and export frames output/5_morph_sequence/
6_render_morph_video.py Render exported frames video output

Configuration

Configuration lives in config/.

File Controls
config/species_data.yaml Species paths, coordinate transforms, extraction settings
config/pipeline.yaml Output paths, decimation, visualization, logging
config/alignment.yaml ICP alignment settings
config/morphing.yaml Correspondence and morphing settings

The project-level config.yaml is optional. If it exists, it is treated as an override on top of config/*.yaml.

This README is the active documentation. Files under docs/archive/ are historical notes and should not be treated as current pipeline instructions.

Morphing Settings

The current Script 5 path is intentionally narrow:

Setting Meaning
region_constraints.enabled Use anatomical region-constrained correspondence. Disable only for pure NN baseline runs.
balanced_physical_weight Penalizes long source-to-target jumps inside a region.
balanced_target_edge_weight Encourages boundary vertices to stay near target region boundaries.
side_aware_matching Splits bilateral regions by left/right side before matching.
use_curvature_aware Adds curvature as a mild matching feature for folded cortex.
deformation_field Smooths matched displacement vectors within regions before frame export.
experimental.tps_init Optional TPS pre-warp, kept as future/experimental work.
experimental.blend_with_global_nn Optional blend with global NN, not part of the current best default path.

Several older knobs are now internal defaults, not config options: balanced NN, normalized local coordinates, local frame matching, unused-target preference, and side axis x.

Common Tasks

Change pair:

just morph mouse rat

Reuse an existing correspondence file:

python scripts/run_pipeline.py --source mouse --target rat --reuse-correspondence

Change mesh density:

# config/pipeline.yaml
decimation:
  target_vertices: 100000

Run headless:

# config/pipeline.yaml
visualization:
  show_visualizations: false

The pipeline runner writes a temporary runtime config that sets visualizations off automatically.

Outputs And Nevrolens

Pipeline runs write isolated outputs to:

output/pair_runs/{source}_to_{target}/
├── 1_correspondence/
├── 2_cortical_surfaces/
├── 3_aligned_meshes/
├── 4_anatomy/
└── 5_morph_sequence/

Script 5 exports same-topology OBJ frames and sequence_info.json. Script 6 can render those frames to MP4 with:

just morph-video rat marmoset

To use frames in Nevrolens, copy the frame directory into the Unity resources path configured in config/pipeline.yaml:

output:
  unity_export_dir: "../nevrolens/Assets/Nevrolens/Resources/MorphSequences"

Unity import settings for frame OBJs:

Setting Value
Read/Write Enabled On
Mesh Compression Off
Generate Colliders Off unless needed
Normals Import

All frames in one sequence should use the same import settings.

Visual Inspection

Inspect the first, middle, and final frames after Script 5. Good morphs keep regions on the correct side, preserve boundaries, avoid large spikes or deep creases, and end close to the target shape.

Useful checks:

python scripts/visualize_region_correspondence.py --source rat --target marmoset --region Motor
open -a MeshLab output/pair_runs/rat_to_marmoset/5_morph_sequence/frame_0015.obj

For difficult pairs, compare deformation_field: true against false, and try use_midpoint_pivot: true when direct A-to-B morphing is visually jumpy.

Legacy Notes

Landmark-based morphing is legacy. The standard pipeline uses anatomical regions from Script 4 and balanced region correspondence in Script 5. Historical landmark utilities remain in utils/landmark_utils.py and scripts/legacy/, but they are not used by just morph.

Troubleshooting

ModuleNotFoundError from a script usually means the wrong Python executable is running. Use:

source .venv/bin/activate
which python
python -m pip install -r requirements.txt

If which python still points to Anaconda or /usr/bin/python3, run scripts as .venv/bin/python ... until the shell configuration is fixed.

If Script 3 alignment looks poor, inspect output/3_aligned_meshes/{source}_to_{target}/alignment_metadata.json and the aligned OBJ files. Script 3 currently uses ICP only.

If Script 5 creates many inverted faces, first compare runs with and without deformation_field, then try use_midpoint_pivot: true. The current correspondence field is strongest for adjacent species pairs and still imperfect for large lissencephalic-to-gyrencephalic jumps.

Dependencies

The pipeline depends on neuroatlas-prep for harmonized part meshes and uses PyMeshLab for mesh decimation/remeshing. The runner validates the prepared input directories before processing and can cache them into a run with --cache-prep-inputs. It no longer depends on mesh-standardizer.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages