Skip to content

ENH: Provide TotalSegmentatorWithContrast as a custom seg option#77

Merged
aylward merged 2 commits into
Project-MONAI:mainfrom
aylward:TS_WithContrast
Jul 6, 2026
Merged

ENH: Provide TotalSegmentatorWithContrast as a custom seg option#77
aylward merged 2 commits into
Project-MONAI:mainfrom
aylward:TS_WithContrast

Conversation

@aylward

@aylward aylward commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Added a contrast-aware chest segmentation implementation, exposed in the public API and available in the CLI (via the contrast option).
    • Default workflow examples now use the contrast-aware segmentation method when contrast is needed.
  • Bug Fixes
    • Updated segmentation/workflow calls to use the correct segment(image) signature and removed reliance on extra contrast-study flags.
    • Adjusted workflow behavior and outputs to align standard vs contrast-enabled returned keys (including the contrast result).
  • Documentation
    • Refreshed quickstart, API, troubleshooting, tutorials, and examples to match the new contrast-aware usage.
  • Tests
    • Updated and expanded segmentation/workflow tests for the new contrast-aware path.

Copilot AI review requested due to automatic review settings July 6, 2026 18:22
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Walkthrough

The PR moves contrast handling into SegmentChestTotalSegmentatorWithContrast, updates workflow/CLI defaults to use it, and removes contrast_enhanced/contrast_enhanced_study parameters from documented and tested call sites.

Changes

Contrast-aware segmentation refactor

Layer / File(s) Summary
Base and contrast segmentators
src/physiomotion4d/segment_chest_total_segmentator.py, src/physiomotion4d/segment_chest_total_segmentator_with_contrast.py
The base chest segmentator drops contrast state and helpers, adds a taxonomy hook, and the new subclass adds contrast taxonomy registration and contrast-label postprocessing.
Workflow and CLI construction
src/physiomotion4d/__init__.py, src/physiomotion4d/cli/_method_factories.py, src/physiomotion4d/cli/convert_image_to_usd.py, src/physiomotion4d/cli/convert_image_to_vtk.py, src/physiomotion4d/workflow_convert_image_to_usd.py, src/physiomotion4d/workflow_convert_image_to_vtk.py, src/physiomotion4d/workflow_fit_statistical_model_to_patient.py
The package export, CLI factory, CLI entry points, and workflow classes now construct the contrast-aware segmentator by default or when contrast is requested, and workflow calls no longer pass contrast flags into segmentation.
Tests and fixtures
tests/conftest.py, tests/test_segment_chest_total_segmentator.py, tests/test_workflow_convert_image_to_usd.py, tests/test_workflow_fit_statistical_model_to_patient.py
The fixture set adds the contrast-aware segmentator, and the segmentation and workflow tests update expectations for the new class, default thresholds, and removed contrast flags.
Docs, tutorials, and experiments
README.md, docs/..., experiments/..., tutorials/tutorial_02_ct_to_vtk.py
README, API docs, tutorials, troubleshooting guidance, and experiment scripts update examples to use the contrast-aware segmentator or remove contrast flags from workflow and segmentation calls.

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

Possibly related PRs

🚥 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 change: adding TotalSegmentatorWithContrast as a new segmentation option and integrating it across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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

This PR refactors “contrast-enhanced” handling for TotalSegmentator by removing the contrast_enhanced_study plumbing from workflows/segmenters and instead routing “contrast mode” through a dedicated SegmentChestTotalSegmentatorWithContrast implementation, then updates CLIs, tutorials, experiments, tests, and docs to use the new selection pattern.

Changes:

  • Removes contrast_enhanced_study support from WorkflowConvertImageToVTK.run_workflow() and from SegmentChestTotalSegmentator (including dropping the "contrast" taxonomy group there).
  • Updates CLI factories to choose a contrast-capable segmenter via build_segmentation_method(..., contrast=...) rather than mutating a plain segmenter instance.
  • Updates tests/tutorials/docs/experiments to call segmenter.segment(image) (no contrast flag) and to use SegmentChestTotalSegmentatorWithContrast where a "contrast" mask is required.

Reviewed changes

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

