Skip to content

Conversation

@Jiaqi-Lv
Copy link
Collaborator

@Jiaqi-Lv Jiaqi-Lv commented Nov 6, 2025

🚀 Summary

This PR introduces a new NucleusDetector engine to the TIAToolbox framework, enabling detection of nuclei from whole slide images (WSIs) or image patches using models such as MapDe and SCCNN. It supersedes PR #538 by leveraging dask for efficient, parallelized post-processing and result merging. The update also includes:


✨ Key Features

New Engine: NucleusDetector

  • Detects nuclei centroids and probabilities from WSIs or patches.
  • Produces a detection map aligned with segmentation dimensions.
  • Serializes detections into detection arrays ([[x], [y], [type], [probs]]).
  • Supports multiple output backends:
    • SQLiteStore (chunked storage for WSI/patch).
    • Dictionary (flat or patch-indexed).
    • Zarr (arrays for coordinates, classes, probabilities).
  • Compatible with nucleus detection models:
    • MapDe (implemented).
    • SCCNN (integration in progress/debugging).
  • Supports both patch-mode and WSI-mode workflows.

Technical Implementation

The detection pipeline operates as follows:

  1. Segmentation: A WSI-level segmentation map (dask array) is generated using SemanticSegmentor.infer_wsi().
  2. Parallel Post-processing: For WSI inference. Use dask.array.map_overlap to apply the model's post-processing function across the entire segmentation map. This allows the function to execute in parallel on chunks, after which the results are automatically merged back into a unified "detection_map", which is saved as zarr in a cache directory for further processing.
  3. Detection Map:
    • Maintains the same dimensions as the segmentation map.
    • Nuclei centroids contain the detection probability values (defaults to 1 if the model does not produce probabilities).
  4. Serialization: The "detection_map" is converted into "detection_arrays" (format: [[x], [y], [type], [probs]]) representing the detected nuclei. These records are then saved into SQLiteStore (chunk-by-chunk), zarr, or a dict (patch mode only).

Output Formats

SQLiteStore

  • WSI Mode: Returns a single SQLiteStore.
  • Patch Mode: Returns one SQLiteStore per patch.
  • Format:
    Annotation(Point(x,y), properties={'type': 'nuclei', 'probs': 0.9})

Dictionary

  • WSI Mode:
    {
        'x': [...],
        'y': [...],
        'classes': [...],
        'probs': [...]
    }
  • Patch Mode (One sub-dictionary per patch index):
    {
        0: {
            'x': [...],
            'y': [...],
            'classes': [...],
            'probs': [...]
        },
        1: { ... }
    }

Zarr

  • WSI Mode:
    {
        'x': [...],
        'y': [...],
        'classes': [...],
        'probs': [...]
    }
  • Patch Mode: Each key maps to a list of da.array objects, where each array corresponds to a patch.
    {
        'x': [[...], ...],
        'y': [[...], ...],
        'classes': [[...], ...],
        'probs': [[...], ...]
    }

Codebase Integration

  • Registers NucleusDetector in tiatoolbox.models and engine registry.
  • Refactors detection logic from PR ✨ NEW: Add Nucleus Detection Engine #538 into modular components.
  • Updates MapDe implementation to use the new engine.
  • Begins integration of SCCNN with NucleusDetector.
  • Adds utilities for serialization into SQLite, dict, and zarr formats.
  • Introduces unit tests for detection workflows.

Tasks

  • Port code from PR ✨ NEW: Add Nucleus Detection Engine #538 to supersede and close it.
  • Add NucleusDetector engine.
  • Update existing detection models (MapDe implementation complete; SCCNN implementation in progress/debugging).
  • Add unit tests.

@Jiaqi-Lv Jiaqi-Lv added the enhancement New feature or request label Nov 6, 2025
@shaneahmed
Copy link
Member

This PR will take over #538

@Jiaqi-Lv Jiaqi-Lv marked this pull request as draft November 7, 2025 17:29
@Jiaqi-Lv Jiaqi-Lv self-assigned this Nov 7, 2025

This comment was marked as outdated.

Copy link
Contributor

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.


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

Copy link
Collaborator

@behnazelhaminia behnazelhaminia left a comment

Choose a reason for hiding this comment

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

Looks good to me, thanks.

Copy link
Collaborator

@measty measty left a comment

Choose a reason for hiding this comment

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

Looks good, just a few small comments to address

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.

5 participants