Getting started with liquid handling on a Hamilton STAR(let)#
In this notebook, you will learn how to use PyLabRobot to move water from one range of wells to another.
Note: before running this notebook, you should have:
Installed PyLabRobot and the USB driver as described in the installation guide.
Connected the Hamilton to your computer using the USB cable.
Video of what this code does:
Setting up a connection with the robot#
Start by importing the LiquidHandler
class, which will serve as a front end for all liquid handling operations.
Backends serve as communicators between LiquidHandler
s and the actual hardware. Since we are using a Hamilton STAR, we also import the STAR
backend.
%load_ext autoreload
%autoreload 2
from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends import STAR
In addition, import the STARLetDeck
, which represents the deck of the Hamilton STAR.
from pylabrobot.resources.hamilton import STARLetDeck
Create a new liquid handler using STAR
as its backend.
backend = STAR()
lh = LiquidHandler(backend=backend, deck=STARLetDeck())
The final step is to open communication with the robot. This is done using the setup()
method.
await lh.setup()
Creating the deck layout#
Now that we have a LiquidHandler
instance, we can define the deck layout.
The layout in this tutorial will contain five sets of standard volume tips with filter, 1 set of 96 1mL wells, and tip and plate carriers on which these resources are positioned.
Start by importing the relevant objects and variables from the PyLabRobot package. This notebook uses the following resources:
TIP_CAR_480_A00
tip carrierPLT_CAR_L5AC_A00
plate carrierHTF
tips
from pylabrobot.resources import (
TIP_CAR_480_A00,
PLT_CAR_L5AC_A00,
Cor_96_wellplate_360ul_Fb,
HTF,
)
Then create a tip carrier named tip carrier
, which will contain tip rack at all 5 positions. These positions can be accessed using tip_car[x]
, and are 0 indexed.
tip_car = TIP_CAR_480_A00(name="tip carrier")
tip_car[0] = HTF(name="tips_01")
Use assign_child_resources()
to assign the tip carrier to the deck of the liquid handler. All resources contained by this carrier will be assigned automatically.
In the rails
parameter, we can pass the location of the tip carrier. The locations of the tips will automatically be calculated.
lh.deck.assign_child_resource(tip_car, rails=3)
Repeat this for the plates.
plt_car = PLT_CAR_L5AC_A00(name="plate carrier")
plt_car[0] = Cor_96_wellplate_360ul_Fb(name="plate_01")
lh.deck.assign_child_resource(plt_car, rails=15)
Let’s look at a summary of the deck layout using summary()
.
lh.summary()
Rail Resource Type Coordinates (mm)
===============================================================================================
(3) ├── tip carrier TipCarrier (145.000, 063.000, 100.000)
│ ├── tips_01 TipRack (162.900, 145.800, 131.450)
│ ├── <empty>
│ ├── <empty>
│ ├── <empty>
│ ├── <empty>
│
(15) ├── plate carrier PlateCarrier (415.000, 063.000, 100.000)
│ ├── plate_01 Plate (433.000, 146.000, 187.150)
│ ├── <empty>
│ ├── <empty>
│ ├── <empty>
│ ├── <empty>
│
(32) ├── trash Trash (800.000, 190.600, 137.100)
Picking up tips#
Picking up tips is as easy as querying the tips from the tiprack.
tiprack = lh.deck.get_resource("tips_01")
await lh.pick_up_tips(tiprack["A1:C1"])
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Sent command: C0TTid0004tt01tf1tl0871tv12500tg3tu0
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Received response: C0TTid0004er00/00
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Sent command: C0TPid0005xp01629 01629 01629 00000&yp1458 1368 1278 0000&tm1 1 1 0&tt01tp2244tz2164th2450td0
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Received response: C0TPid0005er00/00
Aspirating and dispensing#
Aspirating and dispensing work similarly to picking up tips: where you use booleans to specify which tips to pick up, with aspiration and dispensing you use floats to specify the volume to aspirate or dispense in \(\mu L\).
The cells below move liquid from wells 'A1:C1'
to 'D1:F1'
using channels 1, 2, and 3 using the aspirate()
and dispense()
methods.
plate = lh.deck.get_resource("plate_01")
await lh.aspirate(plate["A1:C1"], vols=[100.0, 50.0, 200.0])
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Sent command: C0ASid0006at0&tm1 1 1 0&xp04330 04330 04330 00000&yp1460 1370 1280 0000&th2450te2450lp1931 1931 1931&ch000 000 000&zl1881 1881 1881&po0100 0100 0100&zu0032 0032 0032&zr06180 06180 06180&zx1831 1831 1831&ip0000 0000 0000&it0 0 0&fp0000 0000 0000&av01072 00551 02110&as1000 1000 1000&ta000 000 000&ba0000 0000 0000&oa000 000 000&lm0 0 0&ll1 1 1&lv1 1 1&zo000 000 000&ld00 00 00&de0020 0020 0020&wt10 10 10&mv00000 00000 00000&mc00 00 00&mp000 000 000&ms1000 1000 1000&mh0000 0000 0000&gi000 000 000&gj0gk0lk0 0 0&ik0000 0000 0000&sd0500 0500 0500&se0500 0500 0500&sz0300 0300 0300&io0000 0000 0000&il00000 00000 00000&in0000 0000 0000&
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Received response: C0ASid0006er00/00
After the liquid has been aspirated, dispense it in the wells below. Note that while we specify different wells, we are still using the same channels. This is needed because only these channels contain liquid, of course.
await lh.dispense(plate["D1:F1"], vols=[100.0, 50.0, 200.0])
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Sent command: C0DSid0007dm2 2 2&tm1 1 1 0&xp04330 04330 04330 00000&yp1190 1100 1010 0000&zx1871 1871 1871&lp2321 2321 2321&zl1881 1881 1881&po0100 0100 0100&ip0000 0000 0000&it0 0 0&fp0000 0000 0000&zu0032 0032 0032&zr06180 06180 06180&th2450te2450dv01072 00551 02110&ds1200 1200 1200&ss0050 0050 0050&rv000 000 000&ta000 000 000&ba0000 0000 0000&lm0 0 0&dj00zo000 000 000&ll1 1 1&lv1 1 1&de0020 0020 0020&wt00 00 00&mv00000 00000 00000&mc00 00 00&mp000 000 000&ms0010 0010 0010&mh0000 0000 0000&gi000 000 000&gj0gk0
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Received response: C0DSid0007er00/00
Let’s move the liquid back to the original wells.
await lh.aspirate(plate["D1:F1"], vols=[100.0, 50.0, 200.0])
await lh.dispense(plate["A1:C1"], vols=[100.0, 50.0, 200.0])
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Sent command: C0ASid0008at0&tm1 1 1 0&xp04330 04330 04330 00000&yp1190 1100 1010 0000&th2450te2450lp1931 1931 1931&ch000 000 000&zl1881 1881 1881&po0100 0100 0100&zu0032 0032 0032&zr06180 06180 06180&zx1831 1831 1831&ip0000 0000 0000&it0 0 0&fp0000 0000 0000&av01072 00551 02110&as1000 1000 1000&ta000 000 000&ba0000 0000 0000&oa000 000 000&lm0 0 0&ll1 1 1&lv1 1 1&zo000 000 000&ld00 00 00&de0020 0020 0020&wt10 10 10&mv00000 00000 00000&mc00 00 00&mp000 000 000&ms1000 1000 1000&mh0000 0000 0000&gi000 000 000&gj0gk0lk0 0 0&ik0000 0000 0000&sd0500 0500 0500&se0500 0500 0500&sz0300 0300 0300&io0000 0000 0000&il00000 00000 00000&in0000 0000 0000&
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Received response: C0ASid0008er00/00
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Sent command: C0DSid0009dm2 2 2&tm1 1 1 0&xp04330 04330 04330 00000&yp1460 1370 1280 0000&zx1871 1871 1871&lp2321 2321 2321&zl1881 1881 1881&po0100 0100 0100&ip0000 0000 0000&it0 0 0&fp0000 0000 0000&zu0032 0032 0032&zr06180 06180 06180&th2450te2450dv01072 00551 02110&ds1200 1200 1200&ss0050 0050 0050&rv000 000 000&ta000 000 000&ba0000 0000 0000&lm0 0 0&dj00zo000 000 000&ll1 1 1&lv1 1 1&de0020 0020 0020&wt00 00 00&mv00000 00000 00000&mc00 00 00&mp000 000 000&ms0010 0010 0010&mh0000 0000 0000&gi000 000 000&gj0gk0
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Received response: C0DSid0009er00/00
Dropping tips#
Finally, you can drop tips anywhere on the deck by using the discard_tips()
method.
await lh.drop_tips(tiprack["A1:C1"])
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Sent command: C0TRid0010xp01629 01629 01629 00000&yp1458 1368 1278 0000&tm1 1 1 0&tt01tp1314tz1414th2450ti0
INFO:pylabrobot.liquid_handling.backends.hamilton.STAR:Received response: C0TRid0010er00/00kz381 356 365 000 000 000 000 000vz303 360 368 000 000 000 000 000
await lh.stop()
WARNING:root:Closing connection to USB device.