Show a summary per file
File Description
tutorials/tutorial_02_ct_to_vtk.py Switches tutorial to the contrast-capable segmenter and removes contrast_enhanced_study workflow arg.
tests/test_workflow_fit_statistical_model_to_patient.py Updates expectations after removing contrast_enhanced_study passthrough.
tests/test_workflow_convert_image_to_usd.py Updates default segmenter assertions to the contrast-capable variant and removes contrast-flag expectations.
tests/test_segment_chest_total_segmentator.py Splits contrast expectations: plain segmenter has no "contrast" key; contrast segmenter does.
tests/conftest.py Adds a session fixture for SegmentChestTotalSegmentatorWithContrast.
src/physiomotion4d/workflow_fit_statistical_model_to_patient.py Removes contrast_enhanced_study=False when invoking image→VTK workflow.
src/physiomotion4d/workflow_convert_image_to_vtk.py Removes contrast_enhanced_study parameter and related segmenter mutation logic.
src/physiomotion4d/workflow_convert_image_to_usd.py Switches default segmentation backend to the contrast-capable variant.
src/physiomotion4d/segment_chest_total_segmentator.py Removes contrast-specific state/methods and adds a subclass hook for extra taxonomy groups.
src/physiomotion4d/cli/convert_image_to_vtk.py Routes --contrast into the segmentation-method factory rather than workflow args.
src/physiomotion4d/cli/convert_image_to_usd.py Routes --contrast into the segmentation-method factory; removes old TotalSegmentator-specific mutation.
src/physiomotion4d/cli/_method_factories.py Adds contrast parameter to segmentation factory and selects the contrast-capable backend when requested.
src/physiomotion4d/init.py Exposes SegmentChestTotalSegmentatorWithContrast from the public package API.
README.md Updates examples to use the contrast-capable segmenter rather than a runtime contrast flag.
experiments/Lung-GatedCT_To_USD/Experiment_SegReg.py Removes contrast flag from segmenter call sites.
experiments/Heart-VTKSeries_To_USD/1-heart_vtkseries_to_usd.py Switches to the contrast-capable segmenter and removes contrast flag usage.
experiments/Heart-Statistical_Model_To_Patient/heart_model_to_patient.py Removes contrast flag usage and related contrast-mask handling in the example.
experiments/Heart-GatedCT-OptimizedLongitudinalRegistration/3-eval_icon.py Removes contrast flag from segmenter call sites.
experiments/Heart-GatedCT_To_USD/2-generate_segmentation.py Switches to the contrast-capable segmenter and removes contrast-flag mutation calls.
experiments/Heart-GatedCT_To_USD/1-register_images.py Switches to the contrast-capable segmenter and removes contrast flag usage.
docs/troubleshooting.rst Updates guidance to pick the contrast-capable segmenter for contrast-enhanced studies.
docs/quickstart.rst Updates quickstart examples to remove contrast_enhanced/contrast flags and use the new segmenter.
docs/examples.rst Updates examples to use the contrast-capable segmenter and removes contrast flags.
docs/developer/workflows.rst Removes the outdated contrast_enhanced parameter usage in workflow examples.
docs/developer/segmentation.rst Removes contrast flag usage from the segmentation contract example.
docs/cli_scripts/byod_tutorials.rst Updates BYOD tutorial examples to select segmenter explicitly instead of contrast_enhanced.
docs/api/workflows.rst Updates API docs examples to use the contrast-capable segmenter and removes contrast flags.
docs/api/segmentation/totalsegmentator.rst Updates TotalSegmentator docs: plain segmenter has no "contrast"; contrast-capable variant adds it.
docs/api/segmentation/simpleware.rst Removes contrast flag usage from Simpleware usage examples.
docs/api/segmentation/index.rst Removes contrast flag usage from segmentation index examples.
docs/api/segmentation/base.rst Removes contrast flag usage from the base contract examples.
Comments suppressed due to low confidence (1)

src/physiomotion4d/workflow_convert_image_to_usd.py:115

  • The PR title suggests adding TotalSegmentatorWithContrast as an optional/custom segmentation backend, but this change also makes it the default segmenter for WorkflowConvertImageToUSD when segmentation_method=None. If this default swap is intended, the PR title/description should reflect that behavioral change; otherwise consider keeping the previous default and only using the contrast segmenter when explicitly requested.
        if segmentation_method is None:
            segmentation_method = SegmentChestTotalSegmentatorWithContrast(
                log_level=log_level
            )
        elif not isinstance(segmentation_method, SegmentAnatomyBase):
            raise TypeError(
                "segmentation_method must be a SegmentAnatomyBase instance or None"
            )
        self.segmenter: SegmentAnatomyBase = segmentation_method

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

