Skip to content

ENH: Refactored VTK-to-USD class, workflow, and tutorial.#85

Merged
aylward merged 3 commits into
Project-MONAI:mainfrom
aylward:VTK_To_USD
Jul 10, 2026
Merged

ENH: Refactored VTK-to-USD class, workflow, and tutorial.#85
aylward merged 3 commits into
Project-MONAI:mainfrom
aylward:VTK_To_USD

Conversation

@aylward

@aylward aylward commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Decouple VTK-to-USD workflow from file I/O; rename times_per_second to frames_per_second

  • WorkflowConvertVTKToUSD now takes in-memory PyVista/VTK meshes (input_meshes) with explicit usd_project_name/output_directory and optional time_codes/static_merge, replacing file-path input and regex-based time-series filename discovery.
  • Renamed times_per_second -> frames_per_second across ConvertVTKToUSD, ConversionSettings, CLI --fps, and workflows for clarity.
  • Renamed run() -> process() to match WorkflowConvertImageToUSD's convention.
  • download_data CLI no longer defaults to Slicer-Heart-CT; an explicit dataset argument is now required (prints help otherwise).
  • Updated docs, tutorials, experiments, and tests accordingly.

Summary by CodeRabbit

  • New Features
    • VTK-to-USD conversion now works with in-memory PyVista/VTK meshes.
    • Added static-merge to create a single static USD scene from multiple inputs.
    • Improved dataset download with progress messages.
  • Updates
    • Animation timing is now consistently configured with frames per second (fps) across CLI, workflows, and examples.
    • Updated time-series behavior: multiple inputs are treated as an ordered animation unless static-merge is enabled.
  • Bug Fixes
    • Dataset download CLI now prints help and exits when required arguments are missing.
    • Strengthened validation for time-code length and ordering.

Decouple VTK-to-USD workflow from file I/O; rename times_per_second to frames_per_second

- WorkflowConvertVTKToUSD now takes in-memory PyVista/VTK meshes
  (input_meshes) with explicit usd_project_name/output_directory and
  optional time_codes/static_merge, replacing file-path input and
  regex-based time-series filename discovery.
- Renamed times_per_second -> frames_per_second across ConvertVTKToUSD,
  ConversionSettings, CLI --fps, and workflows for clarity.
- Renamed run() -> process() to match WorkflowConvertImageToUSD's
  convention.
- download_data CLI no longer defaults to Slicer-Heart-CT; an explicit
  dataset argument is now required (prints help otherwise).
- Updated docs, tutorials, experiments, and tests accordingly.
Copilot AI review requested due to automatic review settings July 10, 2026 13:33
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

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: 5dc192f6-1023-41ce-ac0c-c1e433baa062

📥 Commits

Reviewing files that changed from the base of the PR and between 7894615 and f24f220.

📒 Files selected for processing (6)
  • docs/architecture.rst
  • docs/tutorials.rst
  • src/physiotwin4d/cli/convert_vtk_to_usd.py
  • src/physiotwin4d/convert_vtk_to_usd.py
  • src/physiotwin4d/data_download_tools.py
  • src/physiotwin4d/workflow_convert_vtk_to_usd.py
✅ Files skipped from review due to trivial changes (2)
  • docs/architecture.rst
  • src/physiotwin4d/data_download_tools.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • docs/tutorials.rst
  • src/physiotwin4d/workflow_convert_vtk_to_usd.py
  • src/physiotwin4d/convert_vtk_to_usd.py

Walkthrough

The PR migrates VTK-to-USD workflows from file-based inputs to in-memory PyVista/VTK meshes, renames animation-rate parameters, adds static-merge handling, changes dataset CLI behavior, and updates documentation, experiments, tutorials, and tests.

Changes

VTK-to-USD migration

