Skip to content

Fix #8442: pass meta_data to EnsureChannelFirst when track_meta is False#8835

Open
williams145 wants to merge 1 commit intoProject-MONAI:devfrom
williams145:fix/issue-8442-loadimage-track-meta-ensure-channel-first
Open

Fix #8442: pass meta_data to EnsureChannelFirst when track_meta is False#8835
williams145 wants to merge 1 commit intoProject-MONAI:devfrom
williams145:fix/issue-8442-loadimage-track-meta-ensure-channel-first

Conversation

@williams145
Copy link
Copy Markdown
Contributor

Fixes #8442

Description

LoadImage with ensure_channel_first=True raises ValueError when set_track_meta(False) is active.

Root cause chain:

  1. set_track_meta(False) causes MetaTensor.ensure_torch_and_prune_meta() to return a plain tensor instead of a MetaTensor
  2. EnsureChannelFirst()(img) then has no metadata source (img is not a MetaTensor and no meta_dict is passed)
  3. This hits the ValueError branch in EnsureChannelFirst.__call__ at line 205 of utility/array.py

Fix: pass meta_data explicitly to EnsureChannelFirst when img is not a MetaTensor. EnsureChannelFirst.__call__ already accepts a meta_dict parameter; meta_data is always a validated dict at this point in LoadImage.__call__.

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.
  • 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.

…ck_meta is False

When set_track_meta(False) is active, MetaTensor.ensure_torch_and_prune_meta
returns a plain tensor. The subsequent EnsureChannelFirst() call then has no
metadata source, causing a ValueError. Fix: pass meta_data explicitly when
img is not a MetaTensor.

Signed-off-by: UGBOMEH OGOCHUKWU WILLIAMS <williamsugbomeh@gmail.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 18, 2026

📝 Walkthrough

Walkthrough

Modified LoadImage.__call__ to conditionally handle channel-first conversion based on whether the loaded image is a MetaTensor. When ensure_channel_first is enabled, the code now checks the image type: if not a MetaTensor, it passes the metadata dictionary to EnsureChannelFirst; if already a MetaTensor, it calls EnsureChannelFirst without the metadata argument. This addresses crashes that occur when set_track_meta(False) is used alongside ensure_channel_first=True.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly references the issue number and summarizes the core fix: passing meta_data to EnsureChannelFirst when track_meta is disabled.
Description check ✅ Passed Description includes root cause chain, fix rationale, and types of changes checklist. All required sections are addressed with sufficient detail.
Linked Issues check ✅ Passed Changes directly address issue #8442 by passing meta_data to EnsureChannelFirst when img is not a MetaTensor, fixing the ValueError crash when set_track_meta(False) is active.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the reported issue. No extraneous modifications detected; only LoadImage.call control flow updated.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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.