Comment on lines +67 to +69
from .segment_chest_total_segmentator_with_contrast import (
SegmentChestTotalSegmentatorWithContrast,
)


def build_segmentation_method(name: str) -> SegmentAnatomyBase:
def build_segmentation_method(name: str, contrast: bool = False) -> SegmentAnatomyBase:
Comment on lines 203 to 205
contrast_mask_yes = result_with_contrast["contrast"]
segmenter_total_segmentator.set_contrast_enhanced_study(False)

# Both should return valid masks
assert contrast_mask_no is not None, "Contrast mask (no flag) is None"
assert contrast_mask_yes is not None, "Contrast mask (with flag) is None"

@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: 3

Caution

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

⚠️ Outside diff range comments (5)
src/physiomotion4d/cli/convert_image_to_usd.py (1)

138-142: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore the ICON mass-preservation toggle for non-contrast runs. RegisterImagesICON defaults use_mass_preservation to False, so removing set_mass_preservation(not args.contrast) changes non-contrast CLI runs from the previous True setting to False. src/physiomotion4d/cli/convert_image_to_usd.py:138-142

🤖 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/cli/convert_image_to_usd.py` around lines 138 - 142,
Restore the ICON mass-preservation toggle in the RegisterImagesICON branch of
convert_image_to_usd by setting use_mass_preservation based on the contrast flag
before running registration. In the convert_image_to_usd CLI flow, keep the
previous behavior by calling the appropriate RegisterImagesICON setter so
non-contrast runs preserve mass and contrast runs do not, alongside the existing
set_number_of_iterations logic.
docs/api/segmentation/base.rst (1)

40-48: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

SegmentChestTotalSegmentator should not list contrast here. Update this example to reserve contrast for SegmentChestTotalSegmentatorWithContrast; the plain segmenter’s key set is heart, lung, bone, major_vessels, soft_tissue, other.

🤖 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/api/segmentation/base.rst` around lines 40 - 48, The example in the
segmentation docs is incorrect because SegmentChestTotalSegmentator is shown
with a contrast key it does not produce. Update the example in base.rst so the
SegmentChestTotalSegmentator key set only includes heart, lung, bone,
major_vessels, soft_tissue, and other, and reserve contrast for
SegmentChestTotalSegmentatorWithContrast; keep the surrounding explanation about
segmenter-specific membership unchanged.
docs/quickstart.rst (1)

118-123: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Rename project_name to usd_project_name in both quickstart snippets.
WorkflowConvertImageToUSD takes usd_project_name, so the examples at docs/quickstart.rst:118-123 and docs/quickstart.rst:152-157 are broken as written.

🤖 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/quickstart.rst` around lines 118 - 123, In the quickstart examples that
instantiate WorkflowConvertImageToUSD, replace the incorrect project_name
argument with usd_project_name so the documented call matches the actual
constructor signature; update both snippets in the quickstart docs and keep the
rest of the example unchanged.
docs/examples.rst (1)

33-38: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Rename project_name to usd_project_name in the WorkflowConvertImageToUSD examples. The constructor takes usd_project_name, so the snippets at docs/examples.rst:33-38, 409-414, and 478-483 will raise a TypeError as written.

🤖 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/examples.rst` around lines 33 - 38, Update the
`WorkflowConvertImageToUSD` example snippets to use `usd_project_name` instead
of `project_name`, since the constructor expects that argument and the current
examples will fail with a TypeError. Make the same rename in all affected
`WorkflowConvertImageToUSD` usages in the docs examples so the parameter name
matches the workflow API consistently.
docs/developer/segmentation.rst (1)

19-28: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the contrast-handling prose. docs/developer/segmentation.rst:74-76 still attributes contrast-agent fusion to SegmentAnatomyBase; that behavior now belongs in SegmentChestTotalSegmentatorWithContrast.

