Skip to content

Claude/add tutorials docs aa mpp#47

Merged
aylward merged 6 commits into
Project-MONAI:mainfrom
aylward:claude/add-tutorials-docs-AaMPP
May 8, 2026
Merged

Claude/add tutorials docs aa mpp#47
aylward merged 6 commits into
Project-MONAI:mainfrom
aylward:claude/add-tutorials-docs-AaMPP

Conversation

@aylward
Copy link
Copy Markdown
Collaborator

@aylward aylward commented May 7, 2026

Summary by CodeRabbit

  • New Features

    • Six runnable tutorials with CLI entrypoints (CT→USD, CT→VTK, statistical modeling, VTK→USD, 4D CT recon); produce outputs and screenshots.
    • Test utilities: optional per-run results output directory and screenshot helpers for meshes and image slices.
  • Documentation

    • Installation/FAQ/quickstart standardized around CUDA 13; new tutorials landing and tutorial-focused getting-started guidance; refreshed docs theme and landing page.
  • Tests

    • End-to-end tutorial experiment tests with baseline screenshot comparisons and focused unit checks.
  • Chores

    • Packaging/source config simplified to prefer CUDA‑13 wheel sourcing.

claude and others added 2 commits April 23, 2026 15:07
- tutorials/: six end-to-end tutorial scripts (one per workflow class)
  covering HeartGatedCTToUSD, CTToVTK, FitStatisticalModelToPatient,
  CreateStatisticalModel, VTKToUSD, and ReconstructHighres4DCT.
  Each script includes a run_tutorial() function (used by tests), a
  standalone argparse CLI, and structured docstrings documenting
  Inputs/Outputs/Strengths/Weaknesses/Classes/CLI.
- tutorials/README.md: tutorial index, dataset requirements, run order,
  and experiment-test instructions.
- tutorials/__init__.py: makes tutorials/ a package so tests can import
  run_tutorial() with a clean `from tutorials.tutorial_XX import …`.
- test_tools.py: add save_screenshot_mesh() (PyVista off-screen PNG) and
  save_screenshot_image_slice() (matplotlib axial/coronal/sagittal PNG)
  to TestTools; both save under results_dir/class_name/.
- tests/test_tutorials.py: six @pytest.mark.experiment test classes wired
  to the corresponding run_tutorial() functions; compare screenshots
  against baselines via the existing ITK comparison infrastructure.
- pyproject.toml: add pythonpath = ["."] so pytest discovers tutorials/.
- README.md: add "Getting Started: Tutorials" section before Quick Start.
- docs/quickstart.rst: add Tutorials section with table and run examples.

https://claude.ai/code/session_01PmHfz2ntnAAFkyrGwSx7Ui
- Correct tutorial documentation so Slicer-Heart-CT is described as data to
  prepare first, not data auto-downloaded by the tutorial scripts.
- Fix Tutorial 1 to return the actual USD path under the output directory.
- Tighten tutorial typing for PyVista-loaded meshes and screenshot helpers.
- Make screenshot regression tolerance use the intended pixel-count criterion.
- Regenerate docs/API_MAP.md after adding public TestTools screenshot helpers.
- Author default USD mesh points, extent, and normals when writing time samples
  so single-frame USD meshes work with readers that query attributes without an
  explicit time code.
Copilot AI review requested due to automatic review settings May 7, 2026 14:26
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f8460016-4dc5-4f02-ad68-1b38ef3afb8a

📥 Commits

Reviewing files that changed from the base of the PR and between c06d04f and 535b23e.

📒 Files selected for processing (1)
  • docs/tutorials.rst
✅ Files skipped from review due to trivial changes (1)
  • docs/tutorials.rst

Walkthrough

This PR standardizes CUDA support to 13.0 across packaging, CI, and docs; adds six runnable tutorial scripts with run_tutorial() entrypoints and CLIs; extends TestTools with a results_output_dir override and mesh/image screenshot helpers; and updates docs layout, branding, and tutorial-focused content and CSS.

Changes

