Skip to content

🆕Multichannel Image Reading#825

Merged
shaneahmed merged 167 commits intodevelopfrom
multichannel-reading
Feb 14, 2026
Merged

🆕Multichannel Image Reading#825
shaneahmed merged 167 commits intodevelopfrom
multichannel-reading

Conversation

@measty
Copy link
Collaborator

@measty measty commented Jun 21, 2024

Summary

This PR adds ** multichannel (e.g., immunofluorescence) image support** across readers, the TileServer, and the Bokeh visualization app. It introduces a new MultichannelToRGB post‑processing pipeline that composites N‑channel data to RGB, a channel/color selection UI (with enhancement control) in the app, and corresponding TileServer endpoints to sync state. It also hardens TIFF/OME channel‑metadata parsing, adds qptiff samples for testing, and refactors WSIPatchDataset to improve input validation and tissue‑mask handling. Additional tests cover edge cases across readers, metadata parsing, UI, and server routes.

multi_channel

Multichannel Image Support, TileServer & Bokeh UI Enhancements, and Reader/Dataset Hardening


Key Changes

✨ Features

  • Post‑processing for multichannel images

    • New tiatoolbox.utils.postproc_defs.MultichannelToRGB class for converting multi‑channel arrays to RGB, with configurable color dict, channel activity/order, and an enhance factor. Includes extensive unit tests.
  • WSIReader API: post_proc

    • WSIReader.open(..., post_proc="auto" | None | callable) now propagates to all reader types.
      • "auto" applies MultichannelToRGB for multiplex TIFF/virtual inputs (returns RGB).
      • None skips post‑processing (returns native channel count).
      • A callable allows custom post‑processing.
  • Bokeh app – Channel/color UI

    • New UI block (channel table, color table with color picker, “Apply Changes” button, and an Enhance slider) to control which channels are visible and their colors. UI auto‑populates from server.
  • TileServer endpoints

    • GET /tileserver/channels → current {channels, active} state.
    • PUT /tileserver/channels → set color map & active channels.
    • PUT /tileserver/enhance → set global enhancement factor.
    • Safe fallbacks when no multichannel post‑proc is present.
  • QPTIFF sample integration

    • Adds multiplex_example.qptiff (+ small variant) to remote samples; fixtures & tests use them end‑to‑end through app and server.

🧠 TIFF/OME Metadata & Reader Hardening

  • Robust parsing of OME-XML channel colors/dyes, ScanColorTable, and FilterColors blocks, with sane fallbacks (auto‑generated colors, tolerant of missing/invalid values). Objective power inference falls back to MPP when missing. Extensive edge‑case tests included.
  • Reader selection for TIFF now prefers the most appropriate backend; qptiff supported via TIFFWSIReader. Some paths that previously resolved to OpenSlide may now return TIFFWSIReader.

🧰 Dataset Refactor

  • WSIPatchDataset:
    • Input validation split into _validate_inputs, with clearer errors.
    • Mask creation factored into _setup_mask_reader (now retries with MPP when power is unavailable).
    • Patch filtering moved to _filter_patches.
    • Fixes auto‑mask behavior when only MPP is present.

🖼️ Docs

  • Adds “Multichannel Images” section to the visualization docs explaining channel selection and color overrides in the UI (including performance notes).

🔧 Other

  • Bokeh slide list now includes *.qptiff; minor UI and server startup robustness tweaks; small lint/style fix.

Breaking / Behavior‑Changing Notes

  • Output shape change with default settings: When opening multiplex images, post_proc="auto" (default) returns RGB (3 channels). To obtain raw N‑channel data, callers must pass post_proc=None.
  • Reader selection: Some TIFF files (incl. qptiff/tiled‑tiff) may now open via TIFFWSIReader instead of OpenSlideWSIReader. Tests and assertions updated to accept either where appropriate.
  • Stricter dataset validation: WSIPatchDataset now validates shapes early and raises more precise errors.

Usage Examples

1) Programmatic reading (RGB composite vs raw channels)

from tiatoolbox.wsicore.wsireader import WSIReader

# Auto composite to RGB (default multichannel behavior)
wsi = WSIReader.open("sample.ome.tiff", post_proc="auto")
rgb = wsi.read_rect((0, 0), (100, 100))     # rgb.shape == (100, 100, 3)

# Get native channels (no post-processing)
wsi_raw = WSIReader.open("sample.ome.tiff", post_proc=None)
raw = wsi_raw.read_rect((0, 0), (100, 100)) # raw.shape == (100, 100, N)

@codecov
Copy link

codecov bot commented Jun 21, 2024

Codecov Report

❌ Patch coverage is 99.77629% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 99.41%. Comparing base (78b797e) to head (db012cf).

Files with missing lines Patch % Lines
tiatoolbox/visualization/bokeh_app/main.py 98.07% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #825      +/-   ##
===========================================
+ Coverage    99.37%   99.41%   +0.03%     
===========================================
  Files           71       72       +1     
  Lines         9175     9540     +365     
  Branches      1197     1267      +70     
===========================================
+ Hits          9118     9484     +366     
+ Misses          31       29       -2     
- Partials        26       27       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@shaneahmed shaneahmed linked an issue Jun 25, 2024 that may be closed by this pull request
@shaneahmed shaneahmed changed the title ENH: initial draft multichannel reading 🆕Multichannel Image Reading Jun 25, 2024
@measty measty marked this pull request as ready for review February 6, 2026 22:24
Copy link
Member

@shaneahmed shaneahmed left a comment

Choose a reason for hiding this comment

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

This looks good and I can successfully load the images in TIAViz. However, I am not clear how to read the channels in python. Could you add some examples in the docstring?

@shaneahmed shaneahmed merged commit d9f133f into develop Feb 14, 2026
2 of 3 checks passed
@shaneahmed shaneahmed deleted the multichannel-reading branch February 14, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add multichannel viewer [ENH] Get ValueError: Unsupported axes YX when using OME-TIFF for nuclear segmentation

7 participants