🤖 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/developer/segmentation.rst` around lines 19 - 28, The contrast-handling
prose in the segmentation developer docs is outdated and still attributes
contrast-agent fusion to SegmentAnatomyBase. Update the text in
docs/developer/segmentation.rst to describe that this behavior now belongs to
SegmentChestTotalSegmentatorWithContrast, and make sure any nearby references to
segmenter responsibilities or taxonomy-based outputs remain consistent with the
current class names and key-based mask contract.
🤖 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/api/workflows.rst`:
- Around line 57-63: The example for WorkflowConvertImageToUSD uses the wrong
constructor argument name, so update the snippet to use usd_project_name instead
of project_name. Keep the rest of the example unchanged and make sure the
parameter name matches the WorkflowConvertImageToUSD initializer so the docs
reflect the actual API.

In `@docs/cli_scripts/byod_tutorials.rst`:
- Around line 93-98: Update the WorkflowConvertImageToUSD Python API snippets to
use the correct constructor argument name: replace project_name with
usd_project_name in the calls to pm4d.WorkflowConvertImageToUSD. Make this
change consistently in both tutorial examples so the documented usage matches
the actual WorkflowConvertImageToUSD signature and avoids TypeError.

In `@docs/troubleshooting.rst`:
- Around line 72-83: The troubleshooting example uses WorkflowConvertImageToUSD
without importing it, so update the documented Python snippet to include the
workflow import alongside SegmentChestTotalSegmentatorWithContrast. Keep the
import block in the same code example and make sure the snippet is
copy/pasteable by referencing WorkflowConvertImageToUSD and
SegmentChestTotalSegmentatorWithContrast together.

---

Outside diff comments:
In `@docs/api/segmentation/base.rst`:
- Around line 40-48: The example in the segmentation docs is incorrect because
SegmentChestTotalSegmentator is shown with a contrast key it does not produce.
Update the example in base.rst so the SegmentChestTotalSegmentator key set only
includes heart, lung, bone, major_vessels, soft_tissue, and other, and reserve
contrast for SegmentChestTotalSegmentatorWithContrast; keep the surrounding
explanation about segmenter-specific membership unchanged.

In `@docs/developer/segmentation.rst`:
- Around line 19-28: The contrast-handling prose in the segmentation developer
docs is outdated and still attributes contrast-agent fusion to
SegmentAnatomyBase. Update the text in docs/developer/segmentation.rst to
describe that this behavior now belongs to
SegmentChestTotalSegmentatorWithContrast, and make sure any nearby references to
segmenter responsibilities or taxonomy-based outputs remain consistent with the
current class names and key-based mask contract.

In `@docs/examples.rst`:
- Around line 33-38: Update the `WorkflowConvertImageToUSD` example snippets to
use `usd_project_name` instead of `project_name`, since the constructor expects
that argument and the current examples will fail with a TypeError. Make the same
rename in all affected `WorkflowConvertImageToUSD` usages in the docs examples
so the parameter name matches the workflow API consistently.

In `@docs/quickstart.rst`:
- Around line 118-123: In the quickstart examples that instantiate
WorkflowConvertImageToUSD, replace the incorrect project_name argument with
usd_project_name so the documented call matches the actual constructor
signature; update both snippets in the quickstart docs and keep the rest of the
example unchanged.

In `@src/physiomotion4d/cli/convert_image_to_usd.py`:
- Around line 138-142: Restore the ICON mass-preservation toggle in the
RegisterImagesICON branch of convert_image_to_usd by setting
use_mass_preservation based on the contrast flag before running registration. In
the convert_image_to_usd CLI flow, keep the previous behavior by calling the
appropriate RegisterImagesICON setter so non-contrast runs preserve mass and
contrast runs do not, alongside the existing set_number_of_iterations logic.
🪄 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: 15c796a2-dba6-444b-9088-4fb62b897ecb

📥 Commits

Reviewing files that changed from the base of the PR and between aa5f5f2 and 6bde856.

