From 067bfb2e71fa757f7423d1df4a76afdf0d718889 Mon Sep 17 00:00:00 2001 From: Stephen Aylward Date: Tue, 7 Jul 2026 11:10:07 -0400 Subject: [PATCH 1/2] ENH: Cleaned up infrastructure and documentation --- .agents/agents/implementation.md | 3 +- .cursor/rules/project-standards.mdc | 106 ---- .gitattributes | 1 + .vscode/settings.json | 55 -- AGENTS.md | 34 +- CLAUDE.md | 23 +- MANIFEST.in | 1 - README.md | 869 ++-------------------------- docs/PYPI_RELEASE_GUIDE.md | 320 ---------- docs/README.md | 2 +- docs/architecture.rst | 112 +++- docs/assets/example.gif | 3 + docs/changelog.rst | 25 - docs/cli_scripts/overview.rst | 2 +- docs/conf.py | 1 - docs/contributing.rst | 3 - docs/developer/architecture.rst | 7 +- docs/developer/extending.rst | 5 +- docs/examples.rst | 551 ------------------ docs/faq.rst | 10 +- docs/index.rst | 13 +- docs/installation.rst | 2 +- docs/quickstart.rst | 2 +- docs/tutorials.rst | 284 ++++++++- pyproject.toml | 2 +- src/physiotwin4d/__init__.py | 17 +- statistics.md | 171 +++--- 27 files changed, 564 insertions(+), 2060 deletions(-) delete mode 100644 .cursor/rules/project-standards.mdc delete mode 100644 .vscode/settings.json delete mode 100644 docs/PYPI_RELEASE_GUIDE.md create mode 100644 docs/assets/example.gif delete mode 100644 docs/changelog.rst delete mode 100644 docs/examples.rst diff --git a/.agents/agents/implementation.md b/.agents/agents/implementation.md index b9d7b21..20af608 100644 --- a/.agents/agents/implementation.md +++ b/.agents/agents/implementation.md @@ -5,7 +5,8 @@ tools: Read, Edit, Write, Bash, Glob, Grep --- You are an implementation agent for PhysioTwin4D, an early-alpha scientific Python library -that converts 4D CT scans into animated USD models for NVIDIA Omniverse. +that provides methods, workflows, tutorials, and a CLI for creating personalized +physiological digital twins from 3D medical images. ## Pipeline diff --git a/.cursor/rules/project-standards.mdc b/.cursor/rules/project-standards.mdc deleted file mode 100644 index 6769f2c..0000000 --- a/.cursor/rules/project-standards.mdc +++ /dev/null @@ -1,106 +0,0 @@ ---- -description: PhysioTwin4D project standards and workflow preferences -alwaysApply: true ---- - -# PhysioTwin4D Project Standards - -## File Operations - -**ALWAYS use git commands for file operations in this repository:** - -```bash -# Moving files -git mv old_path new_path - -# Deleting files -git rm file_path - -# Renaming files -git mv old_name.py new_name.py -``` - -❌ **Don't use**: `mv`, `rm`, `cp` directly -✅ **Do use**: `git mv`, `git rm` to maintain git history - -## Documentation - -**NEVER create .md files unless explicitly requested by the user or unless creating a new module in a directory that does not already have a README.md, then a README.md may be created if appropriate.** - -❌ **Don't create**: -- `MIGRATION.md` -- `CHANGES.md` -- `UPDATE_SUMMARY.md` -- `MODERNIZATION_*.md` -- `*_GUIDE.md` -- `*_EXAMPLE.md` -- `*_SUMMARY.md` -- Any other .md files without explicit user request except README.md files for new modules. - -✅ **Do document**: -- In-code docstrings -- README files for new modules -- Inline comments for complex logic -- Update existing README.md files when needed -- API documentation in existing docs structure - -## Backward Compatibility - -**Backward compatibility is NOT a priority** for this project: - -- Feel free to make breaking changes to improve code quality -- Remove deprecated code without extensive migration paths -- Update APIs for clarity and consistency -- Prioritize modern, clean design over legacy support - -## Code Style - -- Use descriptive variable and function names -- Add type hints to Python functions -- Keep functions focused and small -- Use `logging` module instead of `print` statements -- Follow PEP 8 for Python code - -## Python Commands - -**Use `py` for running Python on this Windows system:** - -```bash -# Running Python -py script.py - -# Running modules -py -m pytest tests/ - -# Python version -py --version -``` - -❌ **Don't use**: `python` (not available in PATH) -✅ **Do use**: `py` (Python launcher for Windows) - -## Testing - -- Test new functionality with Jupyter notebooks in `experiments/` -- Update existing tests when changing APIs -- Use meaningful test names that describe what is being tested - -## Git Workflow - -**Do NOT stage files automatically:** - -❌ **Don't use**: `git add`, `git stage` -✅ **Do use**: `git status` to show what changed -✅ **User will**: Stage files themselves when ready - -The user prefers to review and stage changes manually. - -**Other git guidelines:** -- Use `git rm` and `git mv` for file operations -- Make atomic commits with clear messages -- Don't commit large binary files (add to `.gitignore`) -- Use `git status` to verify changes before committing - -**Code and documentation versions:** -- Refer to code and documentation in the folder reference_code to get examples and documentation of the APIs and best practices for the advanced libraries used in this project: - - ITK, VTK, PyVista, Omniverse, PhysicsNeMo, Simpleware, MONAI, and OpenUSD diff --git a/.gitattributes b/.gitattributes index 9298cc1..cf20d4a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ *.hdf filter=lfs diff=lfs merge=lfs -text *.mha filter=lfs diff=lfs merge=lfs -text +docs/assets/*.gif filter=lfs diff=lfs merge=lfs -text diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 82100e3..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - // Use Ruff for linting and formatting - "[python]": { - "editor.defaultFormatter": "charliermarsh.ruff", - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.fixAll": "explicit", - "source.organizeImports": "explicit" - }, - "editor.rulers": [ - 88 - ], - "editor.tabSize": 4, - "editor.insertSpaces": true, - "editor.wordWrap": "wordWrapColumn", - "editor.wordWrapColumn": 88, - "editor.wrappingIndent": "indent", - "editor.comments.insertSpace": true - }, - // Ruff extension settings (new native server) - "ruff.enable": true, - "ruff.lint.enable": true, - "ruff.organizeImports": true, - "ruff.fixAll": true, - "ruff.configurationPreference": "filesystemFirst", - // Python analysis and type checking (Pylance) - "python.analysis.typeCheckingMode": "basic", - "python.analysis.diagnosticSeverityOverrides": { - "reportUndefinedVariable": "warning", - "reportMissingImports": "warning" - }, - // Jupyter notebook settings - "jupyter.pylanceHandlesNotebooks": true, - // General editor settings - "editor.rulers": [ - 88 - ], - "editor.wordWrapColumn": 88, - "editor.formatOnSave": true, - "editor.formatOnPaste": false, - "files.trimTrailingWhitespace": true, - "files.insertFinalNewline": true, - "files.trimFinalNewlines": true, - // Disable deprecated Python formatting settings - "python.linting.enabled": false, - "python.linting.flake8Enabled": false, - "python.linting.pylintEnabled": false, - "python.formatting.provider": "none", - "python.languageServer": "None", - "cursorpyright.analysis.diagnosticSeverityOverrides": { - "reportUndefinedVariable": "warning", - "reportMissingImports": "warning" - }, - "cursorpyright.analysis.typeCheckingMode": "basic" -} diff --git a/AGENTS.md b/AGENTS.md index a566903..c160c21 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,10 +2,14 @@ Role-based guidance for AI agents working in this repository. -PhysioTwin4D converts 4D CT scans into animated USD models for NVIDIA -Omniverse. It is an **early-alpha** scientific Python library. Clarity beats -premature optimization. Breaking changes are acceptable. Backward compatibility -is not a goal. +PhysioTwin4D is a collection of methods, workflows, tutorials, and CLI tools +for creating personalized physiological digital twins: starting from a 3D +medical image of a subject, extracting anatomic models, and then using AI +surrogates to estimate the subject's physiological processes (initially +cardiac and respiratory motion, expanding to electrophysiology, blood flow, +and organ perfusion). It is an **early-alpha** scientific Python library. +Clarity beats premature optimization. Breaking changes are acceptable. +Backward compatibility is not a goal. ## Role @@ -42,8 +46,8 @@ Non-Python tools used by contributor workflows: ## Common Commands -Prefer the repository-local virtual environment at `.\venv`. Activate it before -issuing Python commands so `python`, console scripts, and `uv pip` all use that +Prefer the repository-local virtual environment at `.\venv` or `..\venv`. Activate it +before issuing Python commands so `python`, console scripts, and `uv pip` all use that environment. If activation is not possible, invoke `.\venv\Scripts\python.exe -m ...` directly. Use `uv run ...` only when the local `venv` is unavailable and you need uv to create or sync an environment. @@ -98,13 +102,10 @@ Version bumping: `bumpver update --patch`, `--minor`, or `--major`. ## Codex Sandbox - If a Python command fails with - `No Python at '"C:\Users\saylward\AppData\Local\Programs\Python\Python311\python.exe'`, - do not assume Python 3.11 is missing. The Codex sandbox can break the - launcher or venv path. -- Use the temporary validation environment instead: - `C:\Users\saylward\AppData\Local\Temp\pt4d-uv-env\Scripts\python.exe`. - It has been verified as Python 3.11.9 with `ruff` available. -- Run that temporary venv outside the sandbox when needed. Treat this as an + `No Python at ...` + do not assume Python is missing. The sandbox can break the launcher or venv path. +- Use the local virtual environment instead: `.\venv`, `..\venv`, `.\.venv`, `..\.venv` +- Run that venv outside the sandbox when needed. Treat this as an environment/sandbox workaround, not a dependency or installation problem. ## Universal Rules @@ -128,12 +129,10 @@ Version bumping: `bumpver update --patch`, `--minor`, or `--major`. below 88 characters. - Full type hints are required under strict mypy. Use `Optional[X]`, not `X | None`. -- Run `python -m pytest tests/ -v` from the active `.\venv` to verify changes. +- Run `python -m pytest tests/ -v` from the active virtual venv to verify changes. Slow, GPU, Simpleware, experiment, and tutorial tests are auto-skipped unless their opt-in flag is passed. -- The `requires_data` marker no longer exists. Tests that need external data - download it automatically via the session fixtures. - Consult `docs/API_MAP.md` to locate classes, methods, and signatures before searching manually. - Do not commit changes or make pull requests unless specifically told to do so. @@ -150,8 +149,9 @@ Version bumping: `bumpver update --patch`, `--minor`, or `--major`. - Convert surfaces to USD right-handed Y-up only at USD export by `vtk_to_usd.lps_points_to_usd`: USD `+X=Left`, `+Y=Superior`, `+Z=Anterior`. -- Masks are ITK images with integer labels. Keep anatomy group IDs consistent +- Labelmaps are ITK images with integer labels. Keep anatomy group IDs consistent across segmenters. +- Masks are binary ITK images. - Transforms are ITK composite transforms stored in compressed `.hdf` files. ## Implementation Role diff --git a/CLAUDE.md b/CLAUDE.md index ec23b5c..6eeb75a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,9 +2,6 @@ Project guidance for Claude Code in this repository. -Codex and other AI agents should use `AGENTS.md` as the primary shared -instructions file. Claude-specific behavior and slash-command usage remain here. - ## Role: We are developing open-source code for scientific AI libraries. Leverage GPU-accelerated methods when appropriate. @@ -46,21 +43,6 @@ py -m pytest tests/ -v py -m pytest tests/test_contour_tools.py -v py -m pytest tests/test_contour_tools.py::test_extract_surface -v -# Opt-in buckets (each flag enables one marker family) -py -m pytest tests/ -v --run-slow # tests marked 'slow' -py -m pytest tests/ -v --run-gpu # tests marked 'requires_gpu' -py -m pytest tests/ -v --run-simpleware # tests marked 'requires_simpleware' -py -m pytest tests/ -v --run-physicsnemo # tests marked 'requires_physicsnemo' -py -m pytest tests/ -v --run-experiments # tests marked 'experiment' -py -m pytest tests/ -v --run-tutorials # tests marked 'tutorial' - -# Enable every bucket at once (equivalent to passing all --run-* flags). -# Self-hosted CI GPU runner uses this after installing [test,cuda13,physicsnemo]. -py -m pytest tests/ -v --run-all - -# Typical local GPU profile. -py -m pytest tests/ -v --run-gpu --run-slow - # With coverage py -m pytest tests/ --cov=src/physiotwin4d --cov-report=html @@ -86,8 +68,9 @@ Regenerate it after any public API change: `py utils/generate_api_map.py` - Surfaces: `pv.PolyData` in LPS (inherited from the source `itk.Image` via `itk.vtk_image_from_image`); converted to USD right-handed Y-up only at USD export by `vtk_to_usd.lps_points_to_usd` (USD +X=Left, +Y=Superior, +Z=Anterior) -- Masks: ITK images with integer labels; consistent anatomy group IDs across all segmenters -- Transforms: ITK composite transforms stored in `.hdf` files with compression +- Labelmaps: ITK images with integer labels defined by anatomy segmenter used. +- Masks: ITK binary images +- Transforms: ITK transforms stored in `.hdf` files with compression ## Testing diff --git a/MANIFEST.in b/MANIFEST.in index 6dcaf39..0498a90 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,7 +3,6 @@ include README.md include LICENSE include CLAUDE.md include CHANGELOG.md -include doc/PYPI_RELEASE_GUIDE.md # Include configuration files include pyproject.toml diff --git a/README.md b/README.md index 185a59b..da68eaf 100644 --- a/README.md +++ b/README.md @@ -1,878 +1,79 @@ # PhysioTwin4D -**Generate anatomic models in Omniverse with physiological motion derived from 4D medical images.** +**A collection of methods, workflows, tutorials, and CLI tools for creating personalized physiological digital twins.** -PhysioTwin4D is a comprehensive medical imaging package that converts 4D CT scans (particularly heart and lung gated CT data) into dynamic 3D models for visualization in NVIDIA Omniverse. The package provides state-of-the-art deep learning-based image processing, segmentation, registration, and USD file generation capabilities. +PhysioTwin4D typically begins with a 3D medical image of a subject, extracts anatomic models from that image, and then uses AI surrogates to estimate the subject's physiological processes — initially focusing on cardiac and respiratory motion, and expanding to electrophysiology, blood flow, and organ perfusion. The package provides methods for forming these physiological AI surrogates and for fine-tuning the segmentation and registration AI methods that power them, with special emphasis on statistical shape models: they capture subject-specific characteristics that help determine subject-specific physiological function, and establish correspondence across subjects to aid AI surrogate generalization and simplify the application of traditional solvers. -## Documentation - -Start with the hosted documentation: - -**https://project-monai.github.io/physiotwin4d/** - -The documentation is the primary entry point for users and contributors. It -includes: +> **Not validated for clinical use.** PhysioTwin4D is a research toolkit. It +> is not a medical device and must not be used for diagnosis, treatment +> planning, or clinical decision-making. -- **Tutorials**: runnable end-to-end workflows and their required datasets. -- **Getting Started**: installation, quickstart, examples, and architecture. -- **CLI & Scripts Guide**: command-line tools for common conversion, - segmentation, registration, and USD workflows. -- **API Reference**: public workflow classes, registration classes, - segmentation classes, USD tools, and utilities. -- **Developer Guides**: architecture, extension points, workflow design, and - implementation conventions. -- **Contributing, Testing, and Troubleshooting**: project practices, validation - commands, and common setup issues. - -> **Not validated for clinical use.** PhysioTwin4D is a 2026.07.0 beta -> research and visualization toolkit. It is not a medical device and must not -> be used for diagnosis, treatment planning, or clinical decision-making. +## Documentation -## Key Features +**https://project-monai.github.io/physiotwin4d/** is the primary entry point +for users and contributors. Key sections: -- **Complete 4D Medical Imaging Pipeline**: End-to-end processing from 4D CT data to animated USD models -- **Multiple AI Segmentation Methods**: TotalSegmentator and Simpleware cardiac segmentation -- **Deep Learning Registration**: GPU-accelerated image registration using Icon algorithm -- **NVIDIA Omniverse Integration**: Direct USD file export for medical visualization -- **Physiological Motion Analysis**: Capture and visualize cardiac and respiratory motion -- **Flexible Workflow Control**: Step-based processing with checkpoint management +- [Installation](https://project-monai.github.io/physiotwin4d/installation.html) and [Quickstart](https://project-monai.github.io/physiotwin4d/quickstart.html) +- [Tutorials](https://project-monai.github.io/physiotwin4d/tutorials.html) — runnable end-to-end workflows and their datasets +- [CLI & Scripts Guide](https://project-monai.github.io/physiotwin4d/cli_scripts/overview.html) — command-line tools for conversion, segmentation, registration, and USD workflows +- [API Reference](https://project-monai.github.io/physiotwin4d/api/index.html) — workflow, registration, segmentation, and USD classes +- [Developer Guides](https://project-monai.github.io/physiotwin4d/developer/architecture.html) — architecture, extension points, and implementation conventions +- [Contributing](https://project-monai.github.io/physiotwin4d/contributing.html) and [Testing](https://project-monai.github.io/physiotwin4d/testing.html) +- [FAQ](https://project-monai.github.io/physiotwin4d/faq.html) and [Troubleshooting](https://project-monai.github.io/physiotwin4d/troubleshooting.html) -## Supported Applications +## Highlights -- **Cardiac Imaging**: Heart-gated CT processing with cardiac motion analysis -- **Pulmonary Imaging**: Lung 4D-CT processing with respiratory motion tracking -- **Medical Education**: Interactive 3D anatomical models with physiological motion -- **Research Visualization**: Advanced medical imaging research in Omniverse -- **Clinical Planning**: Dynamic anatomical models for treatment planning +- **Personalized digital twins**: build subject-specific anatomic models and physiological AI surrogates from 3D/4D medical images +- **Statistical shape models**: capture subject-specific anatomy and establish cross-subject correspondence, aiding AI surrogate generalization and simplifying traditional solver setup +- **Simplified workflows on industry-leading open-source tools**: ICON and Greedy for registration; MONAI with TotalSegmentator and Simpleware for segmentation; Netgen for meshing (LGPL license); scikit-learn for statistical shape modeling; ITK for image processing; PyVista and OpenUSD/Omniverse for geometry manipulation; CuPy for accelerated computing; and PhysicsNeMo for AI surrogates +- **Extensible class hierarchy**: add new segmentation and registration methods, and extend to new data types, organs, and physiological processes, without reworking the workflow layer +- **Physiological motion**: cardiac and respiratory motion today, expanding to electrophysiology, blood flow, and organ perfusion +- **NVIDIA Omniverse as the simulation hub**: the end goal for simulation — a simulation-information hub and gateway to other engines (e.g., Ansys solvers), interactive simulations for treatment planning (e.g., Isaac Sim, Newton), visualization systems (e.g., AR/VR devices), and physical systems (e.g., robots via ROS) +- **CLI and Python API**: installed command-line tools and workflow classes for repeatable, scriptable pipelines ## Installation -### Prerequisites - -- Python 3.11+ (Python 3.11 or 3.12 recommended) -- NVIDIA GPU with CUDA 13 — recommended for production use; CPU-only installation is supported but slow -- 16GB+ RAM (32GB+ recommended for large datasets) -- NVIDIA Omniverse (for USD visualization) -- **Git LFS** (required for running tests: baseline files in `tests/baselines/` are stored with Git LFS; install from [git-lfs.github.com](https://git-lfs.github.com), then run `git lfs install` and `git lfs pull` after cloning) - -### Installation from PyPI - ```bash -# CPU-only PyPI install — works out of the box; a runtime warning points to the GPU extra +# CPU-only — works out of the box; a runtime warning points to the GPU extra pip install physiotwin4d -# CUDA 13 install (recommended for production) +# CUDA 13 (recommended for production) uv pip install "physiotwin4d[cuda13]" ``` -The `[cuda13]` extra installs CuPy. In uv-managed source environments, PyTorch, -torchvision, and torchaudio resolve from the CUDA 13.0 PyTorch wheel index. -There is no need to install PyTorch separately. - -PhysicsNeMo (used only by Tutorial 9) is an optional extra because it brings in -a large CUDA-only toolchain and narrows supported Python versions. Install it -explicitly when needed: - -```bash -pip install "physiotwin4d[physicsnemo]" -``` - -PhysicsNeMo itself requires Python >= 3.11. PhysioTwin4D otherwise supports -Python >= 3.10. - -### Installation from Source - -1. **Clone the repository** (Git LFS is required for tests; install it first from [git-lfs.github.com](https://git-lfs.github.com)): - ```bash - git clone https://github.com/Project-MONAI/physiotwin4d.git - cd physiotwin4d - git lfs install # if not already done - git lfs pull # fetch .hdf and .mha baselines in tests/baselines/ - ``` - -2. **Create virtual environment**: - ```bash - python -m venv venv - source venv/bin/activate # On Windows: venv\Scripts\activate - ``` - -3. **Install uv package manager** (recommended): - ```bash - pip install uv - ``` - -4. **Install PhysioTwin4D**: - ```bash - # CUDA 13 PyTorch is the default for uv-managed source environments - uv pip install -e "." - - # Add CuPy for CUDA 13 GPU acceleration - uv pip install -e ".[cuda13]" - ``` - -### Verify Installation - -```python -import physiotwin4d -from physiotwin4d import WorkflowConvertImageToUSD - -print(f"PhysioTwin4D version: {physiotwin4d.__version__}") -print(WorkflowConvertImageToUSD.__name__) -``` - -## Package Architecture - -### Core Components - -- **Workflow Classes**: Complete end-to-end pipeline processors - - `WorkflowConvertImageToUSD`: 3D/4D image to USD processing workflow - - `WorkflowCreateStatisticalModel`: Create PCA statistical shape model from sample meshes - - `WorkflowFitStatisticalModelToPatient`: Model-to-patient registration workflow -- **Segmentation Classes**: Multiple AI-based chest segmentation implementations - - `SegmentChestTotalSegmentator`: TotalSegmentator-based segmentation - - `SegmentAnatomyBase`: Base class for custom segmentation methods -- **Registration Classes**: Multiple registration methods for different use cases - - Image-to-Image Registration: - - `RegisterImagesICON`: Deep learning-based registration using Icon algorithm - - `RegisterImagesANTS`: Classical deformable registration using ANTs - - `RegisterTimeSeriesImages`: Specialized time series registration for 4D CT - - Model-to-Image/Model Registration: - - `RegisterModelsPCA`: PCA-based statistical shape model registration - - `RegisterModelsICP`: ICP-based surface registration - - `RegisterModelsDistanceMaps`: Mask-based deformable model registration - - `RegisterImagesBase`: Base class for custom registration methods -- **Base Classes**: Foundation classes providing common functionality - - `PhysioTwin4DBase`: Base class providing standardized logging and debug settings -- **Utility Classes**: Tools for data manipulation and conversion - - `TransformTools`: Comprehensive transform manipulation utilities - - `USDTools`: USD file manipulation for Omniverse integration - - `USDAnatomyTools`: Apply surgical materials to anatomy meshes - - `ImageTools`: Medical image processing utilities - - `ContourTools`: Mesh extraction and contour manipulation -- **USD Conversion**: VTK to USD conversion for Omniverse visualization - - `ConvertVTKToUSD`: High-level converter for PyVista/VTK objects with colormap support - - `vtk_to_usd` module: Advanced low-level file conversion library - - `convert_vtk_file()`: Single-file VTK/VTP/VTU to USD facade - - `read_vtk_file()`: Read VTK/VTP/VTU files into MeshData - - `ConversionSettings`: Configurable conversion parameters - - `MaterialData`: USD material definitions - -### Key Dependencies - -- **Medical Imaging**: ITK, MONAI, nibabel, PyVista -- **AI/ML**: PyTorch, CuPy (CUDA 13), transformers, MONAI -- **Registration**: icon-registration, unigradicon -- **Visualization**: USD-core, PyVista -- **Segmentation**: TotalSegmentator - -## Getting Started: Tutorials - -The `tutorials/` directory contains eleven end-to-end Python scripts covering -nine major workflows (Tutorials 9 and 10 each have MeshGraphNet and MLP -variants). They are the recommended starting point for new users. - -| # | Script | Workflow | Dataset | -|---|--------|----------|---------| -| 1 | `tutorials/tutorial_01_heart_gated_ct_to_usd.py` | Heart-gated CT to animated USD | Slicer-Heart-CT (prepare first) | -| 2 | `tutorials/tutorial_02_ct_to_vtk.py` | CT to VTK surfaces | Slicer-Heart-CT (prepare first) | -| 3 | `tutorials/tutorial_03_create_statistical_model.py` | Build PCA shape model | KCL-Heart-Model (manual) | -| 4 | `tutorials/tutorial_04_fit_statistical_model_to_patient.py` | Fit statistical model to patient | KCL-Heart-Model plus Tutorial 3 output | -| 5 | `tutorials/tutorial_05_vtk_to_usd.py` | VTK surfaces to animated USD | output of tutorial 2 | -| 6 | `tutorials/tutorial_06_reconstruct_highres_4d_ct.py` | Reconstruct high-res 4D CT | DirLab-4DCT (manual) | -| 8 | `tutorials/tutorial_08_cardiac_fit_model.py` | Fit the cardiac PCA model and propagate it through gated phases | Bring your own (`D:/PhysioTwin4D/`) | -| 9a | `tutorials/tutorial_09a_cardiac_train_physicsnemo_mgn.py` | Train a PhysicsNeMo MeshGraphNet cardiac stage model (requires `[physicsnemo]` + `torch-geometric`; Python >= 3.11) | Tutorial 8 output | -| 9b | `tutorials/tutorial_09b_cardiac_train_physicsnemo_mlp.py` | Train a PhysicsNeMo MLP cardiac stage model (requires `[physicsnemo]` extra; Python >= 3.11) | Tutorial 8 output | -| 10a | `tutorials/tutorial_10a_cardiac_eval_physicsnemo_mgn.py` | Predict / score cardiac surfaces from a MeshGraphNet checkpoint | Tutorial 9a checkpoint | -| 10b | `tutorials/tutorial_10b_cardiac_eval_physicsnemo_mlp.py` | Predict / score cardiac surfaces from an MLP checkpoint | Tutorial 9b checkpoint | - -Each tutorial is a `# %%` percent-cell Python script. Paths are defined near -the top of the script; edit those constants for custom data/output locations, -or use the installed `physiotwin4d-*` CLI commands when you want path -arguments. - -```bash -# Tutorial 1 (CPU-safe ANTs registration; requires Slicer-Heart-CT data) -python tutorials/tutorial_01_heart_gated_ct_to_usd.py - -# Tutorial 2 (CT to VTK) -python tutorials/tutorial_02_ct_to_vtk.py -``` - -See `tutorials/README.md` for the full tutorial index, dataset preparation -instructions, recommended run order, and tutorial-test instructions. - -### Minimal Slicer-Heart Quickstart - -This quickstart uses the public Slicer-Heart 4D CT sample. Data downloading and -a CUDA-capable GPU are required for practical runtime. - -```bash -python -c "from physiotwin4d import DataDownloadTools; DataDownloadTools.DownloadSlicerHeartCTData('data/test')" - -physiotwin4d-convert-image-to-usd data/test/TruncalValve_4DCT.seq.nrrd \ - --registration-method ANTS \ - --output-dir output/quickstart \ - --project-name slicer_heart_quickstart -``` +See the [installation guide](https://project-monai.github.io/physiotwin4d/installation.html) for GPU setup, source installs, and optional extras (PhysicsNeMo). ## Quick Start -### Command-Line Interface - -After installation, PhysioTwin4D provides command-line tools that are automatically added to your PATH: - -#### Heart-Gated CT to USD - -Process 4D cardiac CT images into dynamic USD models: - ```bash -# Process a single 4D cardiac CT file physiotwin4d-convert-image-to-usd cardiac_4d.nrrd --contrast --output-dir ./results - -# Process multiple time frames -physiotwin4d-convert-image-to-usd frame_*.nrrd --contrast --project-name patient_001 - -# With custom settings -physiotwin4d-convert-image-to-usd cardiac.nrrd \ - --contrast \ - --reference-image ref.mha \ - --registration-iterations 50 \ - --output-dir ./output -``` - -For Python API usage and advanced customization, see the examples below or refer to the CLI implementation in `src/physiotwin4d/cli/`. - -#### Create Statistical Model - -Build a PCA statistical shape model from sample meshes aligned to a reference: - -```bash -# From a directory of sample meshes -physiotwin4d-create-statistical-model \ - --sample-meshes-dir ./input_meshes \ - --reference-mesh average_mesh.vtk \ - --output-dir ./pca_output - -# With custom PCA components -physiotwin4d-create-statistical-model \ - --sample-meshes-dir ./meshes \ - --reference-mesh average_mesh.vtk \ - --output-dir ./pca_output \ - --pca-components 20 -``` - -Outputs: `pca_mean_surface.vtp`, `pca_mean.vtu` (if reference is volumetric), and `pca_model.json`. - -#### Heart Model to Patient Registration - -Register a generic heart model to patient-specific data: - -```bash -# Basic registration -physiotwin4d-fit-statistical-model-to-patient \ - --template-model heart_model.vtu \ - --template-labelmap heart_labelmap.nii.gz \ - --patient-models lv.vtp rv.vtp myo.vtp \ - --patient-image patient_ct.nii.gz \ - --output-dir ./results - -# With PCA shape fitting -physiotwin4d-fit-statistical-model-to-patient \ - --template-model heart_model.vtu \ - --template-labelmap heart_labelmap.nii.gz \ - --patient-models lv.vtp rv.vtp myo.vtp \ - --patient-image patient_ct.nii.gz \ - --pca-json pca_model.json \ - --pca-number-of-modes 10 \ - --output-dir ./results ``` -For implementation details and advanced usage, see the CLI modules in `src/physiotwin4d/cli/`. - -### Python API - Basic Heart-Gated CT Processing - ```python from physiotwin4d import RegisterImagesICON, WorkflowConvertImageToUSD -# Initialize processor processor = WorkflowConvertImageToUSD( input_filenames=["path/to/cardiac_4d_ct.nrrd"], output_directory="./results", project_name="cardiac_model", - registration_method=RegisterImagesICON(), # or RegisterImagesANTS() + registration_method=RegisterImagesICON(), # or RegisterImagesGreedy() ) - -# Run complete workflow final_usd = processor.process() ``` -### Python API - Model to Patient Registration - -```python -from physiotwin4d import WorkflowFitStatisticalModelToPatient -import pyvista as pv -import itk - -# Load generic model and patient data -model_mesh = pv.read("generic_heart_model.vtu") -patient_surfaces = [pv.read("lv.stl"), pv.read("rv.stl")] -reference_image = itk.imread("patient_ct.nii.gz") - -# Initialize and run workflow -workflow = WorkflowFitStatisticalModelToPatient( - template_model=model_mesh, - patient_models=patient_surfaces, - patient_image=reference_image, -) - -# Run the registration pipeline -result = workflow.run_workflow() -registered_mesh = result["registered_template_model_surface"] -``` - -### Custom Segmentation - -```python -from physiotwin4d import SegmentChestTotalSegmentatorWithContrast -import itk - -# Use SegmentChestTotalSegmentator instead for non-contrast studies -segmenter = SegmentChestTotalSegmentatorWithContrast() - -# Load and segment image -image = itk.imread("chest_ct.nrrd") -masks = segmenter.segment(image) - -# Result always contains "labelmap" plus one entry per anatomy group the -# segmenter registered (heart, lung, bone, major_vessels, soft_tissue, -# contrast, other for SegmentChestTotalSegmentatorWithContrast). The exact -# key set is segmenter-specific; check membership when targeting multiple -# segmenters. -labelmap = masks["labelmap"] -heart_mask = masks["heart"] -if "lung" in masks: - lungs_mask = masks["lung"] -``` - -### Image Registration - -```python -from physiotwin4d import RegisterImagesICON, RegisterImagesANTS, RegisterTimeSeriesImages -import itk - -# Option 1: Icon deep learning registration (GPU-accelerated) -registerer = RegisterImagesICON() -registerer.set_modality('ct') -registerer.set_fixed_image(itk.imread("reference_frame.mha")) -results = registerer.register(itk.imread("target_frame.mha")) - -# Option 2: ANTs classical registration -registerer = RegisterImagesANTS() -registerer.set_fixed_image(itk.imread("reference_frame.mha")) -results = registerer.register(itk.imread("target_frame.mha")) - -# Option 3: Time series registration for 4D CT -time_series_reg = RegisterTimeSeriesImages(registration_method=RegisterImagesICON()) -time_series_reg.set_fixed_image(itk.imread("time00.mha")) -transforms = time_series_reg.register_time_series( - moving_images=[ - itk.imread("time00.mha"), - itk.imread("time01.mha"), - itk.imread("time02.mha"), - ], - reference_frame=0, -) - -# Get forward and inverse displacement fields -inverse_transform = results["inverse_transform"] # Fixed to moving -forward_transform = results["forward_transform"] # Moving to fixed -``` - -### VTK to USD Conversion - -PhysioTwin4D provides two APIs for converting VTK data to USD for NVIDIA Omniverse visualization. Repository workflows, experiments, and CLIs use `ConvertVTKToUSD`; `vtk_to_usd` is a public advanced layer for users who need low-level file conversion primitives. - -#### Option 1: High-Level ConvertVTKToUSD (for PyVista/VTK objects) - -```python -from physiotwin4d import ConvertVTKToUSD, SegmentChestTotalSegmentator -import pyvista as pv - -# Load VTK data -meshes = [pv.read(f"cardiac_frame_{i:03d}.vtp") for i in range(20)] - -# Convert to animated USD with anatomical labels. Pass `segmenter` so the -# converter groups labeled prims by anatomy type: -# /World/CardiacModel/heart/, /World/CardiacModel/lung/, ... -# Without `segmenter`, all labeled prims land under /World/CardiacModel/Anatomy. -seg = SegmentChestTotalSegmentator() -converter = ConvertVTKToUSD( - data_basename='CardiacModel', - input_polydata=meshes, - mask_ids=seg.taxonomy.all_labels(), - segmenter=seg, - compute_normals=True -) - -# Optional: Apply colormap visualization -converter.set_colormap( - color_by_array='transmembrane_potential', - colormap='rainbow', - intensity_range=(-80.0, 20.0) -) - -stage = converter.convert('cardiac_motion.usd') -``` - -#### Option 2: Advanced File-Based vtk_to_usd Facade - -```python -from physiotwin4d.vtk_to_usd import ( - ConversionSettings, - MaterialData, - convert_vtk_file, -) - -# Simple single-file conversion -stage = convert_vtk_file('mesh.vtp', 'output.usd') - -# Advanced: custom settings and material -settings = ConversionSettings( - triangulate_meshes=True, - compute_normals=True, - meters_per_unit=1.0, # USD stage units after built-in mm-to-m scaling - times_per_second=60.0, -) - -material = MaterialData( - name="cardiac_tissue", - diffuse_color=(0.9, 0.3, 0.3), - roughness=0.4, -) - -stage = convert_vtk_file( - 'heart.vtp', - 'heart.usd', - data_basename='Heart', - settings=settings, - material=material, -) -``` - -Features: -- Automatic coordinate system conversion (LPS to USD right-handed Y-up) -- Material system with UsdPreviewSurface -- Preserves all VTK data arrays as USD primvars -- Supports VTP, VTK, and VTU file formats - -### Logging and Debug Control - -PhysioTwin4D provides standardized logging through the `PhysioTwin4DBase` class, which is inherited by workflow and registration classes. - -```python -import logging -from physiotwin4d import WorkflowFitStatisticalModelToPatient, PhysioTwin4DBase - -# Control logging level globally for all classes -PhysioTwin4DBase.set_log_level(logging.DEBUG) - -# Or filter to show logs from specific classes only -PhysioTwin4DBase.set_log_classes(["WorkflowFitStatisticalModelToPatient", "RegisterModelsPCA"]) - -# Show all classes again -PhysioTwin4DBase.set_log_all_classes() - -# Query which classes are currently filtered -filtered = PhysioTwin4DBase.get_log_classes() -``` - -Classes that inherit from `PhysioTwin4DBase` provide: -- Standard log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL -- Progress reporting for long-running operations -- Class-based log filtering -- Unified logging interface across the package - -## Experiments and Examples - -The `experiments/` directory contains research scripts that shaped the -toolkit. They are `# %%` percent-cell Python scripts that can be run -top-to-bottom (`python