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
9 changes: 5 additions & 4 deletions .agents/agents/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ wherever practical.
- `tests/baselines/` — stored via Git LFS; fetch with `git lfs pull`
- `src/physiotwin4d/test_tools.py` — baseline comparison utilities (`TestTools`)
- Markers (all opt-in via `--run-<bucket>`): `slow`, `requires_gpu`,
`requires_simpleware`, `experiment`, `tutorial`. The `requires_data` marker
`requires_simpleware`, `tutorial`. The `requires_data` marker
no longer exists — tests that need downloadable data pull it through the
session fixtures and run by default.

Expand All @@ -29,7 +29,8 @@ python -m pytest tests/ -v # fast, recomm
python -m pytest tests/test_contour_tools.py -v # single file
python -m pytest tests/test_contour_tools.py::TestContourTools -v # single class
python -m pytest tests/ -v --run-slow # opt into slow tests
python -m pytest tests/ -v --run-gpu --run-slow # typical local GPU profile (CI runner adds --run-simpleware --run-experiments --run-tutorials)
# typical local GPU profile; CI adds --run-simpleware --run-tutorials
python -m pytest tests/ -v --run-gpu --run-slow
python -m pytest tests/ --create-baselines # create missing baselines
```

Expand Down Expand Up @@ -59,8 +60,8 @@ python -m pytest tests/ --create-baselines # create missi
8. Prefer storing results in subdirectories under `./results/<test_name>`.
9. Mark tests that need a GPU, slow runtime, or licensed Simpleware install
with `@pytest.mark.requires_gpu`, `@pytest.mark.slow`, or
`@pytest.mark.requires_simpleware`. Mark experiment and tutorial tests
with `@pytest.mark.experiment` or `@pytest.mark.tutorial`. Tests that just
`@pytest.mark.requires_simpleware`. Mark tutorial tests with
`@pytest.mark.tutorial`. Tests that just
need downloadable data need no marker.
10. Do not mock segmentation or registration models — test real outputs.
11. No emojis in test files (Windows cp1252 encoding has bitten this project).
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ uv pip install -e ".[test,cuda13,physicsnemo]"
pytest tests/ --run-gpu

# Enable every --run-* bucket at once (slow, GPU, simpleware,
# physicsnemo, experiments, tutorials)
# physicsnemo, tutorials)
pytest tests/ --run-all
```

Expand Down
19 changes: 9 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ name: CI
# - requires_gpu -> --run-gpu
# - requires_simpleware -> --run-simpleware (also implies GPU)
# - requires_physicsnemo -> --run-physicsnemo (needs the [physicsnemo] extra)
# - experiment -> --run-experiments
# - tutorial -> --run-tutorials
# --run-all enables every bucket above at once.
# Tests that need external data download it automatically via fixtures.
Expand Down Expand Up @@ -107,13 +106,13 @@ jobs:
run: |
pip list

- name: Run unit tests (fast, no GPU/slow/experiment) - Ubuntu
- name: Run unit tests (fast, no GPU/slow/tutorial) - Ubuntu
if: matrix.os == 'ubuntu-latest'
run: |
xvfb-run -a --server-args="-screen 0 1024x768x24" \
pytest tests/ -v --cov=physiotwin4d --cov-report=xml --cov-report=term --cov-report=html

- name: Run unit tests (fast, no GPU/slow/experiment) - Windows
- name: Run unit tests (fast, no GPU/slow/tutorial) - Windows
if: matrix.os == 'windows-latest'
run: |
pytest tests/ -v --cov=physiotwin4d --cov-report=xml --cov-report=term --cov-report=html
Expand Down Expand Up @@ -414,9 +413,9 @@ jobs:
# - tests/test_transform_tools.py (depends on slow registration tests)
# - tests/test_segment_chest_total_segmentator.py (requires CUDA for TotalSegmentator)
#
# Experiment tests (EXTREMELY SLOW - hours to complete):
# - tests/test_experiments.py (runs all notebooks in experiments/ subdirectories)
# These tests are NEVER run in CI/CD and must be run manually
# Tutorial tests (SLOW - hours to complete):
# - tests/test_tutorials.py (runs every script in tutorials/ end-to-end)
# These tests are NEVER run in the PR CI and must be opted into
# They execute end-to-end workflows that may take multiple hours
#
# To run locally:
Expand All @@ -426,9 +425,9 @@ jobs:
# pytest tests/test_register_images_ANTS.py -v --run-slow
#
# Self-hosted GPU runner enables ALL buckets via --run-all
# (--run-gpu --run-slow --run-simpleware --run-physicsnemo --run-experiments --run-tutorials).
# (--run-gpu --run-slow --run-simpleware --run-physicsnemo --run-tutorials).
# That runner installs the [physicsnemo] extra in addition to [test,cuda13].
#
# To run experiment tests (manual only, extremely slow):
# pytest tests/test_experiments.py -v --run-experiments
# pytest tests/test_experiments.py::test_experiment_heart_gated_ct_to_usd -v --run-experiments
# To run tutorial tests (manual only, slow):
# pytest tests/test_tutorials.py -v --run-tutorials
# pytest tests/test_tutorials.py::TestTutorial01HeartGatedCTToUSD -v --run-tutorials
2 changes: 1 addition & 1 deletion .github/workflows/nightly-health.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Nightly Health