📒 Files selected for processing (31)
  • README.md
  • docs/api/segmentation/base.rst
  • docs/api/segmentation/index.rst
  • docs/api/segmentation/simpleware.rst
  • docs/api/segmentation/totalsegmentator.rst
  • docs/api/workflows.rst
  • docs/cli_scripts/byod_tutorials.rst
  • docs/developer/segmentation.rst
  • docs/developer/workflows.rst
  • docs/examples.rst
  • docs/quickstart.rst
  • docs/troubleshooting.rst
  • experiments/Heart-GatedCT-OptimizedLongitudinalRegistration/3-eval_icon.py
  • experiments/Heart-GatedCT_To_USD/1-register_images.py
  • experiments/Heart-GatedCT_To_USD/2-generate_segmentation.py
  • experiments/Heart-Statistical_Model_To_Patient/heart_model_to_patient.py
  • experiments/Heart-VTKSeries_To_USD/1-heart_vtkseries_to_usd.py
  • experiments/Lung-GatedCT_To_USD/Experiment_SegReg.py
  • src/physiomotion4d/__init__.py
  • src/physiomotion4d/cli/_method_factories.py
  • src/physiomotion4d/cli/convert_image_to_usd.py
  • src/physiomotion4d/cli/convert_image_to_vtk.py
  • src/physiomotion4d/segment_chest_total_segmentator.py
  • src/physiomotion4d/workflow_convert_image_to_usd.py
  • src/physiomotion4d/workflow_convert_image_to_vtk.py
  • src/physiomotion4d/workflow_fit_statistical_model_to_patient.py
  • tests/conftest.py
  • tests/test_segment_chest_total_segmentator.py
  • tests/test_workflow_convert_image_to_usd.py
  • tests/test_workflow_fit_statistical_model_to_patient.py
  • tutorials/tutorial_02_ct_to_vtk.py
💤 Files with no reviewable changes (3)
  • docs/developer/workflows.rst
  • tests/test_workflow_fit_statistical_model_to_patient.py
  • src/physiomotion4d/workflow_fit_statistical_model_to_patient.py

