Skip to content

fix(data): skip empty foreground when computing DatasetSummary statistics - #9043

Open
aymuos15 wants to merge 1 commit into
Project-MONAI:devfrom
aymuos15:fix/dataset-summary-no-foreground-crash
Open

fix(data): skip empty foreground when computing DatasetSummary statistics#9043
aymuos15 wants to merge 1 commit into
Project-MONAI:devfrom
aymuos15:fix/dataset-summary-no-foreground-crash

Conversation

@aymuos15

@aymuos15 aymuos15 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Description

DatasetSummary.calculate_statistics crashed with a bare RuntimeError on any sample whose label had no foreground voxels at the given foreground_threshold (common with 2D slices or sparse annotations), and if every sample lacked foreground it would divide by zero in the mean/std. calculate_percentiles had the same empty-accumulation hazard. Both methods now skip empty foreground selections and, when no sample contributes any foreground voxels, raise an actionable ValueError that names foreground_threshold and points to setting it to -1 to compute statistics over whole images:

  • monai/data/dataset_summary.pycalculate_statistics continues past empty foreground selections and guards voxel_ct == 0; calculate_percentiles skips empty selections and guards the accumulated list before calling np.percentile.
  • tests/data/test_dataset_summary.py — two new tests: a mixed foreground/background dataset (statistics and percentiles computed from the remaining foreground), and an all-background dataset (ValueError raised by both methods).

Behavior verified end-to-end: a dataset with one normal and one all-background sample now produces statistics from the normal sample (previously it crashed), and an all-background dataset raises the actionable ValueError from both calculate_statistics and calculate_percentiles.

Types of changes

  • Non-breaking change (fix or new feature that would not break existing functionality).
  • Breaking change (fix or new feature that would cause existing functionality to change).
  • New tests added to cover the changes.
  • Integration tests passed locally by running ./runtests.sh -f -u --net --coverage.
  • Quick tests passed locally by running ./runtests.sh --quick --unittests --disttests.
  • In-line docstrings updated.
  • Documentation updated, tested make html command in the docs/ folder.

…tics

Signed-off-by: Soumya Snigdha Kundu <soumya_snigdha.kundu@kcl.ac.uk>
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

calculate_statistics and calculate_percentiles now skip empty foreground selections and raise ValueError when no foreground voxels exist. Tests cover mixed tensor data and all-background inputs.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary fix: skipping empty foreground selections during DatasetSummary statistics computation.
Description check ✅ Passed The description explains the problem, implementation, tests, and behavior changes, and it correctly marks the non-breaking change and new tests.
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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@monai/data/dataset_summary.py`:
- Around line 171-175: Complete the Google-style docstrings for
calculate_statistics and calculate_percentiles in monai/data/dataset_summary.py,
documenting their Raises behavior and Returns as None. Also add descriptive
docstrings for the mixed foreground/background and all-background error tests in
tests/data/test_dataset_summary.py at lines 103 and 124, respectively.

In `@tests/data/test_dataset_summary.py`:
- Around line 127-130: Update both assertRaisesRegex checks around
calculator.calculate_statistics() and calculator.calculate_percentiles() to
match the complete remediation text, including the exact recommendation
foreground_threshold=-1, rather than only the parameter name.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 31ab911b-369d-4c2e-af71-268749401698

📥 Commits

Reviewing files that changed from the base of the PR and between 8690ae7 and 2f5d4d4.

📒 Files selected for processing (2)
  • monai/data/dataset_summary.py
  • tests/data/test_dataset_summary.py

Comment on lines +171 to +175
if voxel_ct == 0:
raise ValueError(
f"no foreground voxels found in any sample with foreground_threshold={foreground_threshold}; "
"set foreground_threshold=-1 to compute statistics over whole images."
)

Copy link
Copy Markdown
Contributor

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

Complete Google-style docstrings for the changed definitions.

  • monai/data/dataset_summary.py#L171-L175: document Raises: and Returns: None for calculate_statistics.
  • monai/data/dataset_summary.py#L221-L224: document Raises: and Returns: None for calculate_percentiles.
  • tests/data/test_dataset_summary.py#L103-L103: document the mixed foreground/background test.
  • tests/data/test_dataset_summary.py#L124-L124: document the all-background error test.

As per path instructions, Python definitions must document variables, return values, and raised exceptions in Google-style docstrings.

📍 Affects 2 files
  • monai/data/dataset_summary.py#L171-L175 (this comment)
  • monai/data/dataset_summary.py#L221-L224
  • tests/data/test_dataset_summary.py#L103-L103
  • tests/data/test_dataset_summary.py#L124-L124
🤖 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 `@monai/data/dataset_summary.py` around lines 171 - 175, Complete the
Google-style docstrings for calculate_statistics and calculate_percentiles in
monai/data/dataset_summary.py, documenting their Raises behavior and Returns as
None. Also add descriptive docstrings for the mixed foreground/background and
all-background error tests in tests/data/test_dataset_summary.py at lines 103
and 124, respectively.

Source: Path instructions

Comment on lines +127 to +130
with self.assertRaisesRegex(ValueError, "foreground_threshold"):
calculator.calculate_statistics()
with self.assertRaisesRegex(ValueError, "foreground_threshold"):
calculator.calculate_percentiles()

Copy link
Copy Markdown
Contributor

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

Assert the full remediation text.

The test must verify the recommendation foreground_threshold=-1. The current regex checks only foreground_threshold, so it would pass if the recommendation were removed.

Proposed assertion
-        with self.assertRaisesRegex(ValueError, "foreground_threshold"):
+        with self.assertRaisesRegex(ValueError, r"set foreground_threshold=-1"):

Apply this to both assertions.

📝 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
with self.assertRaisesRegex(ValueError, "foreground_threshold"):
calculator.calculate_statistics()
with self.assertRaisesRegex(ValueError, "foreground_threshold"):
calculator.calculate_percentiles()
with self.assertRaisesRegex(ValueError, r"set foreground_threshold=-1"):
calculator.calculate_statistics()
with self.assertRaisesRegex(ValueError, r"set foreground_threshold=-1"):
calculator.calculate_percentiles()
🤖 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 `@tests/data/test_dataset_summary.py` around lines 127 - 130, Update both
assertRaisesRegex checks around calculator.calculate_statistics() and
calculator.calculate_percentiles() to match the complete remediation text,
including the exact recommendation foreground_threshold=-1, rather than only the
parameter name.

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.

1 participant