Skip to content

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

Open
williams145 wants to merge 2 commits 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 2 commits 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.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

📝 Walkthrough

Walkthrough

When LoadImage.__call__ runs with ensure_channel_first=True, the call to the channel-first transform now passes the loaded image's metadata as meta_dict=meta_data (instead of invoking the transform without metadata). A new unit test verifies behavior when global metadata tracking is disabled (set_track_meta(False)): LoadImage returns a plain torch.Tensor with channel-first shape (1, 128, 128, 128).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly references the issue number and describes the core fix: passing metadata to EnsureChannelFirst when track_meta is False.
Description check ✅ Passed Description includes issue reference, clear root cause analysis, solution explanation, and types of changes. Follows template structure with all key sections completed.
Linked Issues check ✅ Passed PR directly addresses #8442 by passing meta_data to EnsureChannelFirst when img lacks MetaTensor, preventing the ValueError that occurs when track_meta is disabled.
Out of Scope Changes check ✅ Passed Changes are narrowly scoped: one-line fix in LoadImage and one test validating the fix. Both directly target the issue without extraneous modifications.

✏️ 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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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 thread monai/transforms/io/array.py Outdated
@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.

Copy link
Copy Markdown
Member

@ericspod ericspod left a comment

Choose a reason for hiding this comment

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

Hi @williams145 thanks for this fix. I think it's correct but we should have a regression test for the class as suggested. I suggested a change, please have a look at that as well.

Comment thread monai/transforms/io/array.py Outdated
…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>
…n test

Apply review suggestion: pass meta_data unconditionally to
EnsureChannelFirst — when img is a MetaTensor, EnsureChannelFirst
overrides meta_dict with img.meta internally, so the explicit if/else
is not needed.

Add regression test covering set_track_meta(False) with
ensure_channel_first=True on LoadImage.

Signed-off-by: UGBOMEH OGOCHUKWU WILLIAMS <williamsugbomeh@gmail.com>
@williams145 williams145 force-pushed the fix/issue-8442-loadimage-track-meta-ensure-channel-first branch from 797cdb7 to 36ded05 Compare May 1, 2026 19:22
@williams145
Copy link
Copy Markdown
Contributor Author

Thanks for the review. Verified the simplification works. Looking at EnsureChannelFirst.__call__, when img is a MetaTensor it does meta_dict = img.meta (line 212 of monai/transforms/utility/array.py), which overrides whatever was passed in. So passing meta_data unconditionally is safe in both cases. Applied your suggestion and pushed.

Also added a regression test (test_track_meta_false_ensure_channel_first) in tests/transforms/test_load_image.py that covers the exact scenario this PR fixes: set_track_meta(False) combined with ensure_channel_first=True. It asserts the result is a plain torch.Tensor (not MetaTensor) with the channel dim correctly added.

CI re-running now.

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 `@tests/transforms/test_load_image.py`:
- Around line 500-508: The test hard-codes set_track_meta(True) in the finally
block which can clobber the suite's prior state; change the test
(test_track_meta_false_ensure_channel_first) to capture the current state at the
start (e.g., prev = get_track_meta()), call set_track_meta(False) for the test,
and then in the finally block restore the original with set_track_meta(prev)
instead of set_track_meta(True); keep using LoadImage(...) and the same
assertions and ensure get_track_meta/set_track_meta symbols are used to locate
the change.
🪄 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: aff8f650-076c-4360-8760-9219eba1c8d4

📥 Commits

Reviewing files that changed from the base of the PR and between 797cdb7 and 36ded05.

📒 Files selected for processing (2)
  • monai/transforms/io/array.py
  • tests/transforms/test_load_image.py

Comment thread tests/transforms/test_load_image.py
Comment on lines +501 to +508
try:
set_track_meta(False)
r = LoadImage(image_only=True, ensure_channel_first=True)(self.test_data)
self.assertTupleEqual(r.shape, (1, 128, 128, 128))
self.assertIsInstance(r, torch.Tensor)
self.assertNotIsInstance(r, MetaTensor)
finally:
set_track_meta(True)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
try:
set_track_meta(False)
r = LoadImage(image_only=True, ensure_channel_first=True)(self.test_data)
self.assertTupleEqual(r.shape, (1, 128, 128, 128))
self.assertIsInstance(r, torch.Tensor)
self.assertNotIsInstance(r, MetaTensor)
finally:
set_track_meta(True)
_previous_meta = get_track_meta()
try:
set_track_meta(False)
r = LoadImage(image_only=True, ensure_channel_first=True)(self.test_data)
self.assertTupleEqual(r.shape, (1, 128, 128, 128))
self.assertIsInstance(r, torch.Tensor)
self.assertNotIsInstance(r, MetaTensor)
finally:
set_track_meta(_previous_meta)

This ensures the previous state is restored which could be False. This isn't thread-safe by the way but every other usage of these functions isn't either so we will have to accept this for now until that's fixed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is unlikely to be an issue in the tests honestly but we should do this anyway just in case.

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

2 participants