Skip to content

Add BD FACSMelody cell sorter support#1156

Open
di-omics wants to merge 2 commits into
PyLabRobot:v1b1from
di-omics:facsmelody-sorter
Open

Add BD FACSMelody cell sorter support#1156
di-omics wants to merge 2 commits into
PyLabRobot:v1b1from
di-omics:facsmelody-sorter

Conversation

@di-omics

@di-omics di-omics commented Jul 7, 2026

Copy link
Copy Markdown

Why: the science this unlocks

Sorting is the one step in plate-based single-cell sequencing that usually has to
happen off-automation. A liquid handler can build libraries end to end, but the
sort itself, one gated cell per well or a targeted, enriched population, is
typically a manual hand-off. Bringing the sorter under PyLabRobot closes that gap:
the deck stages the plate, calls sort_to_plate, and finishes the prep. Walkaway
library prep becomes possible.

It also enables sorting for a target population: enrich a cell type, a
marker-positive subset, or live singlets before the assay. That is what gives
cell-type resolution to downstream measurements, for example cell-type-specific
epigenomics, where you want to read regulatory state in the exact cell type a
variant acts in rather than in a bulk average.

What this adds

A CellSorter (FACS) capability and a BD FACSMelody backend that implements it.

Capability (pylabrobot/capabilities/cell_sorting/)

  • CellSorter frontend: validation plus a sort_to_plate convenience method that
    sequences load-template, deposition, prime, sort, wait, clean.
  • CellSorterBackend ABC: get_status, load_template, set_deposition,
    prime, start_sort, wait_for_completion, abort, clean.
  • CellSorterChatterboxBackend for device-free testing.

BD FACSMelody (pylabrobot/becton_dickinson/facsmelody/), mirroring the
thermo_fisher/cytomat/ layout:

  • FACSMelodyDriver: the wire. Loads a decoded ProtocolMap and sends frames
    behind two independent safety switches.
  • FACSMelodyCellSorterBackend: turns CellSorter operations into the frames the
    map names.
  • A consumer-side ProtocolMap loader. The reverse-engineering toolkit that
    produces the map lives in a separate repo and is intentionally not vendored
    here; only the read side ships.

Docs: a cell-sorting capability page and a FACSMelody reverse-engineering
playbook (docs/facsmelody-re.md) that follows the PyLabRobot method (work to the
OEM command layer, sniff OEM-to-device traffic, correlate action to bytes, decode
framing, guarded replay over PyUSB/pyserial).

Safety and labeling

The Melody is a laser plus pressurized fluidics, so the backend is conservative by
default:

  • Dry-run by default. It builds and logs every frame and transmits nothing unless
    armed and the call is live.
  • Actuating commands (prime, sort, clean, deposition) additionally require an
    explicit opt-in; otherwise they raise.
  • A live run refuses to start against an incomplete ProtocolMap, so a half-mapped
    protocol cannot drive hardware.
  • Not yet hardware-validated. I have a FACSMelody with the plate-sort module on
    hand and will validate sort-to-plate; the code is labeled untested until then.
    Per-parameter byte encoders and response parsing are resolved during that
    validation, gated behind the coverage check so an unresolved map cannot run live.

The capability is kept small and event-oriented so a cytometry/acquisition
capability can reuse the same fluidics and gate-template primitives later; sorting
and acquisition stay separable so the interface can be aligned before either lands.

Testing

Device-free tests cover the capability sequencing, argument validation, the
actuation guard, and the incomplete-map refusal. ruff (format + check), mypy,
and the new tests pass locally.

Introduce a CellSorter (FACS) capability and a BD FACSMelody backend that
implements it, so a deck can run sort-to-plate as a normal device call. This
closes the one step in plate-based single-cell sequencing that usually has to
happen off-automation, and enables sorting for a target population before an
assay (cell-type resolution for downstream measurements).

Capability (pylabrobot/capabilities/cell_sorting):
- CellSorter frontend with validation and a sort_to_plate convenience method
- CellSorterBackend ABC (get_status, load_template, set_deposition, prime,
  start_sort, wait_for_completion, abort, clean)
- CellSorterChatterboxBackend for device-free testing
- Designed to sit alongside a future cytometry capability sharing the same
  fluidics and gate-template primitives

BD FACSMelody backend (pylabrobot/becton_dickinson/facsmelody):
- FACSMelodyDriver: the guarded wire. Dry-run by default; refuses to actuate
  without an explicit opt-in and refuses a live run against an incomplete
  ProtocolMap
- FACSMelodyCellSorterBackend: turns CellSorter operations into decoded frames
- Consumer-side ProtocolMap loader (the RE toolkit that produces the map stays
  in an external repo and is not vendored)
- Not yet hardware-validated; labeled untested until a bench run

Docs: a cell-sorting capability page and a FACSMelody reverse-engineering
playbook (docs/facsmelody-re.md) following the established PyLabRobot method.

Tests: device-free coverage of the capability sequencing, argument validation,
the actuation guard, and the incomplete-map refusal.
@di-omics
di-omics force-pushed the facsmelody-sorter branch from 594056f to 8ce782a Compare July 7, 2026 17:39
@di-omics

di-omics commented Jul 7, 2026

Copy link
Copy Markdown
Author

Heads up on the red checks: they're pre-existing on v1b1, not from this PR. v1b1's own recent pushes are already failing Unit Tests and Type checking, in modules this PR doesn't touch (e.g. legacy/storage/inheco/scila, agilent/biotek, ufactory/xarm6).

This PR's additions pass: all cell_sorting + facsmelody tests are green, no mypy errors in the new files, and lint + typos pass. Happy to rebase once v1b1 is green.

@rickwierenga

Copy link
Copy Markdown
Member

thanks for the PR!

were you able to verify this on the machine? In yesterday's issue you said that was a todo. If there's anything I can look at in the meantime lmk

Heads up on the red checks: they're pre-existing on v1b1, not from this PR. v1b1's own recent pushes are already failing Unit Tests and Type checking, in modules this PR doesn't touch (e.g. legacy/storage/inheco/scila, agilent/biotek, ufactory/xarm6).

yes exactly, dont worry about it :)

@di-omics

di-omics commented Jul 7, 2026

Copy link
Copy Markdown
Author

Not yet, still todo. Melody + plate sort are here, so next is decoding the ProtocolMap off FACSChorus, then guarded replay to a real sort-to-plate.

Does CellSorter fit how you'd want a sorter capability in v1b1 (the interface + where it lives)?

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