Skip to content

fix: combine all membrane markers for cellSAM segmentation - #31

Merged
mcmero merged 2 commits into
WEHI-SODA-Hub:devfrom
mikemcka:fix/cellsam-combine-membrane-channels
Jul 13, 2026
Merged

mcmero merged 2 commits into
WEHI-SODA-Hub:devfrom
mikemcka:fix/cellsam-combine-membrane-channels

Conversation

@mikemcka

Copy link
Copy Markdown
Collaborator

Problem

When running cellSAM whole-cell segmentation, only the first matching
membrane marker was ever used. extract_channels in bin/cellsam_segment.py
loops over the --membrane-channel list and breaks on the first hit, so any
additional markers were silently discarded. With a single weak boundary marker,
cellSAM falls back to a nucleus-driven (round) segmentation.

This is inconsistent with the Cellpose/SOPA path, which already runs
COMBINECHANNELS to max-combine all listed membrane markers into one channel
before segmentation.

Fix

Wire COMBINECHANNELS into the CELLSAM_SEGMENT subworkflow (mirroring
subworkflows/local/sopa_segment/main.nf): all listed membrane markers are
max-combined into a single combined_membrane channel, and that combined tiff
is what feeds both CELLSAMWC and CELLSAMNUC. The duplicate COMBINECHANNELS
call in the report block is removed (it now runs upstream).

CELLSAM_SEGMENT_WBACKSUB inherits the fix automatically — it background-subtracts
then delegates to CELLSAM_SEGMENT.

Observability

Because cellSAM now only sees the single combined channel (its
Available channels: log no longer shows the source panel), combine_channels.py
logs what it combined to stderr, e.g.:

[combine_channels] nuclear='DAPI'; membrane=['CD45', 'Ecad'] -> 'combined_membrane' (method=max, n=2)

This benefits the Cellpose path and the report background too, since they share the module.

Tests

  • New combinechannels - multi-membrane combine case (the module previously had
    no multi-membrane coverage — both existing cases use a single channel).
  • New cellsam_segment - multi-membrane combine case guarding the wiring.
  • Both reuse tests/data/comet/synthetic_multichannel.tif (CD45:TRITC = two markers);
    no new test binary.

Validation already run

  • Ran the real combine_channels.py on a synthetic 2-marker array (markers in
    non-overlapping halves): output is [DAPI, combined_membrane] with
    combined_membrane == max(CD45, Ecad) and not equal to either single marker.
  • Full Nextflow -stub-run of the cellSAM path with CD45:Ecad:
    COMBINECHANNELS -> CELLSAMWC/CELLSAMNUC -> CELLMEASUREMENT -> SEGMENTATIONREPORT,
    pipeline completed successfully (no double-COMBINECHANNELS error).

Reviewer checklist — snapshots need blessing on a GPU node

nf-test snapshots are not included (no nf-test/GPU on the dev box). Before merge, run with --update-snapshot and commit the .snap files:

  • modules/local/combinechannels — new case (deterministic, GPU-free)
  • subworkflows/local/cellsam_segment — new case and re-bless the existing case (changed: COMBINECHANNELS now runs in the workflow → new entry in versions)
  • subworkflows/local/cellsam_segment_wbacksub — re-bless the existing case (same reason)

🤖 Generated with Claude Code

cellSAM previously received only the first matching membrane channel
(first-match-and-break in extract_channels), silently discarding any
additional markers. Wire COMBINECHANNELS into the CELLSAM_SEGMENT
subworkflow (mirroring the SOPA/Cellpose path) so all listed membrane
markers are max-combined into a single 'combined_membrane' channel
before segmentation. The background-subtraction variant inherits the
fix via its call to CELLSAM_SEGMENT.

Because cellSAM now only sees the single combined channel, log which
channels were combined in combine_channels.py so that information stays
visible in the process log.

Add multi-membrane nf-test cases to the combinechannels module and the
cellsam_segment subworkflow (reusing synthetic_multichannel.tif with
CD45:TRITC). Snapshots still need blessing on a GPU node; the existing
cellsam_segment / cellsam_segment_wbacksub snapshots also change because
COMBINECHANNELS now runs within those workflows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

This PR is against the main branch ❌

  • Do not close this PR
  • Click Edit and change the base to dev
  • This CI test will remain failed until you push a new commit

Hi @mikemcka,

It looks like this pull-request is has been made against the mikemcka/sp_segment main branch.
The main branch on nf-core repositories should always contain code from the latest release.
Because of this, PRs to main are only allowed if they come from the mikemcka/sp_segment dev branch.

You do not need to close this PR, you can change the target branch to dev by clicking the "Edit" button at the top of this page.
Note that even after this, the test will continue to show as failing until you push a new commit.

Thanks again for your contribution!

@mikemcka
mikemcka changed the base branch from main to dev June 29, 2026 04:55

@mcmero mcmero left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good, I'll merge it to dev.

@mcmero
mcmero merged commit 02bc645 into WEHI-SODA-Hub:dev Jul 13, 2026
4 checks passed
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.

2 participants