Comment thread docs/api/workflows.rst
Comment on lines 57 to 63
workflow = WorkflowConvertImageToUSD(
input_filenames=["cardiac_4d.nrrd"],
contrast_enhanced=True,
output_directory="./results",
project_name="patient_001",
segmentation_method=SegmentChestTotalSegmentator(),
segmentation_method=SegmentChestTotalSegmentatorWithContrast(),
registration_method=RegisterImagesICON(),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## file list"
git ls-files docs/api/workflows.rst
git ls-files | rg '(^|/)(.*workflow.*|.*test.*|.*convert.*usd.*)\.(py|rst|md|ts|js)$' || true

echo
echo "## relevant snippets from docs/api/workflows.rst"
wc -l docs/api/workflows.rst
cat -n docs/api/workflows.rst | sed -n '45,85p'

echo
echo "## search for WorkflowConvertImageToUSD and usd_project_name"
rg -n "WorkflowConvertImageToUSD|usd_project_name|project_name" . -g '!**/.git/**' -g '!**/node_modules/**'

Repository: Project-MONAI/physiomotion4d

Length of output: 14494


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## docs/api/workflows.rst excerpt"
wc -l docs/api/workflows.rst
sed -n '55,70p' docs/api/workflows.rst | cat -n

echo
echo "## declarations/usages"
rg -n "class WorkflowConvertImageToUSD|def __init__|usd_project_name|project_name" . -g '!**/.git/**' -g '!**/node_modules/**'

Repository: Project-MONAI/physiomotion4d

Length of output: 11051


Rename project_name to usd_project_name in this example. WorkflowConvertImageToUSD takes usd_project_name, so this snippet doesn’t match the constructor as written.

🤖 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/api/workflows.rst` around lines 57 - 63, The example for
WorkflowConvertImageToUSD uses the wrong constructor argument name, so update
the snippet to use usd_project_name instead of project_name. Keep the rest of
the example unchanged and make sure the parameter name matches the
WorkflowConvertImageToUSD initializer so the docs reflect the actual API.

Comment on lines 93 to 98
workflow = pm4d.WorkflowConvertImageToUSD(
input_filenames=["patient_dicom_dir"],
contrast_enhanced=False,
segmentation_method=pm4d.SegmentChestTotalSegmentator(),
output_directory="./results",
project_name="patient_heart",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the tutorial file and relevant workflow/API references.
git ls-files docs/cli_scripts/byod_tutorials.rst
rg -n "WorkflowConvertImageToUSD|usd_project_name|project_name" docs/cli_scripts/byod_tutorials.rst . -g '!**/.git/**'

Repository: Project-MONAI/physiomotion4d

Length of output: 11356


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the tutorial sections around the referenced lines.
sed -n '80,155p' docs/cli_scripts/byod_tutorials.rst

Repository: Project-MONAI/physiomotion4d

Length of output: 2354


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search tests or docs that define the expected keyword for this workflow.
rg -n "usd_project_name|project_name" . -g '!**/.git/**' -g '!docs/cli_scripts/byod_tutorials.rst'

Repository: Project-MONAI/physiomotion4d

Length of output: 5156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# If this file is generated from examples elsewhere, inspect nearby docs to compare.
rg -n "WorkflowConvertImageToUSD" docs . -g '!**/.git/**'

Repository: Project-MONAI/physiomotion4d

Length of output: 7905


Rename project_name to usd_project_name in both Python API snippets.

WorkflowConvertImageToUSD takes usd_project_name, so the calls at lines 93-98 and 140-146 will raise TypeError as written.

🤖 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 93 - 98, Update the
WorkflowConvertImageToUSD Python API snippets to use the correct constructor
argument name: replace project_name with usd_project_name in the calls to
pm4d.WorkflowConvertImageToUSD. Make this change consistently in both tutorial
examples so the documented usage matches the actual WorkflowConvertImageToUSD
signature and avoids TypeError.

Comment thread docs/troubleshooting.rst
Comment on lines +72 to 83
1. Check if image is contrast-enhanced. Use
:class:`SegmentChestTotalSegmentatorWithContrast` instead of
:class:`SegmentChestTotalSegmentator` for contrast-enhanced studies:

.. code-block:: python

from physiomotion4d import SegmentChestTotalSegmentatorWithContrast

workflow = WorkflowConvertImageToUSD(
...,
contrast_enhanced=True # or False
segmentation_method=SegmentChestTotalSegmentatorWithContrast(),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add the missing workflow import.

WorkflowConvertImageToUSD is used here without being imported, so the snippet is not copy/pasteable. Please add the workflow import alongside SegmentChestTotalSegmentatorWithContrast.

🤖 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/troubleshooting.rst` around lines 72 - 83, The troubleshooting example
uses WorkflowConvertImageToUSD without importing it, so update the documented
Python snippet to include the workflow import alongside
SegmentChestTotalSegmentatorWithContrast. Keep the import block in the same code
example and make sure the snippet is copy/pasteable by referencing
WorkflowConvertImageToUSD and SegmentChestTotalSegmentatorWithContrast together.

@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: 2

Caution

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

⚠️ Outside diff range comments (2)
src/physiomotion4d/workflow_convert_image_to_vtk.py (2)

51-57: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Stale docstring: still states default is SegmentChestTotalSegmentator.

Line 57 reads "Defaults to a new :class:SegmentChestTotalSegmentator when omitted," but the actual default (per lines 94 and 104-106) is now SegmentChestTotalSegmentatorWithContrast. This directly contradicts the updated __init__ docstring/behavior a few lines below.

📝 Proposed fix
-    segmentation with pulmonary/great-vessel branches trimmed). Defaults to
-    a new :class:`SegmentChestTotalSegmentator` when omitted.
+    segmentation with pulmonary/great-vessel branches trimmed). Defaults to
+    a new :class:`SegmentChestTotalSegmentatorWithContrast` when omitted.
🤖 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/workflow_convert_image_to_vtk.py` around lines 51 - 57,
Update the stale docstring for the segmentation_method parameter in
workflow_convert_image_to_vtk.py so it matches the actual default used by the
constructor. The current text still says the default is
SegmentChestTotalSegmentator, but __init__ now uses
SegmentChestTotalSegmentatorWithContrast when omitted; revise that sentence and
any related wording in the docstring to reflect the current behavior, keeping
the references to SegmentAnatomyBase and the concrete segmenter classes
consistent.

92-106: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore the plain default for WorkflowConvertImageToVTK

WorkflowConvertImageToVTK() now instantiates SegmentChestTotalSegmentatorWithContrast, but this workflow's docstring and tests still expect SegmentChestTotalSegmentator. That changes the implicit behavior for every caller that omits segmentation_method and can relabel non-contrast CTs as contrast. Make the contrast variant explicit instead, or revert the default to the plain segmenter.

🤖 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/workflow_convert_image_to_vtk.py` around lines 92 - 106,
The default segmentation backend in WorkflowConvertImageToVTK has been changed
to the contrast variant, but the documented and tested behavior still expects
the plain segmenter. Update the default handling in
WorkflowConvertImageToVTK.__init__ so callers omitting segmentation_method get
SegmentChestTotalSegmentator, or otherwise make the contrast choice explicit
without changing the implicit default. Keep the type check and constructor flow
intact, but ensure the default path matches the existing
WorkflowConvertImageToVTK docstring and tests.
🧹 Nitpick comments (1)
src/physiomotion4d/segment_chest_total_segmentator_with_contrast.py (1)

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

