Skip to content

OpentronsOT2Backend: support the 8-channel pipette#1135

Draft
BioCam wants to merge 3 commits into
PyLabRobot:mainfrom
BioCam:ot2-head8-channels
Draft

OpentronsOT2Backend: support the 8-channel pipette#1135
BioCam wants to merge 3 commits into
PyLabRobot:mainfrom
BioCam:ot2-head8-channels

Conversation

@BioCam

@BioCam BioCam commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

The backend modeled every mount as a single channel, so the OT-2 8-channel pipette could not be driven correctly. This models a multi mount as 8 channels - anchored at channel 0 (back, row A) and filling toward row H at the 9 mm nozzle pitch - and issues one wire command per column for multi-channel pickup, aspirate, and dispense, matching the hardware, which acts on a whole column at once rather than channel by channel. Single-channel pipettes are unchanged: they stay one channel and one command per operation.

Tests cover the channel model (mount -> channel count, channel-0 anchoring) and the per-column wire grouping, run as a dry run against the chatterbox so no hardware or ot_api is needed.

Stacked on #1132, whose OpentronsOT2ChatterboxBackend is the dry-run harness these tests use. The self-contained change here is the three commits above that base.

🤖 Generated with Claude Code

BioCam and others added 3 commits July 8, 2026 08:56
First slice of building the 8-channel head into the backend itself. Adds the
channel model: _pipette_channel_count (8 for a multi, 1 for a single), _channel_map
(per-mount channel blocks, left then right), num_channels derived from it, and
_pipette_id_for_channel routed through it. A multi mount now reports 8 channels
(0 = back / row A) instead of 1; single-channel setups are unchanged, so the
characterization net and the chatterbox tests stay green.

Per-column command issuing and the pickup geometry guard build on this next.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ep 2)

Routes pick_up_tips / aspirate / dispense / drop_tips through a new
_resolve_pipette_and_primary(ops, use_channels): it maps the channels to the
single mount they address (rejecting a mix of mounts) and picks the primary op
(lowest nozzle). A multi column op now issues exactly one ot_api command at the
primary well while PLR tracks all 8 channels. can_pick_up_tip is likewise routed
through the channel map so the multi's channels 1-7 are accepted (previously
hardcoded channel 0 = left, 1 = right).

The single-channel _get_*_pipette helpers stay - OpentronsOT2Simulator still uses
them. Verified in simulation through the chatterbox: one pick_up_tip / one
aspirate_in_place / one dispense_in_place for a full 8-channel column, all eight
channels tracked, and a cross-mount selection rejected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Remove test_multi_mount_reports_eight_channels: num_channels==9 is already
  pinned by test_channel_map_multi_mount_is_eight_channels and exercised by the
  8-channel column test.
- Remove the chatterbox-vs-simulator differential: both backends share the PLR
  frontend that does the tracking, so they can only diverge by raising, which the
  full-protocol recording test already guards.
- Strip tautological assertEqual(offset_x, offset_x) (x3 in each of test_tip_pick_up
  and test_tip_drop) and a duplicate well_name assert in test_tip_drop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant