mcpField
A
alterlab-pylabrobot

alterlab-pylabrobot

github.com/alterlab-ieuOther7866 installsUpdated 5w ago
Repository

About alterlab-pylabrobot

alterlab-pylabrobot is a skill for PyLabRobot, a Python SDK for lab automation. It helps researchers write and debug liquid-handling and equipment workflows, with protocol code that can target a simulator or different hardware through backend changes.

Key features

  1. 01Write asynchronous liquid-handling workflows
  2. 02Define and track labware layouts
  3. 03Switch among hardware backends
  4. 04Simulate and visualize workflows
  5. 05Connect readers and other equipment

Use cases

  1. 01Simulate a liquid-handling protocol before running it
  2. 02Port workflows across robot vendors
  3. 03Configure labware and deck layouts
  4. 04Coordinate plate reading and temperature-control equipment

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/alterlab-ieu/alterlab-academic-skills --skill alterlab-pylabrobot

After installing, type/alterlab-pylabrobotin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

evals/
evals.json
references/
analytical-equipment.md
hardware-backends.md
liquid-handling.md
material-handling.md
resources.md
visualization.md

Details

From the project README

PyLabRobot

Overview

PyLabRobot (PLR) is a hardware-agnostic Python SDK for lab automation. Every device is a front end (LiquidHandler, PlateReader, HeaterShaker, ...) plus a backend for a specific instrument, so the same protocol code runs on a simulator, a Hamilton STAR, or an Opentrons OT-2 by swapping one backend line. All device calls are async and must be awaited inside an event loop (asyncio.run(main()), or directly in a Jupyter cell).

When to Use This Skill

  • Writing or debugging a liquid-handling protocol in Python for Hamilton STAR/STARlet/Vantage, Tecan EVO, or Opentrons OT-2
  • Simulating a protocol (chatterbox backend, tip/volume tracking, browser visualizer) before touching hardware
  • Defining deck layouts: carriers, tip racks, plates, troughs, tubes, and custom labware
  • Integrating plate readers, heater shakers, incubators, centrifuges, pumps, scales, or thermocyclers into one workflow
  • Porting a protocol from one robot vendor to another
Does NOT Trigger
ScenarioUse Instead
Writing an Opentrons OT-2/Flex protocol with the official Opentrons Python API (apiLevel, opentrons_simulate)alterlab-opentrons
Sending work to a remote cloud lab instead of running your own robotalterlab-ginkgo-cloud
Ordering protein binding/expression assays from the Adaptyv Bio foundryalterlab-adaptyv
Finding, writing, or publishing a human-readable protocol with a DOIalterlab-protocolsio

Core Capabilities

AreaWhat it coversReference
Liquid handlingaspirate, dispense, transfer, tips, multichannel moves, serial dilutions, error handlingreferences/liquid-handling.md
ResourcesDecks, carriers, plates, tip racks, troughs, indexing, tracking, saving layouts, custom labwarereferences/resources.md
Hardware backendsSTAR, Vantage, EVO, OT-2, chatterbox; switching backendsreferences/hardware-backends.md
Analytical equipmentPlate readers (CLARIOstar, BioTek, SpectraMax, Byonoy), scalesreferences/analytical-equipment.md
Material handlingHeater shakers, temperature controllers, incubators, centrifuges, pumps, thermocyclersreferences/material-handling.md
VisualizationBrowser visualizer, simulation-driven testingreferences/visualization.md

Quick Start (simulation)

import asyncio

from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends import LiquidHandlerChatterboxBackend  # STARBackend() on a real STAR
from pylabrobot.resources import (
    PLT_CAR_L5AC_A00,                   # plate carrier (5 sites)
    STARLetDeck,
    TIP_CAR_480_A00,                    # tip carrier (5 sites)
    cor_96_wellplate_360uL_Fb,
    hamilton_96_tiprack_1000uL_filter,
    set_tip_tracking,
    set_volume_tracking,
)


async def main():
    set_tip_tracking(True)      # catch missing tips and over-aspiration in simulation
    set_volume_tracking(True)

    lh = LiquidHandler(backend=LiquidHandlerChatterboxBackend(), deck=STARLetDeck())
    await lh.setup()
    try:
        # Labware goes into carrier sites; carriers go on deck rails.
        tip_car = TIP_CAR_480_A00(name="tip_carrier")
        tip_car[0] = tip_rack = hamilton_96_tiprack_1000uL_filter(name="tips_01")
        lh.deck.assign_child_resource(tip_car, rails=3)

        plt_car = PLT_CAR_L5AC_A00(name="plate_carrier")
        plt_car[0] = source = cor_96_wellplate_360uL_Fb(name="source")
        plt_car[1] = dest = cor_96_wellplate_360uL_Fb(name="dest")
        lh.deck.assign_child_resource(plt_car, rails=15)

        for well in source.get_all_items():
            well.tracker.set_liquids([(None, 300)])

        # 8-channel column copy: "A1:H1" is column 1 (8 wells), one tip per channel
        await lh.pick_up_tips(tip_rack["A1:H1"])
        await lh.aspirate(source["A1:H1"], vols=[100] * 8)
        await lh.dispense(dest["A1:H1"], vols=[100] * 8)
        await lh.discard_tips()         # to the deck's trash; return_tips() puts them back

        print(dest.get_well("A1").tracker.get_used_volume())  # 100.0
    finally:
        await lh.stop()


