Role-based guidance for AI agents working in this repository.
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.
We are developing open-source code for scientific AI libraries. Leverage GPU-accelerated methods when appropriate.
- Accuracy.
- Clarity, maintainability, and simplicity.
- Consistency with the rest of the platform and open-source standards.
- Documentation.
- Testing.
- Do not assume. Do not hide confusion. Surface tradeoffs.
- Minimum code that solves the problem. Nothing speculative.
- Touch only what you must. Clean up only your own mess.
- Define success criteria. Loop until verified.
Non-Python tools used by contributor workflows:
- Codex CLI (
codex) - can run the.agents/slash skills and is the default PR-review agent forai_agent_github_reviews.py. - Claude Code CLI (
claude) - can run the.agents/slash skills andai_agent_github_reviews.py --agent claude. Install:winget install Anthropic.ClaudeCode. - gh CLI (
gh) - required byai_agent_github_reviews.pyto fetch PR review data. Install:winget install GitHub.clithengh auth login. Not installable via pip/uv; it is a compiled Go binary.
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.
# Create the repo-local environment if it does not already exist
uv venv venv
.\venv\Scripts\Activate.ps1
# Install in editable mode
uv pip install -e .
# Lint and format
python -m ruff check . --fix && python -m ruff format .
# Type checking
python -m mypy src/ tests/
# All pre-commit hooks
python -m pre_commit run --all-files
# Fast tests
python -m pytest tests/ -v
# Single test file or test by name
python -m pytest tests/test_contour_tools.py -v
python -m pytest tests/test_contour_tools.py::test_extract_surface -v
# Opt-in test buckets
python -m pytest tests/ -v --run-slow
python -m pytest tests/ -v --run-gpu
python -m pytest tests/ -v --run-simpleware
python -m pytest tests/ -v --run-physicsnemo
python -m pytest tests/ -v --run-experiments
python -m pytest tests/ -v --run-tutorials
# Enable every bucket at once (equivalent to passing all --run-* flags)
python -m pytest tests/ -v --run-all
# Typical local GPU profile
python -m pytest tests/ -v --run-gpu --run-slow
# Coverage
python -m pytest tests/ --cov=src/physiotwin4d --cov-report=html
# Create missing baselines
python -m pytest tests/ --create-baselinesVersion bumping: bumpver update --patch, --minor, or --major.
- If a Python command fails with
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.
- Read the relevant source files before proposing changes.
- Runtime classes for workflows, segmentation, registration, and USD tools
inherit from
PhysioTwin4DBase; new runtime classes must too. Standalone utility scripts and data/container/helper classes do not. - In classes that inherit from
PhysioTwin4DBase, useself.log_info()andself.log_debug(), neverprint(). Standalone scripts may useprint(). - No emojis in
.pyfiles; avoid them in docs too. Windows cp1252 encoding has broken this project before. - The public VTK→USD entry point is
ConvertVTKToUSD. Experiments, CLIs, tests, and tutorials must use it. Do not import from thevtk_to_usd/subpackage directly outside ofconvert_vtk_to_usd.pyand the subpackage itself. - Scripts that instantiate
SegmentChestTotalSegmentatormust guard the top-level invocation withif __name__ == "__main__":on Windows (torch.multiprocessingrequires it). - Double quotes for strings and docstrings. Keep lines at or below 88 characters.
- Full type hints are required under strict mypy. Use
Optional[X], notX | None. - Run
python -m pytest tests/ -vfrom the active virtual venv to verify changes. Slow, GPU, Simpleware, experiment, and tutorial tests are auto-skipped unless their opt-in flag is passed. - Consult
docs/API_MAP.mdto locate classes, methods, and signatures before searching manually. - Do not commit changes or make pull requests unless specifically told to do so.
- Images are
itk.Imageobjects with axes X, Y, Z [, T] in LPS world space.itk.imreadnormalizes DICOM, NIfTI, MHA, and NRRD inputs to LPS. Persist images withitk.imwrite(..., compression=True). - 4D time series use shape
(X, Y, Z, T). Never silently squeeze or permute axes. - Surfaces are
pv.PolyDatain LPS, inherited from the sourceitk.Imageviaitk.vtk_image_from_image. - 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. - 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
.hdffiles.
- Summarize current behavior in 2-4 sentences before editing.
- Identify success criteria or metrics.
- Refer to
*_tools.pyfiles for commonly used routines. - Refer to
workspace/reference_code, when available, for third-party library usage. - Propose a numbered plan; confirm before implementing non-trivial structural changes.
- Keep diffs small and reviewable.
- Prefer editing existing modules over creating new ones.
- No backward-compatibility shims: just change the code.
- Strongly prefer real downloaded test data over synthetic data. Request the
session fixtures
test_directories,download_test_data, andtest_imagesso standard datasets are fetched automatically on first use. - Real data exercises preprocessing, resampling, dtype handling, and world-frame metadata paths that synthetic toy volumes silently bypass.
- Only fall back to synthetic
itk.Imageorpv.PolyDatainputs when the behavior under test is a pure unit such as axis arithmetic or dict routing, or when real data would push the test into a slow, GPU, or Simpleware bucket that does not fit the test's purpose. Keep synthetic volumes at or below 64 voxels per side and say so in the docstring. - State image shape and axis order in every test docstring, for example:
shape (X, Y, Z, T) = (64, 64, 32, 1), LPS world frame. - When a test produces an image or surface, compare against a baseline using
src/physiotwin4d/test_tools.pyutilities such asTestTools. - Store baselines under
tests/baselines/, which is tracked by Git LFS. Rungit lfs pullafter cloning. - Run with
--create-baselinesto materialize missing baselines on first use. tests/conftest.pyowns session-scoped fixtures that chain download, convert, segment, and register.- Mark tests that need a GPU, a slow runtime, or a licensed Simpleware install
with
@pytest.mark.requires_gpu,@pytest.mark.slow, or@pytest.mark.requires_simpleware. - Mark experiment and tutorial tests with
@pytest.mark.experimentor@pytest.mark.tutorial. - Tests that just need downloadable data need no marker; the fixture chain handles it.
- Prefer images from
ROOT/data/test/slicer_heart_smallfor tests. - Prefer storing test results in subdirectories under
./results/<test_name>.
- Update docstrings for every changed public method. Keep claims factual.
- Document with docstrings and inline comments.
- Do not create new
.mdfiles unless explicitly requested. - Regenerate
docs/API_MAP.mdafter any public API change from the active.\venv:python utils/generate_api_map.py.
- Propose a numbered design plan with tradeoffs before structural changes.
- Identify every file that will change and how the class hierarchy is affected.
- Flag changes at the ITK/PyVista boundary or the RAS to Y-up coordinate transform as high-risk.
- Use
git mvandgit rm, notmvorrm, to preserve history.