|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Commands |
| 6 | + |
| 7 | +**Python launcher:** Use `py` on this Windows system (not `python`). |
| 8 | + |
| 9 | +```bash |
| 10 | +# Install in editable mode (preferred) |
| 11 | +uv pip install -e . |
| 12 | + |
| 13 | +# Lint and format |
| 14 | +ruff check . --fix |
| 15 | +ruff format . |
| 16 | + |
| 17 | +# Type checking |
| 18 | +mypy src/ |
| 19 | + |
| 20 | +# All pre-commit hooks |
| 21 | +pre-commit run --all-files |
| 22 | + |
| 23 | +# Run fast tests (recommended for development) |
| 24 | +py -m pytest tests/ -m "not slow and not requires_data" -v |
| 25 | + |
| 26 | +# Run a single test file |
| 27 | +py -m pytest tests/test_contour_tools.py -v |
| 28 | + |
| 29 | +# Run a single test by name |
| 30 | +py -m pytest tests/test_contour_tools.py::test_extract_surface -v |
| 31 | + |
| 32 | +# Run tests without GPU-dependent tests |
| 33 | +py -m pytest tests/ --ignore=tests/test_segment_chest_total_segmentator.py \ |
| 34 | + --ignore=tests/test_segment_chest_vista_3d.py \ |
| 35 | + --ignore=tests/test_register_images_icon.py |
| 36 | + |
| 37 | +# Run with coverage |
| 38 | +py -m pytest tests/ --cov=src/physiomotion4d --cov-report=html |
| 39 | + |
| 40 | +# Run experiment notebook tests (opt-in, very slow) |
| 41 | +py -m pytest tests/ --run-experiments |
| 42 | + |
| 43 | +# Create baseline files when missing |
| 44 | +py -m pytest tests/ --create-baselines |
| 45 | +``` |
| 46 | + |
| 47 | +**Version bumping:** `bumpver update --patch` (or `--minor`, `--major`) |
| 48 | + |
| 49 | +## Architecture |
| 50 | + |
| 51 | +### Pipeline Overview |
| 52 | + |
| 53 | +PhysioMotion4D converts 4D CT scans (cardiac or pulmonary) into animated USD models for NVIDIA Omniverse. The pipeline flows: |
| 54 | + |
| 55 | +``` |
| 56 | +4D CT → Segmentation → Registration → Contour Extraction → USD Export |
| 57 | +``` |
| 58 | + |
| 59 | +### Class Hierarchy |
| 60 | + |
| 61 | +All major classes inherit from `PhysioMotion4DBase` (`src/physiomotion4d/physiomotion4d_base.py`), which provides a shared logger named `"PhysioMotion4D"`. Use `self.log_info()`, `self.log_debug()`, etc. — never `print()`. Use `PhysioMotion4DBase.set_log_classes([...])` to filter output to specific classes. |
| 62 | + |
| 63 | +### Workflow Classes (entry points) |
| 64 | + |
| 65 | +- **`WorkflowConvertHeartGatedCTToUSD`**: Full 4D cardiac CT → USD pipeline. Orchestrates: 4D→3D conversion → segmentation (TotalSegmentator) → registration (ICON or ANTs) → contour extraction → USD generation. |
| 66 | +- **`WorkflowCreateStatisticalModel`**: Builds a PCA statistical shape model (sklearn) from a population of aligned meshes. Outputs `pca_model.json`, `pca_mean_surface.vtp`. |
| 67 | +- **`WorkflowFitStatisticalModelToPatient`**: Multi-stage model-to-patient registration: (1) ICP rough alignment → (2) optional PCA shape fitting → (3) mask-to-mask deformable registration → (4) optional Icon final refinement. |
| 68 | +- **`WorkflowReconstructHighres4DCT`**: Reconstructs high-resolution 4D CT from sparse time samples via deformable registration. |
| 69 | + |
| 70 | +### Segmentation Classes |
| 71 | + |
| 72 | +All segment methods return anatomy group masks (heart, lung, major_vessels, bone, soft_tissue, contrast, other, dynamic). The `SegmentAnatomyBase` abstract class defines the interface. |
| 73 | + |
| 74 | +- `SegmentChestTotalSegmentator` — default, CPU-capable |
| 75 | +- `SegmentChestVista3D` — GPU-accelerated MONAI VISTA-3D model |
| 76 | +- `SegmentChestVista3DNIM` — NIM cloud API version (requires `pip install physiomotion4d[nim]`) |
| 77 | +- `SegmentChestEnsemble` — combines multiple methods |
| 78 | +- `SegmentHeartSimpleware` — wraps Simpleware ScanIP SDK (requires Simpleware installation) |
| 79 | + |
| 80 | +### Registration Classes |
| 81 | + |
| 82 | +**Image-to-image:** |
| 83 | +- `RegisterImagesICON` — deep learning, GPU, preferred for 4D CT |
| 84 | +- `RegisterImagesANTs` — classical deformable, CPU-capable |
| 85 | +- `RegisterTimeSeriesImages` — wraps ICON or ANTs for 4D time series; handles reference frame selection |
| 86 | + |
| 87 | +All image registerers follow the interface: `set_fixed_image()` → `register(moving_image)` → returns `{"forward_transform": ..., "inverse_transform": ...}` (ITK composite transforms). |
| 88 | + |
| 89 | +**Model-to-model/image:** |
| 90 | +- `RegisterModelsICP` — centroid + affine ICP using VTK/PyVista |
| 91 | +- `RegisterModelsICPITK` — ICP using ITK |
| 92 | +- `RegisterModelsPCA` — PCA shape space fitting; requires `pca_model.json` |
| 93 | +- `RegisterModelsDistanceMaps` — deformable registration via distance map matching (uses ANTs or ICON internally) |
| 94 | + |
| 95 | +### USD Pipeline |
| 96 | + |
| 97 | +Two APIs exist for VTK→USD conversion: |
| 98 | + |
| 99 | +1. **`ConvertVTKToUSD`** (`convert_vtk_to_usd.py`) — high-level, operates on PyVista objects in memory. Supports colormap overlays, multi-label anatomy, and animated time series. |
| 100 | +2. **`vtk_to_usd/`** subpackage — file-based, modular. Core: `VTKToUSDConverter`, `ConversionSettings`, `MaterialData`. Use `convert_vtk_file()` for simple cases. |
| 101 | + |
| 102 | +`USDTools` and `USDAnatomyTools` handle USD stage merging, time-varying data preservation, and applying surgical materials from a materials library. |
| 103 | + |
| 104 | +### Key Data Conventions |
| 105 | + |
| 106 | +- Medical images use ITK (`itk.Image`); surfaces use PyVista (`pv.PolyData`, `pv.UnstructuredGrid`) |
| 107 | +- Coordinate system: RAS (medical) internally; converted to Y-up for USD/Omniverse export |
| 108 | +- Masks are ITK images with integer labels; anatomy groups use consistent label IDs across segmenters |
| 109 | +- Transforms stored as ITK composite transforms in `.hdf` files |
| 110 | + |
| 111 | +### Testing |
| 112 | + |
| 113 | +- Test baselines are stored in `tests/baselines/` via **Git LFS** — run `git lfs pull` after cloning |
| 114 | +- `tests/conftest.py` provides session-scoped fixtures that chain (download → convert → segment → register); most tests depend on upstream fixtures |
| 115 | +- Test markers: `slow`, `requires_gpu`, `requires_data`, `experiment` (skipped by default; use `--run-experiments`) |
| 116 | +- `test_tools.py` (`src/physiomotion4d/test_tools.py`) provides baseline comparison utilities |
| 117 | + |
| 118 | +### Reference Code |
| 119 | + |
| 120 | +API documentation and examples for advanced third-party libraries (ITK, VTK, PyVista, Omniverse, PhysicsNeMo, Simpleware, MONAI, OpenUSD) are in the `reference_code/` directory. |
| 121 | + |
| 122 | +## File Operations |
| 123 | + |
| 124 | +Use `git mv` / `git rm` for moving or deleting tracked files — not `mv` / `rm` — to preserve git history. |
| 125 | + |
| 126 | +## Documentation Policy |
| 127 | + |
| 128 | +Do **not** create new `.md` files unless explicitly requested. Document via docstrings and inline comments. A `README.md` may be created for new submodules that lack one. |
| 129 | + |
| 130 | +## Code Style |
| 131 | + |
| 132 | +- Single quotes for strings (`'...'`), double quotes for docstrings (`"""..."""`) |
| 133 | +- Full type hints required (`mypy` is strict; `disallow_untyped_defs = true`) |
| 134 | +- `Optional[X]` not `X | None` for ITK compatibility (ruff `UP007` is suppressed) |
| 135 | +- Backward compatibility is **not** a priority — breaking changes are acceptable |
0 commit comments