Copy link
Copy Markdown
Contributor

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@monai/transforms/io/array.py`:
- Around line 302-306: Add a regression test that verifies disabling meta
tracking with set_track_meta(False) does not break channel-first conversion when
using LoadImage or LoadImaged with ensure_channel_first=True: create a test that
calls set_track_meta(False), runs LoadImage(..., ensure_channel_first=True) (and
a LoadImaged variant) on a sample array, and asserts the output is channel-first
(shape/order) and that no MetaTensor metadata is attached (or meta dict remains
absent) to ensure EnsureChannelFirst still runs on plain tensors; reference
EnsureChannelFirst, LoadImage/LoadImaged, ensure_channel_first, set_track_meta,
and MetaTensor when locating code to test.
🪄 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

Run ID: 9e5bb3f7-9f63-4fb0-9f3b-14fdd624423e

📥 Commits

Reviewing files that changed from the base of the PR and between 851054c and 797cdb7.

📒 Files selected for processing (1)
  • monai/transforms/io/array.py

Comment on lines 302 to +306
if self.ensure_channel_first:
img = EnsureChannelFirst()(img)
if not isinstance(img, MetaTensor):
img = EnsureChannelFirst()(img, meta_dict=meta_data)
else:
img = EnsureChannelFirst()(img)
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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check whether tests already cover disabled meta tracking with ensure_channel_first.
# Expect: At least one test combines set_track_meta(False) with ensure_channel_first=True.

rg -n -C3 'set_track_meta\s*\(\s*False\s*\)' --type py
rg -n -C3 'ensure_channel_first\s*=\s*True' --type py

Repository: Project-MONAI/MONAI

Length of output: 18238


🏁 Script executed:

# Find LoadImage/LoadImaged test files
fd -e py "test_load_image" tests/

Repository: Project-MONAI/MONAI

Length of output: 135


🏁 Script executed:

# Search within LoadImage test files for set_track_meta(False) usage
rg -l "class.*LoadImage" tests/ --type py

Repository: Project-MONAI/MONAI

Length of output: 166


🏁 Script executed:

# Check test_load_image.py and test_load_imaged.py for both conditions
for f in tests/transforms/test_load_image.py tests/transforms/test_load_imaged.py; do
  echo "=== $f ==="
  if [ -f "$f" ]; then
    rg -A5 -B5 "ensure_channel_first.*=.*True" "$f" | head -50
    echo "---"
    rg -A5 -B5 "set_track_meta.*False" "$f" | head -50
  fi
done

Repository: Project-MONAI/MONAI

Length of output: 783


🏁 Script executed:

# Read test_load_image.py to check for set_track_meta usage
wc -l tests/transforms/test_load_image.py

Repository: Project-MONAI/MONAI

Length of output: 102


🏁 Script executed:

# Read test_load_imaged.py to check for set_track_meta usage
wc -l tests/transforms/test_load_imaged.py

Repository: Project-MONAI/MONAI

Length of output: 103


🏁 Script executed:

# Check both files for any set_track_meta calls
grep -n "set_track_meta" tests/transforms/test_load_image.py tests/transforms/test_load_imaged.py

Repository: Project-MONAI/MONAI

Length of output: 386


🏁 Script executed:

# Get context around ensure_channel_first usage in both test files
rg -B10 -A10 "ensure_channel_first\s*=\s*True" tests/transforms/test_load_image.py

Repository: Project-MONAI/MONAI

Length of output: 45


🏁 Script executed:

rg -B10 -A10 "ensure_channel_meta_first\s*=\s*True" tests/transforms/test_load_imaged.py

Repository: Project-MONAI/MONAI

Length of output: 45


🏁 Script executed:

# Check lines around set_track_meta in test_load_image.py
sed -n '480,495p' tests/transforms/test_load_image.py

Repository: Project-MONAI/MONAI

Length of output: 734


🏁 Script executed:

# Check lines around set_track_meta in test_load_imaged.py
sed -n '168,185p' tests/transforms/test_load_imaged.py

Repository: Project-MONAI/MONAI

Length of output: 696


🏁 Script executed:

# Search for any ensure_channel_first in test files (case-insensitive)
rg -i "ensure_channel_first" tests/transforms/test_load_image.py tests/transforms/test_load_imaged.py

Repository: Project-MONAI/MONAI

Length of output: 831


🏁 Script executed:

# Find TESTS_META definition in test_load_image.py
rg -B5 -A5 "TESTS_META\s*=" tests/transforms/test_load_image.py

Repository: Project-MONAI/MONAI

Length of output: 347


🏁 Script executed:

# Find TESTS_META definition in test_load_imaged.py
rg -B5 -A5 "TESTS_META\s*=" tests/transforms/test_load_imaged.py

Repository: Project-MONAI/MONAI

Length of output: 444


🏁 Script executed:

# Get the full test_correct test method in test_load_image.py
sed -n '485,510p' tests/transforms/test_load_image.py

Repository: Project-MONAI/MONAI

Length of output: 825


🏁 Script executed:

# Check if TESTS_META includes ensure_channel_first anywhere
rg -A20 "TESTS_META\s*=" tests/transforms/test_load_image.py | grep "ensure_channel_first"

Repository: Project-MONAI/MONAI

Length of output: 45


🏁 Script executed:

rg -A20 "TESTS_META\s*=" tests/transforms/test_load_imaged.py | grep "ensure_channel_first"

Repository: Project-MONAI/MONAI

Length of output: 45


🏁 Script executed:

# Find all test methods that use ensure_channel_first in test files
rg -B2 "ensure_channel_first" tests/transforms/test_load_image.py tests/transforms/test_load_imaged.py | head -80

Repository: Project-MONAI/MONAI

Length of output: 1457


🏁 Script executed:

# Check if any of those tests also call set_track_meta(False)
rg -B20 "ensure_channel_first\s*=\s*True" tests/transforms/test_load_image.py | rg "set_track_meta"

Repository: Project-MONAI/MONAI

Length of output: 45


🏁 Script executed:

# Check which test method uses TEST_CASE_14, TEST_CASE_18, TEST_CASE_20
rg "TEST_CASE_14|TEST_CASE_18|TEST_CASE_20" tests/transforms/test_load_image.py

Repository: Project-MONAI/MONAI

Length of output: 337


🏁 Script executed:

# Get the test method that uses these test cases
sed -n '445,475p' tests/transforms/test_load_image.py

Repository: Project-MONAI/MONAI

Length of output: 1501


🏁 Script executed:

# Get context around the test_channel_dim method to see full implementation
sed -n '455,480p' tests/transforms/test_load_image.py

Repository: Project-MONAI/MONAI

Length of output: 1281


🏁 Script executed:

# Verify the _cmp method in test_load_imaged.py is not using set_track_meta(False)
sed -n '97,115p' tests/transforms/test_load_imaged.py

Repository: Project-MONAI/MONAI

Length of output: 931


Add regression test for set_track_meta(False) + ensure_channel_first=True.

The fix is correct, but there is no test coverage for set_track_meta(False) combined with LoadImage(..., ensure_channel_first=True) or LoadImaged(..., ensure_channel_first=True). Existing tests cover meta tracking separately from channel-first ordering, but not together. Add a test case to prevent regression of this specific scenario.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@monai/transforms/io/array.py` around lines 302 - 306, Add a regression test
that verifies disabling meta tracking with set_track_meta(False) does not break
channel-first conversion when using LoadImage or LoadImaged with
ensure_channel_first=True: create a test that calls set_track_meta(False), runs
LoadImage(..., ensure_channel_first=True) (and a LoadImaged variant) on a sample
array, and asserts the output is channel-first (shape/order) and that no
MetaTensor metadata is attached (or meta dict remains absent) to ensure
EnsureChannelFirst still runs on plain tensors; reference EnsureChannelFirst,
LoadImage/LoadImaged, ensure_channel_first, set_track_meta, and MetaTensor when
locating code to test.

@williams145
Copy link
Copy Markdown
Contributor Author

@ericspod: CI is green and the branch is up to date. Happy to answer any questions if helpful.

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.

Using set_track_meta(False) causes crash in LoadImage if ensure_channel_first=True

1 participant