Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

**A collection of methods, workflows, tutorials, and CLI tools for creating personalized physiological digital twins.**

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.
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 finetuning 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.

> **Not validated for clinical use.** PhysioTwin4D is a research toolkit. It
> is not a medical device and must not be used for diagnosis, treatment
Expand Down
13 changes: 6 additions & 7 deletions docs/architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Data Flow
| |
| +--> RegisterImagesANTS / RegisterImagesGreedy / RegisterImagesICON
| +--> RegisterImagesGreedyICON / RegisterImagesChain (chained methods)
| +--> WorkflowFineTuneICONRegistration (fine-tune ICON on subject data)
| +--> WorkflowFinetuneICONRegistration (finetune ICON on subject data)
v
SegmentChestTotalSegmentator / SegmentChestTotalSegmentatorWithContrast
SegmentHeartSimpleware / SegmentHeartSimplewareTrimmedBranches
Expand Down Expand Up @@ -77,11 +77,10 @@ Primary Workflows
Reconstructs higher-resolution 4D CT frames from a time series and a fixed
high-resolution reference image.

``WorkflowFineTuneICONRegistration``
Fine-tunes a uniGradICON checkpoint on subject-specific image/labelmap/
landmark data, then applies the fine-tuned weights through
:class:`RegisterTimeSeriesImages` to register a list of moving images to a
reference.
``WorkflowFinetuneICONRegistration``
Finetunes a uniGradICON checkpoint on subject-specific image/labelmap/
landmark data and returns the path to the resulting weights, which
:class:`RegisterImagesICON` can then load.

``WorkflowConvertVTKToUSD``
Converts in-memory PyVista/VTK meshes to static or animated USD scenes
Expand Down Expand Up @@ -185,6 +184,6 @@ workflow classes. They are the preferred examples for executable API usage:
* ``physiotwin4d-reconstruct-highres-4d-ct``
* ``physiotwin4d-visualize-pca-modes``

There is no CLI wrapper for ``WorkflowFineTuneICONRegistration`` or for the
There is no CLI wrapper for ``WorkflowFinetuneICONRegistration`` or for the
PhysicsNeMo training/evaluation tutorials; those are used through the Python
API and tutorial scripts.
4 changes: 2 additions & 2 deletions docs/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ Tutorial 5: Fit Statistical Model to Patient
============================================

Script
``tutorials/tutorial_05_heart_to_lung_fit_statistical_model_to_patient.py``
``tutorials/tutorial_05_heart_fit_statistical_model_to_patient.py``
Comment thread
aylward marked this conversation as resolved.

Workflow
``WorkflowFitStatisticalModelToPatient``
Expand Down Expand Up @@ -321,7 +321,7 @@ Inner API usage
Run
.. code-block:: bash

python tutorials/tutorial_05_heart_to_lung_fit_statistical_model_to_patient.py
python tutorials/tutorial_05_heart_fit_statistical_model_to_patient.py

Outputs
Patient-fitted statistical model surfaces and registration diagnostics.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# %% [markdown]
# # Fine-tune uniGradICON on Duke 4D Gated CT Data
# # Finetune uniGradICON on Duke 4D Gated CT Data
#
# Discovers per-patient gated CT images and their precomputed
# SegmentHeartSimpleware labelmaps and applies the project-wide fixed 80/20
# train/test split (sort patients in ``ref_data_dir`` by filename; the first
# 80% are train, the last 20% are test). The train cohort is handed to
# :class:`WorkflowFineTuneICONRegistration`, which builds the paired dataset
# :class:`WorkflowFinetuneICONRegistration`, which builds the paired dataset
# JSON, YAML config, and derived loss-function masks, then launches
# ``unigradicon.finetuning.finetune`` as a subprocess.
#
Expand All @@ -28,8 +28,7 @@
from pathlib import Path
from typing import Optional

from physiotwin4d import WorkflowFineTuneICONRegistration
from physiotwin4d.labelmap_tools import LabelmapTools
from physiotwin4d import WorkflowFinetuneICONRegistration

# %% [markdown]
# ## 1. Configure data, output locations, and the train/test split
Expand All @@ -41,10 +40,10 @@

# Where the workflow writes the dataset JSON, YAML config, derived masks, and
# the uniGradICON ``checkpoints/`` tree. experiment_dir resolves to
# ``output_dir / fine_tune_name``.
# ``output_dir / finetune_name``.
_HERE = Path(__file__).parent
output_dir = _HERE / "results_finetuning"
fine_tune_name = "icon_finetuning"
finetune_name = "icon_finetuning"

# Pre-registration augmentation: ``1-initial_registration.py`` warps every gated
# moving frame into reference space with these backends and writes the init
Expand Down Expand Up @@ -115,9 +114,6 @@
train_mask_files: list[list[Optional[Path]]] = []
valid_train_subjects: list[str] = []

