Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
734ad51
Phase 0: Update CLAUDE.md for v1b1 Tecan EVO migration
Robert-Keyser-Calico Mar 28, 2026
81e68cc
Phase 1: Extract Tecan EVO firmware wrappers to pylabrobot/tecan/evo/
Robert-Keyser-Calico Mar 28, 2026
0590640
Phase 2: Add TecanEVODriver for USB I/O and command protocol
Robert-Keyser-Calico Mar 28, 2026
11767a9
Phase 3: Add EVOPIPBackend for syringe LiHa pipetting
Robert-Keyser-Calico Mar 28, 2026
805262d
Phase 4: Add AirEVOPIPBackend for Air LiHa (ZaapMotion)
Robert-Keyser-Calico Mar 28, 2026
01516be
Phase 5+6: Add EVORoMaBackend and TecanEVO device composition
Robert-Keyser-Calico Mar 28, 2026
f6f46e7
Add hardware testing scripts, checklist, and jog/teach tool
Robert-Keyser-Calico Mar 28, 2026
aebb2ce
Add web-based jog UI with keyboard controls and teach mode
Robert-Keyser-Calico Mar 28, 2026
dbea017
Fix jog_ui.py: add missing labware imports in init_evo()
Robert-Keyser-Calico Mar 28, 2026
cb66a1a
Add labware_library.py from air-liha-backend branch
Robert-Keyser-Calico Mar 28, 2026
d59ad44
Add ZaapDiTi 50uL liquid class entries from air-liha-backend
Robert-Keyser-Calico Mar 28, 2026
dca319b
Add PR cleanup checklist for both branches
Robert-Keyser-Calico Mar 28, 2026
e43ce28
Update v1b1 migration plan with completion status and PR cleanup
Robert-Keyser-Calico Mar 28, 2026
a37a937
Add unit tests for PIP, Air PIP, and RoMa backends
Robert-Keyser-Calico Mar 28, 2026
fa49cb6
Add tips_off.py using v1b1 driver/firmware directly
Robert-Keyser-Calico Mar 30, 2026
fe9c41a
Fix slow reconnect: skip RoMa PIA when already initialized
Robert-Keyser-Calico Mar 30, 2026
495ef25
Jog UI: add command logging, busy lock, and command details
Robert-Keyser-Calico Mar 30, 2026
5cdf357
Fix position display glitches: add USB mutex lock
Robert-Keyser-Calico Mar 30, 2026
6664f61
Jog UI: add labware inspector with full properties
Robert-Keyser-Calico Mar 30, 2026
f5a51ca
Jog UI: add Connect/Disconnect button, start without hardware
Robert-Keyser-Calico Mar 30, 2026
cc98f48
Fix labware endpoint: skip non-resource carrier site entries
Robert-Keyser-Calico Mar 30, 2026
1deef21
Jog UI: add status lamp and motor power controls
Robert-Keyser-Calico Mar 30, 2026
8867ceb
Fix labware discovery: use recursive children walk, not sites
Robert-Keyser-Calico Mar 30, 2026
ab4f0e5
Fix Z jog direction: - = down (toward deck), + = up
Robert-Keyser-Calico Mar 30, 2026
e6f0fd5
Use taught Z positions directly for aspirate/dispense
Robert-Keyser-Calico Mar 30, 2026
e513b72
Adjust aspirate/dispense Z for mounted tip length
Robert-Keyser-Calico Mar 30, 2026
60a069e
Add per-labware X/Y calibration offsets
Robert-Keyser-Calico Mar 30, 2026
f8e1a30
Fix _is_initialized: cast REE0 response to str (may be int)
Robert-Keyser-Calico Mar 30, 2026
5e223ac
Add coordinate logging to all Air PIP operations
Robert-Keyser-Calico Mar 30, 2026
ab21e1d
Widen tip AGT search range and add debug output
Robert-Keyser-Calico Mar 30, 2026
d9c2c7e
Show full X/Y coordinates vs taught positions before tip pickup
Robert-Keyser-Calico Mar 30, 2026
355c673
Add firmware feature enhancements: wrappers, ZaapMotion abstraction, …
Robert-Keyser-Calico Mar 30, 2026
8b3082f
Update hardware testing checklist with completed tests
Robert-Keyser-Calico Mar 30, 2026
c59b3cf
Move firmware feature plans to completed-plans, add system-level futu…
Robert-Keyser-Calico Mar 30, 2026
e867805
Fix lint and format: remove unused import, reformat, fix mypy indexing
Robert-Keyser-Calico Mar 31, 2026
bf5f46e
Fix unused import, update _typos.toml for Tecan firmware commands
Robert-Keyser-Calico Mar 31, 2026
96f1062
Add Tecan manuals, USB captures, and PDFs to .gitignore
Robert-Keyser-Calico Mar 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ pyhamilton/LAY-BACKUP
.ipynb_checkpoints
*.egg-info
*.log
keyser-testing/Tecan Manuals/
keyser-testing/evoware-usb-capture-*/
keyser-testing/evoware-pktmon-capture-*/
keyser-testing/*.pdf
build/lib

myenv
Expand Down
15 changes: 14 additions & 1 deletion _typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,21 @@ mis = "mis"
RHE = "RHE"
"ASEND" = "ASEND"
caf = "caf"
# Tecan firmware command abbreviations
ALO = "ALO"
SOM = "SOM"
SHS = "SHS"
SHW = "SHW"
AZMA = "AZMA"
MCH = "MCH"
AAS = "AAS"
AER = "AER"

[files]
extend-exclude = [
"*.ipynb"
"*.ipynb",
"keyser-testing/Tecan Manuals/",
"keyser-testing/evoware-usb-capture-aspirate-dispense/",
"keyser-testing/evoware-usb-capture-multidispense/",
"keyser-testing/evoware-pktmon-capture-20260327/",
]
105 changes: 104 additions & 1 deletion claude.md
Original file line number Diff line number Diff line change
@@ -1 +1,104 @@
pretend you are Jeff Dean
# PyLabRobot - Lab Automation Integration

## Project Overview
PyLabRobot is a hardware-agnostic Python library for lab automation. We are integrating several instruments for automated liquid handling, bulk dispensing, and robotic plate movement.

## Our Lab Equipment

### Tecan EVO 150 (Liquid Handler)
- **Backend**: `EVOBackend` from `pylabrobot.liquid_handling.backends.tecan`
- **Frontend**: `LiquidHandler` from `pylabrobot.liquid_handling`
- **Deck**: `EVO150Deck` (45 rails, 1315 x 780 x 765 mm)
- **Connection**: USB (VID=0x0C47, PID=0x4000)
- **Install**: `pip install -e ".[usb]"`

#### Default Deck Components
- **Plate carrier**: `MP_3Pos` (Tecan part no. 10612604) - 3-position microplate carrier
- Import: `from pylabrobot.resources.tecan.plate_carriers import MP_3Pos`
- **Tip carrier**: `DiTi_3Pos` (Tecan part no. 10613022) - 3-position DiTi carrier
- Import: `from pylabrobot.resources.tecan.tip_carriers import DiTi_3Pos`
- **Tips**: `DiTi_50ul_SBS_LiHa` - 50uL disposable tips for LiHa
- Import: `from pylabrobot.resources.tecan.tip_racks import DiTi_50ul_SBS_LiHa`
- **Plates**: `Eppendorf_96_wellplate_250ul_Vb` - Eppendorf twin.tec 96-well (250uL, V-bottom)
- Import: `from pylabrobot.resources.eppendorf.plates import Eppendorf_96_wellplate_250ul_Vb`

### Thermo Scientific Multidrop Combi (Bulk Dispenser)
- **Backend**: `MultidropCombiBackend` from `pylabrobot.bulk_dispensers.thermo_scientific.multidrop_combi`
- **Frontend**: `BulkDispenser` from `pylabrobot.bulk_dispensers`
- **Connection**: RS232 via USB adapter (specify COM port explicitly)
- **Serial config**: 9600 baud, 8N1, XON/XOFF
- **Install**: `pip install -e ".[serial]"`
- **Plate helpers**: `plate_to_type_index()`, `plate_to_pla_params()` for PLR plate → Multidrop mapping
- **Protocol docs**: `C:\Users\keyser\source\repos\keyser-sila-testing\documentation\Multidrop Combi Remote Control Command Sets (1).pdf`

### UFACTORY xArm 6 (Robotic Arm)
- **Backend**: `XArm6Backend` from `pylabrobot.arms.xarm6.xarm6_backend`
- **Frontend**: `SixAxisArm` from `pylabrobot.arms.six_axis`
- **Connection**: Ethernet (IP address)
- **Install**: `pip install xarm-python-sdk`

## Architecture Patterns

### Legacy Architecture (main branch)
Each device category follows this pattern:
- **Frontend class** (`Machine` subclass) - thin delegation layer with `@need_setup_finished` guards
- **Abstract backend** (`MachineBackend` subclass with `ABCMeta`) - defines the device-type interface
- **Concrete backend** - implements the abstract backend for a specific instrument
- **Chatterbox backend** - prints operations for testing without hardware

Key base classes:
- `pylabrobot/machines/backend.py` - `MachineBackend(SerializableMixin, ABC)`
- `pylabrobot/machines/machine.py` - `Machine(SerializableMixin, ABC)` + `need_setup_finished` decorator

### v1b1 Architecture (v1b1 branch)
New capability-based architecture replacing the monolithic backend model:
- **Driver** (`pylabrobot/device.py`) - owns I/O, connection lifecycle (`setup()/stop()`)
- **CapabilityBackend** (`pylabrobot/capabilities/capability.py`) - protocol translation for one concern
- **Capability** - user-facing API with validation, tip tracking, etc.
- **Device** - owns Driver + list of Capabilities, orchestrates lifecycle
- **BackendParams** - typed dataclasses replacing `**kwargs`

Key interfaces for Tecan EVO migration:
- `PIPBackend` (`pylabrobot/capabilities/liquid_handling/pip_backend.py`) - independent channel pipetting
- `GripperArmBackend` (`pylabrobot/arms/backend.py`) - plate handling arms
- Reference implementation: Hamilton STAR at `pylabrobot/hamilton/liquid_handlers/star/`

## Branch Strategy

| Branch | Base | Purpose |
|--------|------|---------|
| `air-liha-backend` | `main` | Legacy Air LiHa backend (WIP, may PR to main) |
| `v1b1-tecan-evo` | `origin/v1b1` | Native v1b1 EVO backend (syringe + Air LiHa + RoMa) |
| `keyser-combined` | `main` | Combined xArm + Multidrop for testing |
| `keyser-multidrop-testing` | `main` | Multidrop Combi backend |
| `keyser-xarm-testing` | `main` | xArm 6 backend |

### v1b1 Tecan EVO File Structure
```
pylabrobot/tecan/evo/
driver.py # TecanEVODriver(Driver) — USB I/O + command protocol
pip_backend.py # EVOPIPBackend(PIPBackend) — syringe LiHa
air_pip_backend.py # AirEVOPIPBackend(EVOPIPBackend) — Air LiHa
roma_backend.py # EVORoMaBackend(GripperArmBackend) — RoMa plate handling
evo.py # TecanEVO(Resource, Device) — composite device
params.py # BackendParams dataclasses
errors.py # TecanError
firmware/ # Extracted firmware command wrappers (LiHa, RoMa, EVOArm)
```

Legacy EVO stays at: `pylabrobot/legacy/liquid_handling/backends/tecan/`

## Air LiHa (ZaapMotion) Key Facts
- ZaapMotion controllers boot into bootloader mode after power cycle
- Must send `T2{0-7}X` (exit boot) + 33 motor config commands per tip before PIA
- Plunger conversion: 106.4 steps/uL (vs 3 for syringe), 213 speed factor (vs 6)
- Force mode: `SFR133120`+`SFP1` before plunger ops, `SFR3752`+`SDP1400` after
- Investigation details: `keyser-testing/AirLiHa_Investigation.md`

## Development
- Venv: `.venv/` in project root
- Install all deps: `pip install -e ".[serial,usb]"`
- Tests: `python -m pytest pylabrobot/bulk_dispensers/ -v`
- Lint: `ruff check`, Format: `ruff format`, Types: `mypy pylabrobot --check-untyped-defs`
- Abstract interfaces use microliters (float); backends convert to instrument-specific units
- Tecan Z coordinates: 0 = deck surface, z_range (~2100) = top/home
91 changes: 91 additions & 0 deletions keyser-testing/PR_cleanup_checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# PR Cleanup Checklist

## Before submitting PRs, strip `keyser-testing/` and keep only `pylabrobot/` changes.

---

## `air-liha-backend` → PR to `main`

### Files to INCLUDE in PR:
- [x] `pylabrobot/liquid_handling/backends/tecan/air_evo_backend.py` (new)
- [x] `pylabrobot/liquid_handling/backends/tecan/__init__.py` (1 line added)
- [x] `pylabrobot/liquid_handling/liquid_classes/tecan.py` (8 entries appended)

### Files to EXCLUDE from PR:
- [ ] `keyser-testing/` — entire directory (test scripts, USB captures, manuals, DLLs)
- [ ] `claude.md` — local project instructions
- [ ] `.claude/` — Claude Code settings
- [ ] Any `taught_positions.json`, `labware_edits.json`

### Pre-PR checks:
- [ ] `ruff check pylabrobot/liquid_handling/backends/tecan/air_evo_backend.py`
- [ ] `ruff format --check pylabrobot/liquid_handling/backends/tecan/air_evo_backend.py`
- [ ] `mypy pylabrobot/liquid_handling/backends/tecan/air_evo_backend.py --check-untyped-defs`
- [ ] Existing EVO tests still pass: `pytest pylabrobot/liquid_handling/backends/tecan/EVO_tests.py`
- [ ] Remove debug print statements from `air_evo_backend.py`
- [ ] Remove temporary X offset (`x += 60`) or document as TODO
- [ ] Add docstring to `AirEVOBackend` explaining ZaapMotion requirements

### How to create clean PR branch:
```bash
git checkout air-liha-backend
git checkout -b air-liha-pr
git rm -r --cached keyser-testing/
git rm --cached claude.md
echo "keyser-testing/" >> .gitignore
git commit -m "Remove test artifacts for clean PR"
```

---

## `v1b1-tecan-evo` → PR to `v1b1`

### Files to INCLUDE in PR:
- [x] `pylabrobot/tecan/__init__.py` (new)
- [x] `pylabrobot/tecan/evo/__init__.py` (new)
- [x] `pylabrobot/tecan/evo/driver.py` (new)
- [x] `pylabrobot/tecan/evo/pip_backend.py` (new)
- [x] `pylabrobot/tecan/evo/air_pip_backend.py` (new)
- [x] `pylabrobot/tecan/evo/roma_backend.py` (new)
- [x] `pylabrobot/tecan/evo/evo.py` (new)
- [x] `pylabrobot/tecan/evo/errors.py` (new)
- [x] `pylabrobot/tecan/evo/firmware/__init__.py` (new)
- [x] `pylabrobot/tecan/evo/firmware/arm_base.py` (new)
- [x] `pylabrobot/tecan/evo/firmware/liha.py` (new)
- [x] `pylabrobot/tecan/evo/firmware/roma.py` (new)
- [x] `pylabrobot/tecan/evo/tests/__init__.py` (new)
- [x] `pylabrobot/tecan/evo/tests/driver_tests.py` (new)
- [x] `pylabrobot/legacy/liquid_handling/liquid_classes/tecan.py` (8 entries appended)

### Files to EXCLUDE from PR:
- [ ] `keyser-testing/` — entire directory
- [ ] `claude.md` — local project instructions
- [ ] `.claude/` — Claude Code settings

### Pre-PR checks:
- [ ] `ruff check pylabrobot/tecan/`
- [ ] `ruff format --check pylabrobot/tecan/`
- [ ] `mypy pylabrobot/tecan/ --check-untyped-defs`
- [ ] `pytest pylabrobot/tecan/evo/tests/ -v`
- [ ] Legacy EVO tests still pass: `pytest pylabrobot/legacy/liquid_handling/backends/tecan/EVO_tests.py`
- [ ] Remove any debug print statements
- [ ] Add unit tests for pip_backend, air_pip_backend, roma_backend
- [ ] Verify `TecanEVO` constructs correctly with all config combinations

### How to create clean PR branch:
```bash
git checkout v1b1-tecan-evo
git checkout -b v1b1-tecan-evo-pr
git rm -r --cached keyser-testing/
git rm --cached claude.md
echo "keyser-testing/" >> .gitignore
git commit -m "Remove test artifacts for clean PR"
```

---

## Common notes:
- `keyser-testing/` stays on our fork branches for ongoing development/testing
- The PR branches are ephemeral — created just for the PR, then deleted after merge
- The `labware_library.py` is local to our lab — NOT included in PRs
- USB captures, manuals, DLLs, and EVOware logs are investigation artifacts — NOT for upstream
Loading
Loading