CUDA 13.0 Migration

Layer / File(s) Summary
Packaging / Source config
pyproject.toml
uv sources route torch/torchvision/torchaudio to the cu130 wheel index by default; cuda12-related indices removed; pytest pythonpath = ["."] added.
CI / Local dev docs
.github/workflows/README.md, README.md
CI and local install instructions updated from CUDA 12.6 → CUDA 13.0; uv install examples use uv pip install -e ".[cuda13]" (and .[test,cuda13] where shown).
User docs / Troubleshooting
docs/installation.rst, docs/faq.rst, docs/troubleshooting.rst
Installation and troubleshooting guidance consolidated to recommend the [cuda13] extra and cu130 wheel sourcing; prior cuda12 guidance removed.
Docs theme / logo
docs/conf.py
Added html_logo = "_static/nvidia-logo.svg" and adjusted html_theme_options header background value.
Docs content / README
README.md
README refined for CPU-only vs CUDA13 installs, clarified [cuda13] explanation, added Getting Started: Tutorials section and example commands.

Tutorial System, Tests & TestTools

Layer / File(s) Summary
Test utility API / data shape
src/physiomotion4d/test_tools.py
TestTools.__init__ gains optional results_output_dir parameter; results read/write honor the override while baselines remain in baselines_dir / class_name.
Test utility features
src/physiomotion4d/test_tools.py
Added save_screenshot_mesh(...) and save_screenshot_image_slice(...) to render and save PNG screenshots (off-screen PyVista/matplotlib with best-effort Xvfb handling).
Tutorial implementations
tutorials/tutorial_01_heart_gated_ct_to_usd.py, tutorials/tutorial_02_ct_to_vtk.py, tutorials/tutorial_03_fit_statistical_model_to_patient.py, tutorials/tutorial_04_create_statistical_model.py, tutorials/tutorial_05_vtk_to_usd.py, tutorials/tutorial_06_reconstruct_highres_4d_ct.py
Six new tutorial scripts each expose run_tutorial(data_dir, output_dir, ...) and CLIs; they run workflows, write artifacts (USD/VTK/PCA/volumes), and produce PNG screenshots via TestTools.
Tests / experiment coverage
tests/test_tutorials.py
Adds unit-style checks for tutorial selection/fallback behavior, a _compare_screenshots() helper, and six experiment-style test classes that invoke each tutorial and validate artifacts/screenshots; also tests TestTools results_output_dir override.
Workflow minor validation
src/physiomotion4d/workflow_convert_heart_gated_ct_to_usd.py
_load_time_series now selects reference_frame = int(self._num_time_points * 0.7) and validates that time-series images were loaded (raises on empty).
API map / docs / landing
docs/API_MAP.md, docs/tutorials.rst, docs/index.rst, tutorials/README.md, docs/_static/custom.css
API map updated for TestTools signature and tutorial entrypoints; new tutorials landing page and tutorial hub README added; extensive CSS for branded hero/cards and navigation added.
Minor USD comment
src/physiomotion4d/vtk_to_usd/usd_mesh_converter.py
Clarified comment about authoring a default Points value when time-varying samples exist (no behavior change).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant TutorialScript as Tutorial<br/>(e.g. tutorial_01)
    participant Workflow as Workflow<br/>(e.g. HeartGatedCT)
    participant TestTools
    participant FileSystem as Output<br/>Files

    User->>TutorialScript: run_tutorial(data_dir, output_dir)
    TutorialScript->>Workflow: instantiate + process()
    Workflow->>FileSystem: write USD / meshes / volumes
    TutorialScript->>TestTools: save_screenshot_mesh/image_slice()
    TestTools->>FileSystem: write PNG screenshots
    TutorialScript->>User: return dict with artifact paths