asyncio.run(main())

To run on hardware, replace the backend (STARBackend(), VantageBackend(), EVOBackend(), OpentronsOT2Backend(host="<robot IP>")) and the deck (STARDeck(), VantageDeck(size=1.3), EVO150Deck(), OTDeck()); the protocol body stays the same apart from deck positions.

API Rules That Prevent Most Errors

  • Indexing returns lists. plate["A1"] is a one-element list; plate["A1:H1"] is column 1 and plate["A1:A12"] is row A. Use plate.get_well("A1") or tip_rack.get_item("A1") for a single object (for example to reach .tracker).
  • Volumes are lists. vols=[100] for one channel, vols=[100] * 8 for eight; per-channel options (flow_rates, liquid_height, blow_out_air_volume) are lists too.
  • Tips. pick_up_tips(spots), then discard_tips() (trash), return_tips() (back to the rack), or drop_tips(spots) (explicit spots — it has no default).
  • transfer is one-to-many. lh.transfer(source.get_well("A1"), dest["A1:H1"], target_vols=[50] * 8) aspirates once and dispenses into each target with the channel-0 tip. source_vol= is the total volume, split across targets (equally or by ratios), not a per-target volume.
  • Labware names. Use the current lower-case factories (cor_96_wellplate_360uL_Fb); capitalised legacy names such as Cor_96_wellplate_360ul_Fb warn and will be removed.
  • Always stop() in finally: so USB/serial connections are released after an error.

Common Workflows

One-to-many dispense and a serial dilution
# 50 uL of diluent into each of A2..A5 from one source well (single channel)
await lh.pick_up_tips(tip_rack["A2"])
await lh.transfer(source.get_well("H12"), dest["A2:A5"], target_vols=[50] * 4)
await lh.discard_tips()

# 2-fold dilution along row A (A1 -> A5): move 50 uL to the next well and mix
await lh.pick_up_tips(tip_rack["A3"])
for col in range(1, 5):
    await lh.aspirate(dest[f"A{col}"], vols=[50])
    await lh.dispense(dest[f"A{col + 1}"], vols=[50])
    for _ in range(3):  # mix
        await lh.aspirate(dest[f"A{col + 1}"], vols=[40])
        await lh.dispense(dest[f"A{col + 1}"], vols=[40])
await lh.discard_tips()
Reading a plate
from pylabrobot.plate_reading import CLARIOstarBackend, PlateReader

reader = PlateReader(name="clariostar", size_x=0, size_y=0, size_z=0,
                     backend=CLARIOstarBackend())   # needs pylabrobot[ftdi]
await reader.setup()
await reader.open()
reader.assign_child_resource(dest)                   # or move the plate there with the robot's gripper
await reader.close()
result = await reader.read_absorbance(wavelength=450, use_new_return_type=True)
od450 = result[0]["data"]                            # 8 x 12 nested list
await reader.stop()

PlateReader has no temperature method; readers that support heating expose it on the backend (for example await reader.backend.set_temperature(37) on BioTek and Molecular Devices backends). See references/analytical-equipment.md for other readers and for scales.

Best Practices

  1. Simulate first. Run the whole protocol on LiquidHandlerChatterboxBackend with tip and volume tracking on, and watch it in the Visualizer, before the first hardware run.
  2. Dry-run on hardware. Do a first physical run with water or without liquid, at reduced volumes, and keep a hand near the stop button.
  3. Keep layouts in files. Save the deck with lh.deck.save("deck.json") and commit it with the protocol; record the pylabrobot version.
  4. Check labware definitions. Verify geometry for custom or rarely used labware before trusting aspiration heights.
  5. Start slow devices early. Heating and incubator set points take minutes; do liquid handling while they settle.
  6. Official docs. https://docs.pylabrobot.org (user guide and API), https://github.com/PyLabRobot/pylabrobot, forum https://discuss.pylabrobot.org.

Troubleshooting

SymptomLikely cause
TypeError: Resources must be Containers, got [[Well(...)]]A list was passed where one well is expected (transfer source); use plate.get_well("A1")
TypeError: drop_tips() missing ... 'tip_spots'Use discard_tips() or pass explicit spots
NoTipError / HasTipError with tracking onThe protocol reuses a tip spot or picks up while holding tips; check tip bookkeeping
RuntimeError: ... is not installed. Install with: pip install pylabrobot[...]Install the connection extra named in the message
ImportError for pylabrobot.temperature_control, pylabrobot.incubation, Trough_100mlOutdated names; see references/material-handling.md and references/resources.md for the 0.2.2 modules and labware

Part of the AlterLab Academic Skills suite.

Comments

Markdown supported