Layer / File(s) Summary
Converter contracts and time-code validation
src/physiotwin4d/convert_vtk_to_usd.py, src/physiotwin4d/vtk_to_usd/data_structures.py
Renames times_per_second to frames_per_second, centralizes time_codes validation, and updates USD time sampling.
Mesh-based workflow processing
src/physiotwin4d/workflow_convert_vtk_to_usd.py, experiments/Convert_VTK_To_USD/*, tutorials/tutorial_05_vtk_to_usd.py, docs/api/workflows.rst, docs/architecture.rst, docs/tutorials.rst, docs/cli_scripts/vtk_to_usd.rst, docs/cli_scripts/byod_tutorials.rst
Changes the workflow to accept in-memory meshes, use process(), derive output paths, convert meshes, and apply appearance settings.
VTK CLI and animation-rate integration
src/physiotwin4d/cli/convert_vtk_to_usd.py, src/physiotwin4d/cli/convert_image_to_usd.py, src/physiotwin4d/workflow_convert_image_to_usd.py, experiments/*, tests/*
Loads meshes with PyVista, adds --static-merge, and propagates the frames_per_second parameter through CLIs, workflows, examples, and tests.
Dataset CLI behavior and progress output
src/physiotwin4d/cli/download_data.py, src/physiotwin4d/data_download_tools.py, tests/test_download_data_cli.py, docs/cli_scripts/download_data.rst
Requires an explicit dataset, prints help when omitted, and reports completed downloads.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant PyVista
  participant WorkflowConvertVTKToUSD
  participant ConvertVTKToUSD
  participant USDStage
  CLI->>PyVista: read VTK input meshes
  PyVista->>WorkflowConvertVTKToUSD: provide input_meshes
  WorkflowConvertVTKToUSD->>ConvertVTKToUSD: convert input_polydata
  ConvertVTKToUSD->>USDStage: create USD scene and time samples
  WorkflowConvertVTKToUSD->>USDStage: apply appearance
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main refactor and names the key VTK-to-USD areas changed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ 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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Refactors the VTK-to-USD conversion workflow to accept in-memory meshes (decoupling conversion from file I/O), aligns naming with other workflows (run()process()), and renames times_per_secondframes_per_second across the library/CLIs/docs. It also changes download_data so an explicit dataset argument is required.

Changes:

  • WorkflowConvertVTKToUSD now consumes input_meshes and writes {usd_project_name}.usd into output_directory, with optional static_merge/time_codes.
  • Renames times_per_secondframes_per_second across converter settings, workflows, CLIs, tests, docs, and experiments.
  • download_data CLI no longer has an implicit default dataset; calling it with no args prints help and exits non-zero.

Reviewed changes

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

Show a summary per file
File Description
tutorials/tutorial_05_vtk_to_usd.py Updates tutorial to read a mesh via PyVista and call workflow.process().
tests/test_vtk_to_usd_library.py Updates converter callsite to use frames_per_second.
tests/test_download_data_cli.py Updates expectations for download_data when no args are provided.
tests/test_cli_smoke.py Updates CLI smoke test expectations for frames_per_second.
src/physiotwin4d/workflow_convert_vtk_to_usd.py Refactors workflow to accept in-memory meshes, adds static_merge/time_codes, renames to process().
src/physiotwin4d/workflow_convert_image_to_usd.py Renames workflow parameter to frames_per_second and forwards it.
src/physiotwin4d/vtk_to_usd/data_structures.py Renames ConversionSettings.times_per_second to frames_per_second.
src/physiotwin4d/data_download_tools.py Adds download progress/status print()s during dataset acquisition.
src/physiotwin4d/convert_vtk_to_usd.py Adds static_merge/time_codes to constructor and renames FPS parameter to frames_per_second.
src/physiotwin4d/cli/download_data.py Requires explicit dataset argument; prints help and exits when omitted.
src/physiotwin4d/cli/convert_vtk_to_usd.py Updates CLI to load meshes in-memory and call workflow.process(), adds --static-merge, renames --fps plumbing.
src/physiotwin4d/cli/convert_image_to_usd.py Renames --fps plumbing to frames_per_second.
experiments/Heart-GatedCT_To_USD/3-transform_dynamic_and_static_contours.py Renames converter argument to frames_per_second.
experiments/Convert_VTK_To_USD/convert_chop_tpv25_valve_to_usd.py Renames converter argument to frames_per_second.
experiments/Convert_VTK_To_USD/convert_chop_heart_vtk_to_usd.py Updates workflow usage to in-memory meshes and process().
experiments/Convert_VTK_To_USD/convert_chop_alterra_valve_to_usd.py Renames converter argument to frames_per_second.
docs/tutorials.rst Updates tutorial docs for in-memory meshes + process().
docs/developer/usd_generation.rst Renames times_per_secondframes_per_second in examples.
docs/cli_scripts/vtk_to_usd.rst Documents ordered time series vs --static-merge; clarifies Python API inputs are meshes.
docs/cli_scripts/download_data.rst Updates docs to reflect required dataset argument.
docs/cli_scripts/byod_tutorials.rst Updates BYOD docs for new workflow/converter parameters and usage.
docs/architecture.rst Updates workflow description to “in-memory meshes”.
docs/api/workflows.rst Updates workflow API example to in-memory meshes + process().

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

Comment thread src/physiotwin4d/workflow_convert_vtk_to_usd.py Outdated
Comment thread src/physiotwin4d/convert_vtk_to_usd.py Outdated
Comment thread src/physiotwin4d/cli/convert_vtk_to_usd.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/cli_scripts/byod_tutorials.rst (1)

46-53: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the physiotwin4d-download-data example to pass a dataset name. docs/cli_scripts/byod_tutorials.rst:50-57 The bare command only prints help and exits; use physiotwin4d-download-data Slicer-Heart-CT so the surrounding text matches the actual behavior.

🤖 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/cli_scripts/byod_tutorials.rst` around lines 46 - 53, Update the
`physiotwin4d-download-data` command example in the BYOD tutorial to pass the
required dataset argument `Slicer-Heart-CT`, keeping the surrounding description
consistent with the command’s actual behavior.
🧹 Nitpick comments (2)
src/physiotwin4d/data_download_tools.py (1)

75-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use logging instead of print for download progress in a library module.

DataDownloadTools is a utility class in a library module, not a standalone script. As per coding guidelines, Python code should use the logging module instead of print statements. Consider using logging.info(...) for these progress messages so callers can control log levels and output destinations.

♻️ Suggested refactor: replace print with logging
+import logging
+
+_logger = logging.getLogger(__name__)
+
 # ... in each method:
-            print(f"Downloaded {DataDownloadTools.SLICER_HEART_CT_FILENAME}")
+            _logger.info("Downloaded %s", DataDownloadTools.SLICER_HEART_CT_FILENAME)
-            print(
-                f"Downloaded {index:02d}.vtk ({index}/{DataDownloadTools.KCL_HEART_MODEL_MESH_COUNT})"
-            )
+            _logger.info(
+                "Downloaded %02d.vtk (%d/%d)",
+                index,
+                index,
+                DataDownloadTools.KCL_HEART_MODEL_MESH_COUNT,
+            )
-            print("Downloaded average_mesh.vtk")
+            _logger.info("Downloaded average_mesh.vtk")
-            print(f"Downloaded {subdir_name} ({asset_name})")
+            _logger.info("Downloaded %s (%s)", subdir_name, asset_name)

Also applies to: 126-128, 137-137, 215-215

🤖 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/physiotwin4d/data_download_tools.py` at line 75, Replace the
download-progress print statements in DataDownloadTools with logging.info calls,
including the occurrences around SLICER_HEART_CT_FILENAME and the other
referenced download messages; import and use Python’s logging module so callers
can configure output and log levels.

Source: Coding guidelines

src/physiotwin4d/workflow_convert_vtk_to_usd.py (1)

31-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the missing constructor return annotation.

__init__ needs -> None for strict mypy compliance.

Proposed fix
-    ):
+    ) -> None:

As per coding guidelines, “provide full type hints (mypy strict / no untyped defs).”

🤖 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/physiotwin4d/workflow_convert_vtk_to_usd.py` around lines 31 - 50, Add
the explicit -> None return annotation to the __init__ constructor shown in the
diff, preserving all existing parameters and behavior to satisfy strict mypy
typing.

Source: Coding guidelines

🤖 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 `@docs/architecture.rst`:
- Around line 87-89: Update the workflow wrapper description in the architecture
documentation to state that it converts in-memory PyVista/VTK meshes to both
static and animated USD scenes, while retaining the distinction from the
advanced primitives in the physiotwin4d.vtk_to_usd package.

In `@src/physiotwin4d/cli/convert_vtk_to_usd.py`:
- Around line 200-210: Validate args.output_usd before constructing
WorkflowConvertVTKToUSD, requiring its suffix to be exactly “.usd” and rejecting
unsupported extensions with a clear CLI error; keep the existing
Path.stem/output-directory behavior aligned with this constraint.
- Around line 202-205: The exception handler surrounding `pv.read()` in the CLI
conversion flow should catch the file-loading errors it can raise, including
`OSError`, `FileNotFoundError`, and `TypeError`, in addition to `ValueError.
Update the `try` block around `input_meshes` construction and preserve the
existing CLI error handling so malformed or unreadable VTK inputs do not produce
an uncaught traceback.

In `@src/physiotwin4d/data_download_tools.py`:
- Around line 126-128: In the download progress output within DataDownloadTools,
reformat the overlong f-string to comply with the 88-character limit, for
example by splitting the expression across lines while preserving the existing
message.

In `@src/physiotwin4d/workflow_convert_vtk_to_usd.py`:
- Around line 117-122: The time code selection in the workflow conversion logic
incorrectly treats an explicit empty list as missing. In the time_codes
initialization within ConvertVTKToUSD, replace the truthiness fallback with an
explicit None check so generated codes are used only when time_codes is None,
while [] is preserved for length validation.

---

Outside diff comments:
In `@docs/cli_scripts/byod_tutorials.rst`:
- Around line 46-53: Update the `physiotwin4d-download-data` command example in
the BYOD tutorial to pass the required dataset argument `Slicer-Heart-CT`,
keeping the surrounding description consistent with the command’s actual
behavior.

---

Nitpick comments:
In `@src/physiotwin4d/data_download_tools.py`:
- Line 75: Replace the download-progress print statements in DataDownloadTools
with logging.info calls, including the occurrences around
SLICER_HEART_CT_FILENAME and the other referenced download messages; import and
use Python’s logging module so callers can configure output and log levels.

In `@src/physiotwin4d/workflow_convert_vtk_to_usd.py`:
- Around line 31-50: Add the explicit -> None return annotation to the __init__
constructor shown in the diff, preserving all existing parameters and behavior
to satisfy strict mypy typing.
🪄 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: 54899e8b-b282-4a73-b5b1-b8fd003f633b

📥 Commits

Reviewing files that changed from the base of the PR and between 974b8f1 and 7894615.

📒 Files selected for processing (23)
  • docs/api/workflows.rst
  • docs/architecture.rst
  • docs/cli_scripts/byod_tutorials.rst
  • docs/cli_scripts/download_data.rst
  • docs/cli_scripts/vtk_to_usd.rst
  • docs/developer/usd_generation.rst
  • docs/tutorials.rst
  • experiments/Convert_VTK_To_USD/convert_chop_alterra_valve_to_usd.py
  • experiments/Convert_VTK_To_USD/convert_chop_heart_vtk_to_usd.py
  • experiments/Convert_VTK_To_USD/convert_chop_tpv25_valve_to_usd.py
  • experiments/Heart-GatedCT_To_USD/3-transform_dynamic_and_static_contours.py
  • src/physiotwin4d/cli/convert_image_to_usd.py
  • src/physiotwin4d/cli/convert_vtk_to_usd.py
  • src/physiotwin4d/cli/download_data.py
  • src/physiotwin4d/convert_vtk_to_usd.py
  • src/physiotwin4d/data_download_tools.py
  • src/physiotwin4d/vtk_to_usd/data_structures.py
  • src/physiotwin4d/workflow_convert_image_to_usd.py
  • src/physiotwin4d/workflow_convert_vtk_to_usd.py
  • tests/test_cli_smoke.py
  • tests/test_download_data_cli.py
  • tests/test_vtk_to_usd_library.py
  • tutorials/tutorial_05_vtk_to_usd.py

Comment thread docs/architecture.rst Outdated
Comment thread src/physiotwin4d/cli/convert_vtk_to_usd.py
Comment thread src/physiotwin4d/cli/convert_vtk_to_usd.py
Comment thread src/physiotwin4d/data_download_tools.py Outdated
Comment thread src/physiotwin4d/workflow_convert_vtk_to_usd.py Outdated
Copilot AI review requested due to automatic review settings July 10, 2026 14:14

Copilot AI left a comment

Copy link
Copy Markdown

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 23 changed files in this pull request and generated 3 comments.

Comment thread docs/tutorials.rst
Comment thread src/physiotwin4d/cli/convert_vtk_to_usd.py
Comment thread src/physiotwin4d/workflow_convert_vtk_to_usd.py Outdated
@aylward aylward merged commit db3b4b5 into Project-MONAI:main Jul 10, 2026
9 checks passed
@aylward aylward deleted the VTK_To_USD branch July 10, 2026 16:41
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.

2 participants