Loading
sequenceDiagram
    participant PytestRunner as Pytest<br/>Runner
    participant TestClass as TestTutorialNN<br/>(Experiment)
    participant TutorialScript as Tutorial<br/>Script
    participant TestTools
    participant Baseline as Baseline<br/>Images

    PytestRunner->>TestClass: test_run()
    TestClass->>TutorialScript: run_tutorial()
    TutorialScript->>TestTools: save_screenshot_mesh/image_slice()
    TestTools->>FileSystem: PNG screenshots
    TestClass->>TestTools: compare_result_to_baseline_image()
    TestTools->>Baseline: load baseline PNG
    TestTools->>TestTools: pixel comparison with tolerances
    TestTools->>TestClass: pass/fail result
    TestClass->>PytestRunner: assert pass
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐰 Six tutorials hop from data to view,
CUDA13 set, the docs made new,
TestTools snaps meshes, slices too,
Workflows run and baselines queue,
A floppy-eared cheer for code that grew!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Claude/add tutorials docs aa mpp' is unclear and contains non-descriptive abbreviations ('aa mpp') that do not convey meaningful information about the changeset. Revise the title to clearly describe the main changes, such as 'Add comprehensive tutorials documentation and refactor CUDA 13 configuration' or 'Add tutorial scripts and documentation with CUDA 13 standardization'.
Docstring Coverage ⚠️ Warning Docstring coverage is 74.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Signed-off-by: Stephen R. Aylward <stephen@aylward.org>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a tutorials suite (scripts + docs) and an experiment-style pytest harness to run them end-to-end with screenshot baselines, alongside a small USD time-sample robustness improvement.

Changes:

  • Added 6 runnable tutorial scripts under tutorials/ plus a tutorials index README.
  • Added tests/test_tutorials.py experiment tests and extended TestTools with screenshot helpers for meshes and ITK image slices.
  • Improved USD time-varying mesh authoring by also writing default (non-time-sampled) points/extents/normals.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
