Skip to content

fix: compute IVIM quality mask after D*/D swap#108

Closed
RajdeepKushwaha5 wants to merge 2 commits intoOSIPI:mainfrom
RajdeepKushwaha5:fix/ivim-quality-mask-before-swap
Closed

fix: compute IVIM quality mask after D*/D swap#108
RajdeepKushwaha5 wants to merge 2 commits intoOSIPI:mainfrom
RajdeepKushwaha5:fix/ivim-quality-mask-before-swap

Conversation

@RajdeepKushwaha5
Copy link

Summary

Fixes #107 — IVIM quality mask was computed before the D*/D swap, causing voxels that needed swapping to be incorrectly flagged as bad quality.

Problem

In _apply_ivim_quality_and_swap(), the domain quality mask included the check ds_vals > d_vals. When the optimizer returned D > D* (a common occurrence since the labels are interchangeable), this check evaluated to False — marking the voxel as bad quality — even though the very next code block would swap the values into the correct order.

Result: valid voxels were silently zeroed out by the quality mask, reducing usable perfusion-fraction map coverage.

Fix

Moved the D*/D swap before the quality mask computation. The domain checks (D* > D, D < 5e-3, etc.) now operate on post-swap values, so voxels that only needed a label swap are no longer falsely rejected.

Changes

  • osipy/ivim/fitting/estimators.py: Reordered swap and quality-mask blocks in _apply_ivim_quality_and_swap()
    • Swap block now executes first
    • Quality mask uses d_swapped / ds_swapped instead of d_vals / ds_vals

Testing

  • All 36 existing IVIM unit tests pass (pytest tests/unit/ivim/ -v)
  • ruff check . — all checks passed
  • No new dependencies introduced

The quality mask in _apply_ivim_quality_and_swap() was computed before
the D*/D swap, causing voxels that needed swapping to be incorrectly
flagged as bad quality. After the swap the values become valid, but the
quality mask had already rejected them.

Move the swap logic before the quality mask computation so the domain
checks (D* > D, D < 5e-3, etc.) operate on corrected values.
Copilot AI review requested due to automatic review settings March 17, 2026 19:12
Copy link

Copilot AI left a comment

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 fixes IVIM post-processing so the domain quality mask is computed after the D*/D label swap, preventing voxels that only require swapping from being incorrectly rejected and zeroed out.

Changes:

  • Reordered _apply_ivim_quality_and_swap() to perform the D*/D swap before domain quality checks.
  • Updated the domain quality mask to use post-swap d_swapped / ds_swapped values.

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

Comment on lines +355 to +374
# Ensure D* > D (swap if needed) — must happen BEFORE quality check
# so the quality mask reflects post-swap values
swap = d_vals > ds_vals
d_swapped = xp.where(swap, ds_vals, d_vals)
ds_swapped = xp.where(swap, d_vals, ds_vals)

# Update values in-place via array views
d_map.values[...] = d_swapped
param_maps["D*"].values[...] = ds_swapped

# Domain quality mask (computed on post-swap values)
quality = (
fitter_qmask
& (d_swapped > 0)
& (d_swapped < 5e-3)
& (ds_swapped > d_swapped)
& (ds_swapped < 100e-3)
& (f_vals >= 0)
& (f_vals <= 0.7)
)
Covers the specific scenario from issue OSIPI#107:
- Swapped voxel (D > D*) passes quality after swap
- Already-ordered voxel is unaffected
- Out-of-bounds voxel is rejected regardless of swap
@Vedant-Bachhav
Copy link

hi @RajdeepKushwaha5

i want to join osipi slack workspace but i am unable to join, the links on site and github their email sign-ups are disabled and no invite link is available. pls send me an invite link or pls suggest alternative

@RajdeepKushwaha5
Copy link
Author

hi @RajdeepKushwaha5

i want to join osipi slack workspace but i am unable to join, the links on site and github their email sign-ups are disabled and no invite link is available. pls send me an invite link or pls suggest alternative

check out this link : https://osipi.slack.com/archives/C0AC4HK5ECC

@ltorres6
Copy link
Collaborator

Closing as did not read the readme.

@ltorres6 ltorres6 closed this Mar 25, 2026
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.

[BUG] IVIM quality mask computed before D*/D swap - swapped voxels falsely marked as bad quality

4 participants