Rename preprocessed_image to reflect raw CT input segment_contrast_agent() is called with the original image, and its HU thresholding depends on raw intensities. Update the parameter/docstring to input_image or raw_image so normalized data isn’t passed in later and contrast detection silently breaks.

🤖 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/segment_chest_total_segmentator_with_contrast.py` around
lines 180 - 225, The segment_contrast_agent() parameter name and documentation
are misleading because it operates on raw CT intensities, not a preprocessed
image. Rename preprocessed_image to input_image or raw_image in
segment_contrast_agent() and update the docstring/argument description to match,
then ensure the call to segment_connected_component() uses the renamed variable
consistently so normalized data is not passed in by mistake.
🤖 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 `@src/physiomotion4d/segment_chest_total_segmentator_with_contrast.py`:
- Around line 40-48: Add an explicit `-> None` return annotation to the
`__init__` method in `SegmentChestTotalSegmentatorWithContrast` so it satisfies
mypy strict mode with `disallow_untyped_defs = true`. Keep the existing
`log_level` argument typing and `super().__init__(log_level=log_level)`
initialization unchanged, and only update the constructor signature to make the
return type explicit.
- Around line 54-56: The type annotations in this module use the deprecated
lowercase ITK alias, which is invalid for strict typing. Update the
`postprocess_after_labelmap` signature and any other annotations in this file to
use `itk.Image` instead of `itk.image`, including the `input_image`,
`labelmap_image`, and return types so the class and method definitions remain
type-correct.

---

Outside diff comments:
In `@src/physiomotion4d/workflow_convert_image_to_vtk.py`:
- Around line 51-57: Update the stale docstring for the segmentation_method
parameter in workflow_convert_image_to_vtk.py so it matches the actual default
used by the constructor. The current text still says the default is
SegmentChestTotalSegmentator, but __init__ now uses
SegmentChestTotalSegmentatorWithContrast when omitted; revise that sentence and
any related wording in the docstring to reflect the current behavior, keeping
the references to SegmentAnatomyBase and the concrete segmenter classes
consistent.
- Around line 92-106: The default segmentation backend in
WorkflowConvertImageToVTK has been changed to the contrast variant, but the
documented and tested behavior still expects the plain segmenter. Update the
default handling in WorkflowConvertImageToVTK.__init__ so callers omitting
segmentation_method get SegmentChestTotalSegmentator, or otherwise make the
contrast choice explicit without changing the implicit default. Keep the type
check and constructor flow intact, but ensure the default path matches the
existing WorkflowConvertImageToVTK docstring and tests.

---

Nitpick comments:
In `@src/physiomotion4d/segment_chest_total_segmentator_with_contrast.py`:
- Around line 180-225: The segment_contrast_agent() parameter name and
documentation are misleading because it operates on raw CT intensities, not a
preprocessed image. Rename preprocessed_image to input_image or raw_image in
segment_contrast_agent() and update the docstring/argument description to match,
then ensure the call to segment_connected_component() uses the renamed variable
consistently so normalized data is not passed in by mistake.
🪄 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: 56b84375-8450-4c38-8d8d-689bfe4ccf19

📥 Commits

Reviewing files that changed from the base of the PR and between 6bde856 and 9275acb.

📒 Files selected for processing (2)
  • src/physiomotion4d/segment_chest_total_segmentator_with_contrast.py
  • src/physiomotion4d/workflow_convert_image_to_vtk.py

Comment on lines +40 to +48
def __init__(self, log_level: int | str = logging.INFO):
"""Initialize the contrast-enhanced TotalSegmentator-based segmentation.

Args:
log_level: Logging level (default: logging.INFO)
"""
super().__init__(log_level=log_level)

self.contrast_threshold: int = 500

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Missing -> None return annotation on __init__.

Under mypy strict mode (disallow_untyped_defs = true), __init__ must also declare its return type.

🔧 Proposed fix
-    def __init__(self, log_level: int | str = logging.INFO):
+    def __init__(self, log_level: int | str = logging.INFO) -> None:

As per coding guidelines, "Use full type hints with mypy strict mode (disallow_untyped_defs = true)".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def __init__(self, log_level: int | str = logging.INFO):
"""Initialize the contrast-enhanced TotalSegmentator-based segmentation.
Args:
log_level: Logging level (default: logging.INFO)
"""
super().__init__(log_level=log_level)
self.contrast_threshold: int = 500
def __init__(self, log_level: int | str = logging.INFO) -> None:
"""Initialize the contrast-enhanced TotalSegmentator-based segmentation.
Args:
log_level: Logging level (default: logging.INFO)
"""
super().__init__(log_level=log_level)
self.contrast_threshold: int = 500
🤖 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/segment_chest_total_segmentator_with_contrast.py` around
lines 40 - 48, Add an explicit `-> None` return annotation to the `__init__`
method in `SegmentChestTotalSegmentatorWithContrast` so it satisfies mypy strict
mode with `disallow_untyped_defs = true`. Keep the existing `log_level` argument
typing and `super().__init__(log_level=log_level)` initialization unchanged, and
only update the constructor signature to make the return type explicit.