tutorials/tutorial_01_heart_gated_ct_to_usd.py New tutorial script for heart-gated CT → animated USD with screenshots.
tutorials/tutorial_02_ct_to_vtk.py New tutorial script for CT segmentation → VTK surfaces/meshes with screenshots.
tutorials/tutorial_03_fit_statistical_model_to_patient.py New tutorial script for fitting a statistical model to patient (demo) meshes + screenshots.
tutorials/tutorial_04_create_statistical_model.py New tutorial script for building a PCA shape model + screenshots.
tutorials/tutorial_05_vtk_to_usd.py New tutorial script for VTK → USD conversion + screenshot.
tutorials/tutorial_06_reconstruct_highres_4d_ct.py New tutorial script for high-res 4D CT reconstruction + screenshots.
tutorials/README.md Tutorial index, run instructions, and experiment-test instructions.
tests/test_tutorials.py New experiment tests that run tutorials and compare screenshots to baselines.
src/physiomotion4d/test_tools.py Added screenshot helpers for PyVista meshes and ITK image slices.
src/physiomotion4d/vtk_to_usd/usd_mesh_converter.py Author default values for time-varying points/extents/normals for better reader compatibility.
README.md Added “Getting Started: Tutorials” section.
docs/quickstart.rst Added tutorials section and updated quickstart text.
docs/API_MAP.md Updated API map entries for new tutorial/test helpers.
pyproject.toml Added pytest pythonpath to allow importing tutorials package in tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +151 to +154
# Reference frame: the workflow caches 3D frames in output_dir
ref_frames = sorted(output_dir.glob("slice_???.mha"))
if ref_frames:
ref_image = itk.imread(str(ref_frames[0]))
Comment on lines +167 to +180
# Segmentation overlay: look for cached labelmap
label_files = sorted(output_dir.glob("slice_???_labelmap*.mha"))
overlay = itk.imread(str(label_files[0])) if label_files else None
screenshots.append(
tt.save_screenshot_image_slice(
ref_image,
"segmentation_overlay.png",
axis=0,
slice_fraction=0.5,
colormap="gray",
vmin=-200,
vmax=600,
overlay_mask=overlay,
)
Comment on lines +25 to +29
- ``output_dir/<phase>_*.vtp`` - per-frame surface meshes (VTK PolyData)
- Screenshots (PNG) for documentation and regression testing:
- ``reference_frame_axial.png`` - axial slice of the reference CT frame
- ``segmentation_overlay.png`` - segmentation mask overlaid on reference
- ``contours_3d.png`` - 3-D isometric view of the reference-frame contours
Comment on lines +123 to +126
template_model = pv.read(str(template_file))
if not isinstance(template_model, pv.PolyData):
template_model = template_model.extract_surface()
template_model = cast(pv.PolyData, template_model)
Comment on lines +139 to +142
sample_model = pv.read(str(sample_file))
if not isinstance(sample_model, pv.PolyData):
sample_model = sample_model.extract_surface()
patient_models.append(cast(pv.PolyData, sample_model))
Comment on lines +185 to +187
before_path = tt._results_dir / "model_before_registration.png"
before_path.parent.mkdir(parents=True, exist_ok=True)
plotter.screenshot(str(before_path))
Comment on lines +125 to +133
# Discover phase images (MetaImage .mhd or .mha)
phase_files = sorted(case_dir.glob("*.mhd")) + sorted(case_dir.glob("*.mha"))
if not phase_files:
raise FileNotFoundError(
f"No .mhd / .mha files found under {case_dir}.\n"
"See data/README.md for manual download instructions."
)

phase_files = phase_files[:max_frames]
Comment on lines +426 to +432
import matplotlib.pyplot as plt
import numpy as np

arr = np.asarray(itk.array_view_from_image(image), dtype=np.float64)
idx = int(arr.shape[axis] * slice_fraction)
idx = max(0, min(idx, arr.shape[axis] - 1))

plotter.camera_position = "iso"

png_name = f"pca_mode_{mode_idx + 1:02d}.png"
png_path = tt._results_dir / png_name
Comment on lines +133 to +136
phase_files = phase_files[:max_frames]
time_series = [itk.imread(str(f)) for f in phase_files]
fixed_image = time_series[0] # use first phase as high-res reference

@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 22.09%. Comparing base (b1af1c1) to head (535b23e).

Files with missing lines Patch % Lines
...motion4d/workflow_convert_heart_gated_ct_to_usd.py 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #47      +/-   ##
==========================================
+ Coverage   21.72%   22.09%   +0.36%     
==========================================
  Files          46       46              
  Lines        6268     6272       +4     
==========================================
+ Hits         1362     1386      +24     
+ Misses       4906     4886      -20     
Flag Coverage Δ
integration-tests 22.09% <0.00%> (?)
unittests 21.71% <0.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Make the Sphinx index page the NVIDIA-styled tutorial landing page
- Add tutorial cards, documentation topic cards, and NVIDIA logo styling
- Configure uv-managed PyTorch packages to resolve from the cu130 index by default
- Remove cuda12/cu128 dependency configuration and update install docs accordingly
- Align GitHub workflow docs with CUDA 13.0 setup and cuda13 test installs
- Verify default uv torch resolves as cu130 and Sphinx docs build succeeds
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (3)
src/physiomotion4d/test_tools.py (1)

444-445: 💤 Low value

Redundant import numpy as np inside method.

numpy is already imported at module level (Line 17). The local import is a no-op but adds noise.

♻️ Proposed fix
-        import matplotlib.pyplot as plt
-        import numpy as np
+        import matplotlib.pyplot as plt
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/physiomotion4d/test_tools.py` around lines 444 - 445, Remove the
redundant local import "import numpy as np" inside the method where "import
matplotlib.pyplot as plt" is present; numpy is already imported at module scope,
so delete the local "import numpy as np" statement (leave the plt import if it's
only used locally) to avoid no-op duplicate imports and reduce noise.
docs/index.rst (1)

105-248: ⚡ Quick win

Duplicate tutorial content across index.rst and tutorials.rst creates a maintenance burden

Lines 105–248 inline the complete tutorial documentation (Recommended Run Order + all six Tutorial sections + Dataset Notes) that is also fully present in docs/tutorials.rst. Any future change to commands, dataset paths, or outputs must be applied in both files, and they will inevitably drift.

Consider replacing the inlined content with a Sphinx .. include:: directive or replacing the in-page card href anchors with cross-document links (:doc:tutorials`` + section anchors), keeping the full content only in tutorials.rst.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/index.rst` around lines 105 - 248, Index.rst duplicates the entire
tutorial content (the "Recommended Run Order" and "Tutorial 1" through "Tutorial
6" sections and "Dataset Notes") that already lives in tutorials.rst, causing
maintenance drift; remove the inlined blocks in index.rst (the sections headed
"Recommended Run Order", "Tutorial 1: Heart-Gated CT to Animated USD" …
"Tutorial 6: Reconstruct High-Resolution 4D CT", and "Dataset Notes") and
replace them with a single Sphinx-level reference to the canonical tutorials.rst
content — either use a Sphinx include of the tutorials document or replace the
inline cards/anchors with cross-document links to the tutorials document and its
section anchors (so updates live only in tutorials.rst).
tutorials/tutorial_03_fit_statistical_model_to_patient.py (1)

169-174: 💤 Low value

Redundant _extract_surface call on an already-converted mesh.

template_model was already extracted to a pv.PolyData on Line 130, so the _extract_surface wrapping on Line 169 is a no-op (the function returns a pv.PolyData unchanged).

♻️ Proposed fix
-    plotter.add_mesh(
-        _extract_surface(template_model),
-        color="dodgerblue",
-        opacity=0.6,
-        label="Template",
-    )
+    plotter.add_mesh(
+        template_model,
+        color="dodgerblue",
+        opacity=0.6,
+        label="Template",
+    )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tutorials/tutorial_03_fit_statistical_model_to_patient.py` around lines 169 -
174, The call to _extract_surface is redundant because template_model is already
a pv.PolyData; update the plotter.add_mesh invocation to pass template_model
directly instead of wrapping it in _extract_surface. Locate the plotter.add_mesh
call that currently uses _extract_surface(template_model) and replace the
argument with template_model (keeping color, opacity, and label unchanged) so
you avoid the no-op wrapper around the already-converted mesh.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/README.md:
- Around line 110-114: Add a note to the "Install CUDA toolkit 13.0" section
warning that CUDA 13.0 requires Ubuntu 22.04+ so installs of the
wget/dpkg/cuda-keyring and apt-get install cuda-toolkit-13-0 commands will fail
on Ubuntu 20.04; update the README near the "Install CUDA toolkit 13.0" heading
and mention self-hosted runners should be upgraded to Ubuntu 22.04 LTS or later
(reference the "cuda-keyring_1.1-1_all.deb" and "cuda-toolkit-13-0" package
names in the note).
- Around line 110-114: The apt install command uses the wrong package name;
change the APT package in the workflow from "cuda-toolkit-13-0" to the correct
meta-package "cuda-toolkit-13" so the CUDA toolkit installs successfully (update
the sudo apt-get install line that currently references cuda-toolkit-13-0).

In `@docs/_static/custom.css`:
- Around line 303-310: Add a distinct keyboard focus indicator for the card
components so focus is visually different from hover: update the .pm4d-card and
.pm4d-topic-card selectors to keep the existing hover styles for :hover but add
a separate :focus-visible rule that adds a clear, high-contrast outline or an
adjusted box-shadow (and does not rely solely on the hover transform), so
keyboard users can distinguish focus from hover and meet WCAG 2.4.11; target
.pm4d-card:focus-visible and .pm4d-topic-card:focus-visible (instead of :focus)
and ensure the indicator uses accessible color/contrast and does not get hidden
by outline: none elsewhere.

In `@src/physiomotion4d/test_tools.py`:
- Around line 392-404: The off-screen pv.Plotter created in this function can
leak resources if screenshot or other calls raise; wrap the Plotter usage in a
try/finally so plotter.close() is always called (e.g., create plotter =
pv.Plotter(...); try: add_mesh/ set camera/ screenshot; finally:
plotter.close()). Also ensure that if you successfully started pv.start_xvfb(),
you call pv.stop_xvfb() in a finally block (or after plotter.close()) to clean
up Xvfb; reference the pv.start_xvfb(), pv.stop_xvfb() calls and the plotter
variable/plotter.close() to locate where to add the try/finally.
- Around line 455-473: The plotting code creates fig and ax then calls ax.imshow
and fig.savefig but never guarantees plt.close(fig) on exceptions; wrap the
plotting and save calls in a try/finally (or use try/except/finally) around the
block that uses fig/ax (the ax.imshow(...) and fig.savefig(...) calls) and move
plt.close(fig) into the finally so the figure is always closed even if ax.imshow
or fig.savefig raises; reference the local symbols fig, ax, ax.imshow,
fig.savefig, and plt.close to locate and update the code.

In `@src/physiomotion4d/workflow_convert_heart_gated_ct_to_usd.py`:
- Around line 181-183: The code currently indexes self._time_series_images using
reference_frame computed from self._num_time_points without guarding against an
empty series; add a guard in the conversion routine (around the reference_frame
/ self._fixed_image assignment) that checks self._num_time_points > 0 and
self._time_series_images is non-empty, and if not either raise a clear
ValueError/RuntimeError mentioning no time-series images were produced or set
self._fixed_image to None and handle that downstream; update any callers of the
conversion method to expect and handle the new error/None return accordingly so
IndexError is avoided.

In `@tests/test_tutorials.py`:
- Around line 59-72: The test helper _compare_screenshots currently silently
succeeds when the screenshots list is empty; add an explicit guard at the start
of _compare_screenshots to fail the test when screenshots is empty (e.g., if not
screenshots: pytest.fail("No screenshots produced by run_tutorial")) so missing
outputs cause a test failure; reference the screenshots parameter and keep the
existing per-image checks/loop intact so existing comparisons still run when
screenshots are present.

In `@tutorials/README.md`:
- Around line 54-57: The "Tutorials 3 and 4" line is misleading because Tutorial
3 (WorkflowFitStatisticalModelToPatient) requires the model produced by Tutorial
4 (WorkflowCreateStatisticalModel); update the README to explicitly state that
Tutorial 4 must be run before Tutorial 3 (either swap their mention or change
the text to "Run Tutorial 4 (WorkflowCreateStatisticalModel) before Tutorial 3
(WorkflowFitStatisticalModelToPatient)"), so readers know the required execution
order.

In `@tutorials/tutorial_04_create_statistical_model.py`:
- Around line 193-199: pv.start_xvfb() is being called inside the PCA loop (the
for mode_idx in range(min(2, pca_components)) block) which can start multiple
Xvfb instances; move the pv.start_xvfb() call (with its existing try/except
guard) to run once before the loop (for example immediately before entering the
TestTools block or before the for loop) so Xvfb is started only once; update the
code around pv.start_xvfb() and the loop to ensure the virtual framebuffer is
started once and still protected by the same exception handling.
- Around line 129-137: The fallback glob currently includes the reference mesh
pca_mean.vtu (via kcl_dir.glob("*.vtu")), biasing the PCA; update the sample
selection after both globs so sample_files = [f for f in sample_files if f.name
!= "pca_mean.vtu"] (or filter out kcl_dir / "pca_mean.vtu") to exclude the
reference mesh from training, and ensure the length check (len(sample_files) <
3) counts only non-reference files and raises the FileNotFoundError if there are
fewer than 3 valid samples; adjust the error message to mention the directory
actually searched (sample_dir/kcl_dir) if desired.

In `@tutorials/tutorial_05_vtk_to_usd.py`:
- Around line 103-116: The candidate lookup for the Tutorial 2 VTK file is using
Path("output") which is CWD-relative and ignores the configured data_dir; update
the auto-discovery so candidate is resolved relative to the project/data root
(use data_dir as the base) instead of the current working directory — e.g.,
compute the project root from data_dir (or use an existing project_root
variable) and build candidate from that root (referencing the variables
vtk_file, candidate and data_dir in the existing block) so the script reliably
finds output/tutorial_02/patient_surfaces.vtp regardless of CWD or configured
output locations.

In `@tutorials/tutorial_06_reconstruct_highres_4d_ct.py`:
- Around line 129-135: The current concatenation of sorted lists (phase_files =
sorted(case_dir.glob("*.mhd")) + sorted(case_dir.glob("*.mha")) and similarly
for dirlab_dir) forces all .mhd before .mha and breaks temporal order; instead,
collect both extensions into one list then sort the combined list so filenames
are ordered temporally (e.g., merge results from case_dir.glob("*.mhd") and
case_dir.glob("*.mha") into a single list and call sorted(...) once, or sort by
extracted frame index from filenames), and apply the same fix for the fallback
that uses phase_pattern and dirlab_dir so phase_files holds a correctly ordered
sequence.

---

Nitpick comments:
In `@docs/index.rst`:
- Around line 105-248: Index.rst duplicates the entire tutorial content (the
"Recommended Run Order" and "Tutorial 1" through "Tutorial 6" sections and
"Dataset Notes") that already lives in tutorials.rst, causing maintenance drift;
remove the inlined blocks in index.rst (the sections headed "Recommended Run
Order", "Tutorial 1: Heart-Gated CT to Animated USD" … "Tutorial 6: Reconstruct
High-Resolution 4D CT", and "Dataset Notes") and replace them with a single
Sphinx-level reference to the canonical tutorials.rst content — either use a
Sphinx include of the tutorials document or replace the inline cards/anchors
with cross-document links to the tutorials document and its section anchors (so
updates live only in tutorials.rst).

In `@src/physiomotion4d/test_tools.py`:
- Around line 444-445: Remove the redundant local import "import numpy as np"
inside the method where "import matplotlib.pyplot as plt" is present; numpy is
already imported at module scope, so delete the local "import numpy as np"
statement (leave the plt import if it's only used locally) to avoid no-op
duplicate imports and reduce noise.

In `@tutorials/tutorial_03_fit_statistical_model_to_patient.py`:
- Around line 169-174: The call to _extract_surface is redundant because
template_model is already a pv.PolyData; update the plotter.add_mesh invocation
to pass template_model directly instead of wrapping it in _extract_surface.
Locate the plotter.add_mesh call that currently uses
_extract_surface(template_model) and replace the argument with template_model
(keeping color, opacity, and label unchanged) so you avoid the no-op wrapper
around the already-converted mesh.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2b59bb8e-1847-443d-89ed-67d3aa768356

📥 Commits

Reviewing files that changed from the base of the PR and between b1af1c1 and cbcb858.

⛔ Files ignored due to path filters (1)
  • docs/_static/nvidia-logo.svg is excluded by !**/*.svg
📒 Files selected for processing (24)
  • .github/workflows/README.md
  • README.md
  • docs/API_MAP.md
  • docs/_static/custom.css
  • docs/conf.py
  • docs/faq.rst
  • docs/index.rst
  • docs/installation.rst
  • docs/quickstart.rst
  • docs/troubleshooting.rst
  • docs/tutorials.rst
  • pyproject.toml
  • src/physiomotion4d/test_tools.py
  • src/physiomotion4d/vtk_to_usd/usd_mesh_converter.py
  • src/physiomotion4d/workflow_convert_heart_gated_ct_to_usd.py
  • tests/test_tutorials.py
  • tutorials/README.md
  • tutorials/__init__.py
  • tutorials/tutorial_01_heart_gated_ct_to_usd.py
  • tutorials/tutorial_02_ct_to_vtk.py
  • tutorials/tutorial_03_fit_statistical_model_to_patient.py
  • tutorials/tutorial_04_create_statistical_model.py
  • tutorials/tutorial_05_vtk_to_usd.py
  • tutorials/tutorial_06_reconstruct_highres_4d_ct.py

Comment thread .github/workflows/README.md Outdated
Comment thread docs/_static/custom.css Outdated
Comment thread src/physiomotion4d/test_tools.py
Comment thread src/physiomotion4d/test_tools.py Outdated
Comment thread src/physiomotion4d/workflow_convert_heart_gated_ct_to_usd.py
Comment thread tutorials/README.md
Comment on lines +54 to +57
1. **Tutorial 1** and **Tutorial 2** use Slicer-Heart-CT - prepare it per `data/README.md`, then start here.
2. **Tutorial 5** uses the VTK surfaces produced by Tutorial 2 - run Tutorial 2 first.
3. **Tutorials 3 and 4** require the KCL-Heart-Model - download it per `data/README.md`.
4. **Tutorial 6** requires DirLab-4DCT - download it per `data/README.md`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Tutorial 3 depends on Tutorial 4 — recommended order is misleading.

Tutorial 3 (WorkflowFitStatisticalModelToPatient) requires a statistical model as input, which is produced by Tutorial 4 (WorkflowCreateStatisticalModel). The recommended order section groups them as "Tutorials 3 and 4" without clarifying that Tutorial 4 must run first.

📝 Suggested fix
-3. **Tutorials 3 and 4** require the KCL-Heart-Model - download it per `data/README.md`.
+3. **Tutorial 4** (`WorkflowCreateStatisticalModel`) requires the KCL-Heart-Model - download it per `data/README.md`, then run Tutorial 4 before Tutorial 3.
+4. **Tutorial 3** (`WorkflowFitStatisticalModelToPatient`) requires the output of Tutorial 4.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tutorials/README.md` around lines 54 - 57, The "Tutorials 3 and 4" line is
misleading because Tutorial 3 (WorkflowFitStatisticalModelToPatient) requires
the model produced by Tutorial 4 (WorkflowCreateStatisticalModel); update the
README to explicitly state that Tutorial 4 must be run before Tutorial 3 (either
swap their mention or change the text to "Run Tutorial 4
(WorkflowCreateStatisticalModel) before Tutorial 3
(WorkflowFitStatisticalModelToPatient)"), so readers know the required execution
order.

Comment thread tutorials/tutorial_04_create_statistical_model.py
Comment thread tutorials/tutorial_04_create_statistical_model.py Outdated
Comment thread tutorials/tutorial_05_vtk_to_usd.py
Comment thread tutorials/tutorial_06_reconstruct_highres_4d_ct.py
- Make the docs index the NVIDIA-styled tutorial landing page
- Add tutorial cards, doc topic cards, NVIDIA logo, and accessible card focus states
- Move detailed tutorial content back to tutorials.rst and link index cards there
- Configure uv-managed PyTorch packages to use the cu130 index by default
- Remove cuda12/cu128 install paths and update README/docs/workflow guidance
- Align GitHub workflow runner docs with CUDA 13.0 and cuda-toolkit-13
- Harden tutorial screenshot handling, sample discovery, and empty output checks
- Guard empty heart-gated CT time-series conversion before reference-frame indexing
- Validate with Ruff, fast pytest, and Sphinx HTML build
Copilot AI review requested due to automatic review settings May 7, 2026 22:36
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 25 changed files in this pull request and generated 2 comments.

Comment thread docs/tutorials.rst Outdated

python tutorials/tutorial_05_vtk_to_usd.py \
--data-dir ./data --output-dir ./output/tutorial_05 \
--input output/tutorial_02/patient_surfaces.vtp
Comment on lines 34 to 39
class TestTools(PhysioMotion4DBase):
"""
Utilities for pytest image comparison: baseline directory, results directory,
Utilities for pytest image comparison: baseline directory, result directory,
and comparison with configurable tolerances. Inherits from PhysioMotion4DBase
for logging. All image I/O uses ITK .mha with compression.
for logging. All image I/O uses ITK with compression where supported.
"""
@aylward aylward merged commit f66b3d4 into Project-MONAI:main May 8, 2026
13 of 14 checks passed
@aylward aylward deleted the claude/add-tutorials-docs-AaMPP branch May 8, 2026 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants