MONAI icon indicating copy to clipboard operation
MONAI copied to clipboard

Correct H&E stain ordering heuristic in ExtractHEStains

Open iyassou opened this issue 3 months ago β€’ 5 comments

Description

I noticed when attempting to extract the hematoxylin stain from an H&E stained image that the previous heuristic for ordering hematoxylin first and eosin second incorrectly assumed hematoxylin has a higher red channel value, when the opposite is typically true. I've corrected this and implemented a more robust heuristic that compares red-blue ratios instead, since:

  • Hematoxylin (nuclear, blue): lower red/blue ratio
  • Eosin (cytoplasm, pink): higher red/blue ratio

I've updated the tests to reflect the corrected stain ordering, and the output now accurately reflects the documented behaviour (first column hematoxylin, second eosin).

Types of changes

  • [x] Non-breaking change (fix or new feature that would not break existing functionality).
  • [x] Integration tests passed locally by running ./runtests.sh -f -u --net --coverage.
  • [x] Quick tests passed locally by running ./runtests.sh --quick --unittests --disttests.

iyassou avatar Sep 01 '25 13:09 iyassou

Walkthrough

The HE stain ordering in monai/apps/pathology/transforms/stain/array.py was changed to use a red-to-blue (R/B) ratio heuristic between two candidate vectors (v_min and v_max) with an epsilon guard to avoid division-by-zero. If the hematoxylin-like vector has a smaller R/B ratio it is kept first; otherwise the two vectors are swapped when constructing the two-column β€œhe” matrix. Tests in tests/apps/pathology/transforms/test_pathology_he_stain.py and test_pathology_he_stain_dict.py were updated to reflect the swapped stain-column orientation and adjusted concentration and normalized-image expectations. No public API signatures changed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Pre-merge checks and finishing touches

βœ… Passed checks (3 passed)
Check name Status Explanation
Title Check βœ… Passed The title "Correct H&E stain ordering heuristic in ExtractHEStains" clearly and specifically describes the main change: fixing the stain ordering logic in the ExtractHEStains component. It directly reflects the core modification from a threshold-based heuristic to a red-blue ratio heuristic, is concise and readable, and provides sufficient context for developers scanning the history to understand the primary change.
Description Check βœ… Passed The description follows the template structure with a substantive Description section explaining the problem, solution, and rationale for the change. The author provided detailed context on why the previous heuristic was incorrect and how the new red-blue ratio approach works. The Types of changes section is populated with relevant checkboxes and indicates integration and quick tests were run locally. The only missing element from the template is the "Fixes #" issue reference line, which is a minor omission.
Docstring Coverage βœ… Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • [ ] πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • [ ] Create PR with unit tests
  • [ ] Post copyable unit tests in a comment

πŸ“œ Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 246282d8d39f34432ab25f78d067a2baf635d926 and dde2c606820a524dca88c482f575695a403b84a0.

πŸ“’ Files selected for processing (1)
  • monai/apps/pathology/transforms/stain/array.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • monai/apps/pathology/transforms/stain/array.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: flake8-py3 (mypy)
  • GitHub Check: quick-py3 (macOS-latest)
  • GitHub Check: packaging
  • GitHub Check: flake8-py3 (pytype)
  • GitHub Check: quick-py3 (windows-latest)
  • GitHub Check: build-docs
  • GitHub Check: flake8-py3 (codeformat)
  • GitHub Check: quick-py3 (ubuntu-latest)
  • GitHub Check: min-dep-pytorch (2.8.0)
  • GitHub Check: min-dep-pytorch (2.5.1)
  • GitHub Check: min-dep-pytorch (2.6.0)
  • GitHub Check: min-dep-py3 (3.10)
  • GitHub Check: min-dep-pytorch (2.7.1)
  • GitHub Check: min-dep-os (windows-latest)
  • GitHub Check: min-dep-py3 (3.12)
  • GitHub Check: min-dep-py3 (3.11)
  • GitHub Check: min-dep-py3 (3.9)
  • GitHub Check: min-dep-os (macOS-latest)
  • GitHub Check: min-dep-os (ubuntu-latest)

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot] avatar Sep 01 '25 13:09 coderabbitai[bot]

Hi @bhashemian would you be able to review this change or suggest who might be better placed? Thanks!

ericspod avatar Sep 11 '25 23:09 ericspod

@coderabbitai full review

bhashemian avatar Oct 21 '25 19:10 bhashemian

βœ… Actions performed

Full review triggered.

coderabbitai[bot] avatar Oct 21 '25 19:10 coderabbitai[bot]

/build

bhashemian avatar Oct 24 '25 13:10 bhashemian

Hi @KumoLiu please trigger blossom on this PR when you can, @bhashemian isn't able to do so himself. Thanks!

ericspod avatar Nov 11 '25 00:11 ericspod

/build

KumoLiu avatar Nov 12 '25 15:11 KumoLiu