# Run the full test suite (including experiments) on the GPU runner every night.
# Run the full test suite (including tutorials) on the GPU runner every night.
#
# Schedule: 07:00 UTC daily ≈ 02:00 EST / 03:00 EDT
#
Expand Down
6 changes: 2 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ 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)
Expand Down Expand Up @@ -151,7 +150,7 @@ graphify update . # refresh after code changes (AST-only, no API c
`X | None`.
- 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
and tutorial tests are auto-skipped unless their opt-in flag is
passed.
- Do not run pytest with `--run-slow` or `--run-all` unless the user explicitly
asks; those runs take far too long for an interactive session. Default to the
Expand Down Expand Up @@ -219,8 +218,7 @@ graphify update . # refresh after code changes (AST-only, no API c
- 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.experiment` or
`@pytest.mark.tutorial`.
- Mark tutorial tests with `@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_small` for tests.
Expand Down
11 changes: 7 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,18 @@ came from.

## Testing

- Fast tests (recommended for development — slow/GPU/Simpleware/experiment
/tutorial tests are auto-skipped unless their opt-in flag is passed)
- Fast tests (recommended for development — slow/GPU/Simpleware/tutorial
tests are auto-skipped unless their opt-in flag is passed)
py -m pytest tests/ -v
- Baselines in `tests/baselines/` via Git LFS — run `git lfs pull` after cloning
- `tests/conftest.py`: session-scoped fixtures chaining download → convert → segment → register
- `tests/conftest.py`: session-scoped fixtures chaining
download → convert → segment → register
- `src/physiotwin4d/test_tools.py`: baseline comparison utilities (`TestTools`, etc.)
- Markers (all opt-in via `--run-<bucket>`): `slow`, `requires_gpu`,
`requires_simpleware`, `experiment`, `tutorial`. Data-dependent tests no
`requires_simpleware`, `tutorial`. Data-dependent tests no
longer use a marker — they pull data through fixtures and run by default.
- `experiments/` scripts are exploratory and are not run as tests; the
`tutorials/` scripts are the optional end-to-end suite
- **Avoid `pytest --run-slow` (or `--run-all`) unless the user explicitly
requests it.** Those runs take far too long for an interactive session.
Default to the fast suite and let the user invoke the slow buckets.
Expand Down
4 changes: 2 additions & 2 deletions docs/cli_scripts/create_statistical_model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ With Custom Parameters
--sample-meshes-dir ./meshes \
--reference-mesh average_mesh.vtk \
--output-dir ./pca_output \
--pca-components 20
--number-of-pca-components 20

Command-Line Arguments
======================
Expand All @@ -94,7 +94,7 @@ Required Arguments
Optional Arguments
------------------

``--pca-components N``
``--number-of-pca-components N``
Number of PCA components to retain (default: 7).

See :class:`physiotwin4d.WorkflowCreateStatisticalModel` for the full API and
Expand Down
8 changes: 4 additions & 4 deletions docs/cli_scripts/fit_statistical_model_to_patient.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Include statistical shape model fitting:
--patient-models lv.vtp rv.vtp myo.vtp \
--patient-image patient_ct.nii.gz \
--pca-json pca_model.json \
--pca-number-of-modes 10 \
--number-of-pca-components 10 \
--output-dir ./results

Command-Line Arguments
Expand Down Expand Up @@ -106,8 +106,8 @@ PCA Registration Options
``--pca-json PATH``
Path to PCA JSON file for shape-based registration (optional)

``--pca-number-of-modes NUM``
Number of PCA modes to use (default: 0, uses all if PCA enabled)
``--number-of-pca-components NUM``
Number of PCA components to use (default: 0, uses all if PCA enabled)

Registration Configuration
---------------------------
Expand Down Expand Up @@ -162,7 +162,7 @@ Example 2: PCA-Based Registration
--patient-models lv.vtp rv.vtp \
--patient-image patient_ct.nii.gz \
--pca-json pca_model.json \
--pca-number-of-modes 10 \
--number-of-pca-components 10 \
--output-dir results/pca

Output Files
Expand Down
14 changes: 13 additions & 1 deletion docs/cli_scripts/vtk_to_usd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Solid color:
--appearance solid \
--color 1 0 0

Anatomy material:
One anatomy material for every mesh:

.. code-block:: bash

Expand All @@ -45,6 +45,18 @@ Anatomy material:
--appearance anatomy \
--anatomy-type heart

A material per structure. Omitting ``--anatomy-type`` picks each object's
material from its name, and with ``--static-merge`` the objects are named after
the structures recorded in each file's ``SegmentationLabelNames`` field data —
as written by the image-to-VTK workflow:

.. code-block:: bash

physiotwin4d-convert-vtk-to-usd patient_highres_*.vtp \
--output heart_structures.usd \
--appearance anatomy \
--static-merge

Colormap from a VTK point data array:

.. code-block:: bash
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ Run Tests
# Run with coverage
pytest tests/ --cov=src/physiotwin4d --cov-report=html

# Default invocation auto-skips slow/GPU/Simpleware/experiment/tutorial
# Default invocation auto-skips slow/GPU/Simpleware/tutorial
pytest tests/

# Opt into specific buckets
Expand Down
4 changes: 2 additions & 2 deletions docs/developer/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ For most code changes, run:

py -m pytest tests/ -v

(Slow / GPU / Simpleware / PhysicsNeMo / experiment / tutorial tests are
(Slow / GPU / Simpleware / PhysicsNeMo / tutorial tests are
auto-skipped; opt in with ``--run-slow``, ``--run-gpu``, ``--run-simpleware``,
``--run-physicsnemo``, ``--run-experiments``, ``--run-tutorials``, or use
``--run-physicsnemo``, ``--run-tutorials``, or use
``--run-all`` to enable every bucket at once. Data-dependent tests download
their data through the session fixtures and run by default.)

Expand Down
25 changes: 21 additions & 4 deletions docs/developer/registration_images.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ Workflows that accept a ``registration_method`` (e.g.
:class:`WorkflowConvertImageToUSD`, :class:`RegisterTimeSeriesImages`) take
any :class:`RegisterImagesBase` instance, including a composite chain that
runs multiple backends in sequence. :class:`RegisterImagesChain` runs an
ordered list of registrars, feeding each stage's ``forward_transform`` as the
next stage's ``initial_forward_transform``. :class:`RegisterImagesGreedyICON`
is a named 2-stage convenience class for the common case of a fast Greedy
registration followed by ICON refinement:
ordered list of registrars, each stage refining the previous stage's
``forward_transform`` through ``register_from()`` (see `Seeding a registration`_
below). :class:`RegisterImagesGreedyICON` is a named 2-stage convenience class
for the common case of a fast Greedy registration followed by ICON refinement:

.. code-block:: python

Expand All @@ -76,6 +76,23 @@ registration followed by ICON refinement:
registrar.greedy.set_number_of_iterations([30, 15, 7, 3])
registrar.icon.set_number_of_iterations(20)

Seeding a registration
======================

To start from an alignment you already have, call ``register_from()`` instead of
``register()``:

.. code-block:: python

result = registrar.register_from(known_forward_transform, moving_image)

It warps the moving image, mask and labelmap onto the fixed grid by that
transform, registers the residual, and composes the two, so the returned
transforms still map between the *original* moving image and the fixed image.
Every backend goes through this one implementation -- no registrar accepts an
initial transform of its own, which is what keeps the pre-warp, the composition
and the inversion identical for Greedy, ICON and ANTs.

Development Notes
=================

Expand Down
3 changes: 1 addition & 2 deletions docs/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Run the fast test suite during development:

pytest tests/ -v

Slow, GPU, Simpleware, experiment, and tutorial tests are auto-skipped unless
Slow, GPU, Simpleware, and tutorial tests are auto-skipped unless
their opt-in flag is passed. Tests that depend on downloadable data fetch it
automatically via the session fixtures, so no marker filter is needed for them.

Expand All @@ -23,7 +23,6 @@ Each ``--run-<bucket>`` flag enables one marker family:
pytest tests/ -v --run-gpu # tests marked 'requires_gpu'
pytest tests/ -v --run-simpleware # tests marked 'requires_simpleware'
pytest tests/ -v --run-physicsnemo # tests marked 'requires_physicsnemo'
pytest tests/ -v --run-experiments # tests marked 'experiment'
pytest tests/ -v --run-tutorials # tests marked 'tutorial'

Flags compose. A typical local GPU profile is:
Expand Down
Loading
Loading