mask_dilation_mm = 3.0
labelmap_tools = LabelmapTools()


# %%
def gather_init_frames(
Expand Down Expand Up @@ -215,13 +211,13 @@ def gather_init_frames(
train_mask_files[subject_index].extend(init_masks)

# %%
workflow = WorkflowFineTuneICONRegistration(
workflow = WorkflowFinetuneICONRegistration(
subject_image_files=[
[str(image_path) for image_path in image_paths]
for image_paths in train_image_files
],
output_dir=output_dir,
fine_tune_name=fine_tune_name,
finetune_name=finetune_name,
subject_ids=valid_train_subjects,
subject_labelmap_files=[
[
Expand All @@ -234,11 +230,10 @@ def gather_init_frames(
[str(mask_path) if mask_path is not None else None for mask_path in mask_paths]
for mask_paths in train_mask_files
],
mask_dilation_mm=0, # masks are already dilated
unigradicon_src_path=unigradicon_src_path,
epochs=500,
)

weights_path = workflow.run_fine_tuning()
print(f"\nFine-tuning complete. Expected weights at: {weights_path}")
weights_path = workflow.process()
print(f"\nFinetuning complete. Expected weights at: {weights_path}")
print(f"Held-out test cohort (for 2-recon_4d_icon_eval.py): {test_subjects}")
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def _build_registrar(
# LPS) by ``0-cardiacGatedCT_segment_and_landmark.py``. Binary registration
# masks come from :meth:`LabelmapTools.convert_labelmap_to_mask` (``>0``
# threshold plus 5 mm dilation), matching the loss-function masks used
# during fine-tuning in ``1-finetune_icon.py``.
# during finetuning in ``1-finetune_icon.py``.

# %%
landmark_tools = LandmarkTools()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

# Clone uniGradICON (feat-add-finetuning branch required for fine-tuning support)
# Clone uniGradICON (feat-add-finetuning branch required for finetuning support)
if [ ! -d "uniGradICON" ]; then
git clone -b feat-add-finetuning https://github.com/uncbiag/uniGradICON.git
else
Expand Down
4 changes: 2 additions & 2 deletions experiments/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ obtaining finer details in 4D data used to train AI motion simulations.
- Traditional ANTs registration library
- CT-appropriate tissue mass-preserving metric (optional)

**Adaptation potential:** This approach can be fine-tuned for:
**Adaptation potential:** This approach can be finetuned for:
- Different anatomical regions (abdomen, pelvis, extremities)
- Alternative imaging modalities (MRI, ultrasound time series)
- Custom registration metrics for specific tissue types
Expand Down Expand Up @@ -180,7 +180,7 @@ to new anatomical regions, physiological processes, and digital twin application
2. **Consult the CLI implementation** - See `src/physiotwin4d/cli/` to identify production classes and methods that implement similar functionality
3. **Identify customization points:**
- Registration parameters (metrics, transforms, optimization)
- Segmentation models (custom training, fine-tuning, label mappings)
- Segmentation models (custom training, finetuning, label mappings)
- Meshing parameters (resolution, smoothing, topology)
- Tissue property mappings (visualization, physics parameters)
4. **Leverage modular design** - Swap components (registration algorithms, segmentation models) as needed
Expand Down
21 changes: 21 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ dependencies = [
"icon-registration>=1.0.0",
"picsl-greedy>=0.0.12",
"scipy>=1.10.0",
# Finetuning (``unigradicon.finetuning``, used by
# WorkflowFinetuneICONRegistration and Tutorial 7) only exists on the
# uniGradICON ``feat-add-finetuning`` branch; see [tool.uv.sources] below.
"unigradicon>=1.0.0",

# Visualization and USD
Expand Down Expand Up @@ -105,6 +108,13 @@ no-build-isolation-package = ["torch-scatter"]
torch = { index = "pytorch-cu130" }
torchvision = { index = "pytorch-cu130" }
torchaudio = { index = "pytorch-cu130" }
# The PyPI unigradicon release ships no ``unigradicon.finetuning`` module, so
# finetuning (WorkflowFinetuneICONRegistration, Tutorial 7) needs this branch.
# Declared as a uv source instead of a PEP 508 direct reference in
# [project.dependencies] because PyPI rejects direct references at upload time.
# pip users must install the branch explicitly:
# pip install "unigradicon @ git+https://github.com/uncbiag/uniGradICON.git@feat-add-finetuning"
unigradicon = { git = "https://github.com/uncbiag/uniGradICON.git", branch = "feat-add-finetuning" }

[[tool.uv.index]]
name = "pytorch-cu130"
Expand Down Expand Up @@ -178,6 +188,16 @@ test = [
"pytest-timeout>=2.0.0",
"coverage[toml]>=7.0.0",
]
# Every optional component at once. Inherits the physicsnemo caveats above:
# torch and setuptools must already be installed, and pip needs
# ``--no-build-isolation`` when torch-scatter has no matching wheel.
all = [
"physiotwin4d[cuda13]",
"physiotwin4d[dev]",
"physiotwin4d[docs]",
"physiotwin4d[physicsnemo]",
"physiotwin4d[test]",
]

[project.urls]
Homepage = "https://github.com/Project-MONAI/physiotwin4d"
Expand Down Expand Up @@ -301,6 +321,7 @@ module = [
"physiotwin4d.cli.visualize_pca_modes",
"physiotwin4d.vtk_to_usd.mesh_utils",
"physiotwin4d.vtk_to_usd.vtk_reader",
"tutorial_07_finetune_icon_dirlab",
"tutorial_08_byod_fit_model_to_patients",
"tutorial_09_byod_train_physicsnemo_mgn",
"tutorial_09_byod_train_physicsnemo_mlp",
Expand Down
6 changes: 3 additions & 3 deletions src/physiotwin4d/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
models and then uses AI surrogates to estimate the subject's physiological
processes, initially cardiac and respiratory motion and expanding to
electrophysiology, blood flow, and organ perfusion. It provides methods for
forming those AI surrogates and for fine-tuning the segmentation and
forming those AI surrogates and for finetuning the segmentation and
registration AI methods that power them, with statistical shape models used
to capture subject-specific characteristics and establish correspondence
across subjects.
Expand Down Expand Up @@ -86,7 +86,7 @@
from .workflow_convert_vtk_to_usd import WorkflowConvertVTKToUSD
from .workflow_reconstruct_highres_4d_ct import WorkflowReconstructHighres4DCT
from .workflow_create_statistical_model import WorkflowCreateStatisticalModel
from .workflow_fine_tune_icon_registration import WorkflowFineTuneICONRegistration
from .workflow_finetune_icon_registration import WorkflowFinetuneICONRegistration
from .workflow_fit_statistical_model_to_patient import (
WorkflowFitStatisticalModelToPatient,
)
Expand All @@ -107,7 +107,7 @@
"WorkflowConvertImageToUSD",
"WorkflowConvertVTKToUSD",
"WorkflowCreateStatisticalModel",
"WorkflowFineTuneICONRegistration",
"WorkflowFinetuneICONRegistration",
"WorkflowReconstructHighres4DCT",
"WorkflowFitStatisticalModelToPatient",
"WorkflowTrainPhysicsNeMo",
Expand Down
2 changes: 1 addition & 1 deletion src/physiotwin4d/cli/reconstruct_highres_4d_ct.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def main() -> int:
"--ICON-iterations",
type=int,
default=None,
help="ICON fine-tuning iterations. Default: None",
help="ICON finetuning iterations. Default: None",
)

# Mask options
Expand Down
10 changes: 6 additions & 4 deletions src/physiotwin4d/register_images_icon.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ class RegisterImagesICON(RegisterImagesBase):
- Mass preservation
- LNCC (Local Normalized Cross Correlation) similarity metric
- Inverse consistent transformations
- Fine-tuning with 50 optimization steps per registration
- Per-registration finetuning, 50 optimization steps by default
(override with set_number_of_iterations())

Inherits from RegisterImagesBase:
- Fixed and moving image management
Expand Down Expand Up @@ -100,7 +101,7 @@ def __init__(self, log_level: int | str = logging.INFO) -> None:
def set_weights_path(self, weights_path: str) -> None:
"""Set a custom weights file for the uniGradICON network.

Use this to load a fine-tuned checkpoint instead of the default
Use this to load a finetuned checkpoint instead of the default
pretrained weights. Clears any previously loaded network so the new
weights are applied on the next call to register().

Expand All @@ -119,7 +120,7 @@ def set_number_of_iterations(self, number_of_iterations: Optional[int]) -> None:
"""Set the number of iterations for ICON registration.

Args:
number_of_iterations: Number of fine-tuning steps for ICON registration
number_of_iterations: Number of finetuning steps for ICON registration
"""
self.number_of_iterations = number_of_iterations

Expand Down Expand Up @@ -224,7 +225,8 @@ def registration_method(
Implementation details:
- Uses UniGradIcon with LNCC loss function
- Optionally applies mass preservation
- Performs 50 fine-tuning steps per registration
- Performs number_of_iterations finetuning steps per registration
(passed to unigradicon as finetune_steps; 50 by default)
- Supports both masked and unmasked registration modes

Example:
Expand Down
Loading
Loading