Source: Coding guidelines

Comment on lines +54 to +56
def postprocess_after_labelmap(
self, input_image: itk.image, labelmap_image: itk.image
) -> itk.image:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does the itk Python package define itk.image as a class or only as a deprecated function alias for itk.output()?

💡 Result:

In the itk Python package, itk.Image (with a capital "I") is a class, whereas itk.image (with a lowercase "i") is a deprecated function [1][2][3]. Specifically: - itk.Image is the template class used to instantiate ITK image objects (e.g., ImageType = itk.Image[itk.UC, 2]) [2][4]. - itk.image is a legacy function that acts as an alias for itk.output [1][5]. Its usage triggers a warning stating that it is deprecated and that itk.output should be used instead [1][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/physiomotion4d/segment_chest_total_segmentator_with_contrast.py"

echo "== File outline =="
ast-grep outline "$FILE" --view expanded || true

echo
echo "== Matching annotations =="
rg -n "itk\.image|itk\.Image" "$FILE" || true

echo
echo "== Relevant file excerpt =="
wc -l "$FILE"
sed -n '1,240p' "$FILE"

Repository: Project-MONAI/physiomotion4d

Length of output: 10726


Replace itk.image with itk.Image in this module.
itk.image is a deprecated function alias, not a type, so these annotations are invalid for strict type checking. Update the parameter and return annotations throughout this file.

🤖 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/segment_chest_total_segmentator_with_contrast.py` around
lines 54 - 56, The type annotations in this module use the deprecated lowercase
ITK alias, which is invalid for strict typing. Update the
`postprocess_after_labelmap` signature and any other annotations in this file to
use `itk.Image` instead of `itk.image`, including the `input_image`,
`labelmap_image`, and return types so the class and method definitions remain
type-correct.

Source: Coding guidelines

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 34.24658% with 48 lines in your changes missing coverage. Please review.
✅ Project coverage is 36.07%. Comparing base (aa5f5f2) to head (9275acb).

Files with missing lines Patch % Lines
...d/segment_chest_total_segmentator_with_contrast.py 25.00% 45 Missing ⚠️
src/physiomotion4d/cli/_method_factories.py 40.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #77      +/-   ##
==========================================
+ Coverage   36.04%   36.07%   +0.03%     
==========================================
  Files          57       58       +1     
  Lines        7275     7271       -4     
==========================================
+ Hits         2622     2623       +1     
+ Misses       4653     4648       -5     
Flag Coverage Δ
integration-tests 35.96% <34.24%> (?)
unittests 36.06% <34.24%> (+0.01%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

@aylward aylward merged commit 2bf7933 into Project-MONAI:main Jul 6, 2026
11 of 12 checks passed
@aylward aylward deleted the TS_WithContrast branch July 6, 2026 20:24
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