UniteLabs

CO-RE 96 Head

Use the CO-RE 96 head on the Hamilton Vantage.

The Vantage CO-RE 96 head is a pipetting tool with 96 channels that picks up tips and pipettes with all channels at once. It is mounted on the Vantage arm. For movement in the X direction, the head uses the arm's X motor. The head has its own Y and Z drives. The position of the head is the position of the bottom of the A1 channel (when no tips are picked up) or of the bottom of the A1 tip, in the standard deck coordinate system.

Prerequisites

  • Hamilton Vantage with a CO-RE 96 head
  • A Hamilton Vantage connector >= v0.7.0 and UniteLabs liquid handling SDK >= v0.41.0
  • Vantage waste configured, with the head's discard and home location set (See CO-RE 96 Head Waste)
  • Basic understanding of the liquid handler class and its modules (See liquid handling and modules)

Connect to the Device

The head is available as vantage.core96 once the device is configured and initialized. Configure the waste first, because initialize() ejects any tips the head holds at its discard location. This example uses a 2T waste on track 35. The 2T waste does not change the head's default discard location, Vector(x=-70, y=180.2, z=250.0), so the head needs no extra configuration (see CO-RE 96 Head Waste for other waste types and locations).

from unitelabs.labware import Vector
from unitelabs.labware.hamilton.waste import Hamilton2TEjectionPlate
from unitelabs.liquid_handling.hamilton import Vantage, WasteType

vantage = Vantage(name="Hamilton Vantage")

# 2T waste on track 35
config = await vantage.get_configuration()
config.waste_type = WasteType.TWO_T
config.waste_track = 35
config.ejection_plate = Hamilton2TEjectionPlate.PIP_1000UL
await vantage.configure()

await vantage.initialize()
initialize() drops any tips the head still holds at the discard location. Check the configured discard location of the CO-RE 96 head before the first run.

Arrange the Deck

All examples on this page use the same deck. The tip carrier holds two racks of 300 µL tips, two racks of 1000 µL tips, and a CO-RE tip support for shifted pick-up. The plate carrier holds a trough with 200 mL of water, a trough with magnetic beads, and a 96 deep-well plate (2.2 mL per well).

from unitelabs.labware import Liquid, PredefinedLiquids, StandardTrough
from unitelabs.labware.hamilton import (
    PLT_CAR_L5MD_A00,
    TIP_CAR_480_A00,
    HamiltonCore96TipSupport_1000,
    HamiltonLiquidClasses,
    HamiltonPlate_2200ul_96DWP_Square_UBottom,
    HamiltonTip_300,
    HamiltonTip_1000,
    HamiltonTipRack_300,
    HamiltonTipRack_1000,
)

tip_carrier = TIP_CAR_480_A00(identifier="tip_carrier")
tip_carrier[0] = tip_rack_300_1 = HamiltonTipRack_300(identifier="tip_rack_300_1", filled_with=HamiltonTip_300())
tip_carrier[1] = tip_rack_300_2 = HamiltonTipRack_300(identifier="tip_rack_300_2", filled_with=HamiltonTip_300())
tip_carrier[2] = tip_rack_1000_1 = HamiltonTipRack_1000(identifier="tip_rack_1000_1", filled_with=HamiltonTip_1000())
tip_carrier[3] = tip_rack_1000_2 = HamiltonTipRack_1000(identifier="tip_rack_1000_2", filled_with=HamiltonTip_1000())
tip_carrier[4] = tip_support_1000 = HamiltonCore96TipSupport_1000(identifier="tip_support_1000")

plate_carrier = PLT_CAR_L5MD_A00(identifier="plate_carrier")
plate_carrier[0] = water_trough = StandardTrough(identifier="water_trough")
plate_carrier[1] = bead_trough = StandardTrough(identifier="bead_trough")
plate_carrier[2] = plate = HamiltonPlate_2200ul_96DWP_Square_UBottom(identifier="plate")
water_trough.containers[0].add_liquid(PredefinedLiquids.WATER, 200_000)  # 200 mL
bead_trough.containers[0].add_liquid(Liquid(name="Magnetic beads"), 100_000)  # 100 mL

vantage.deck.add(tip_carrier, track=7)
vantage.deck.add(plate_carrier, track=20)
print(vantage.deck.summary())

Tip Handling

Pick Up, Put Down, and Discard Tips

pick_up_tips_from() picks up a whole rack of tips with all 96 channels of the head. put_down_tips_to() returns the tips to a rack, and discard_tips() ejects them at the configured discard location. The tip type is read from the tips in the rack.

await vantage.core96.pick_up_tips_from(rack=tip_rack_300_1)
await vantage.core96.put_down_tips_to(rack=tip_rack_300_1)

await vantage.core96.pick_up_tips_from(rack=tip_rack_300_1)
await vantage.core96.discard_tips()

Pass the tip class instead of a rack and the head uses the next matching rack on the deck.

await vantage.core96.pick_up_tips_from_anywhere(tip_type=HamiltonTip_300)
await vantage.core96.put_down_tips_to_anywhere(tip_type=HamiltonTip_300)

Both calls need a full rack arrangement of that tip type. pick_up_tips_from_anywhere() raises MissingError when no rack with tips is left, and put_down_tips_to_anywhere() raises it when no rack with free spots is left. They take neither well_offset nor offset. Pass an explicit rack when you need one.

A partially used rack is picked up without any extra arguments.

Pass an offset to adjust the pick-up or discard location in mm, for example to eject over a different part of the waste:

await vantage.core96.discard_tips(offset=Vector(x=0, y=20, z=0))
drop_tips() releases the tips at the current position instead of the waste. The tips fall wherever the head is at the moment.

Shifted Tip Pick-Up

Shifted pick-up lets you address only certain columns, rows, or a rectangular section of a tip rack.

Use well_offset=(row, col) to shift the head against the tip rack and pick up a selected pattern of tips. With well_offset=(0, 11) head column 1 sits over rack column 12, so only the 8 channels of column 1 pick up tips.

A shifted pick-up on Hamilton robots needs a CO-RE tip support. The tip support holds the tips higher than a standard tip rack, so the head can reach them from the side without crashing into the rack itself. A shifted pick-up or put-down into a normal tip rack raises a ValueError.

The supports are defined in unitelabs.labware.hamilton, one per tip size. The example uses the 1000 µL support tip_support_1000 from Arrange the Deck.

# 1. Transfer 96 tips into the support
await vantage.core96.pick_up_tips_from(rack=tip_rack_1000_1)
await vantage.core96.put_down_tips_to(rack=tip_support_1000)

# 2. Pick up tips with the leftmost column of the head and place them back
await vantage.core96.pick_up_tips_from(rack=tip_support_1000, well_offset=(0, 11))
await vantage.core96.put_down_tips_to(rack=tip_support_1000, well_offset=(0, 11))

# 3. Full support back into the rack
await vantage.core96.pick_up_tips_from(rack=tip_support_1000)
await vantage.core96.put_down_tips_to(rack=tip_rack_1000_1)

Use the same well_offset for the put-down that you used for the pick-up.

There are two types of CO-RE tip supports: CO-RE II (for example HamiltonCore96TipSupport_1000) for heads with CO-RE II technology (Compressed O-Ring Expansion) and legacy CO-RE I (for example HamiltonCore96TipSupport_1000_CoreI), supported in unitelabs-labware >=0.39.0. Those two support types have different z dimensions and are not interchangeable. If in doubt, consult the product number or ask the hardware manufacturer.

Tip Pick-Up Parameters

The following parameters are available for the tip commands.

ParameterCommandsDescription
rackpick_up_tips_from, put_down_tips_toThe tip rack or CO-RE tip support to use. It must be assigned to the deck.
tip_typepick_up_tips_from_anywhere, put_down_tips_to_anywhereThe tip class to look for, for example HamiltonTip_300.
well_offsetpick_up_tips_from, put_down_tips_to(row, col) shift of the head against the rack, in wells. Defaults to (0, 0). A non-zero value needs a CO-RE tip support.
offsetpick_up_tips_from, put_down_tips_to, discard_tipsVector in mm added to the pick-up, drop, or discard position.

Tip Presence Detection

Unlike the single pipetting channels, the Hamilton Vantage CO-RE 96 head cannot detect whether tips are present on its channels. The Vantage firmware keeps track of tip pick-up and discard commands and holds a state flag that core96.has_tips_fw() can read, but the flag does not come from actual sensors.

Pipetting

The head aspirates and dispenses with all 96 channels at once and at the same height. The plunger motor is shared between the channels, so all channels handle the same liquid volume in one pipetting step.

Transfer with Liquid Level Detection and Jet Dispense

After picking up tips, use aspirate() and dispense() with keyword arguments to transfer liquid. This example transfers 700 µL of water from the trough into every well of the 96-well plate. The head finds the water surface in the trough using capacitive liquid level detection (cLLD) and aspirates 2 mm under it. The dispense is done in contactless jet mode, 15 mm above the liquid surface. The wells are empty, so the surface is the well bottom.

from unitelabs.liquid_handling import DispensePipetteMode
from unitelabs.liquid_handling.hamilton import LLDMode

await vantage.core96.pick_up_tips_from(rack=tip_rack_1000_1)

await vantage.core96.aspirate(
    source=water_trough,
    volume=700,
    lld_mode=LLDMode.CAPACITIVE,
    liquid_offset=2,
    follow_liquid=True,
    liquid_class=HamiltonLiquidClasses.HamiltonTip_1000_Water_DispenseJet_Empty,
)

await vantage.core96.dispense(
    target=plate,
    volume=700,
    pipette_mode=DispensePipetteMode.JET,
    liquid_offset=15,
    follow_liquid=False,
    liquid_class=HamiltonLiquidClasses.HamiltonTip_1000_Water_DispenseJet_Empty,
)

await vantage.core96.discard_tips()

Transfer and Mix with a Parameter Set

Use parameter sets to hold the pipetting settings in one object, so you can validate it, preview its resolved values, and reuse it for several steps. This example transfers 100 µL of the bead suspension from the second trough into the plate, which is prefilled with water. The head dispenses 2 mm under the liquid surface and then mixes three times with 600 µL, following the changing liquid level.

from unitelabs.liquid_handling import MixingParameterSet
from unitelabs.liquid_handling.hamilton import (
    CoRe96AspirateParameterSet,
    CoRe96Context,
    CoRe96DispenseParameterSet,
)

surface_class = HamiltonLiquidClasses.HamiltonTip_1000_Water_DispenseSurface_Empty

aspirate_params = CoRe96AspirateParameterSet(
    volume=100,
    lld_mode=LLDMode.CAPACITIVE,
    liquid_offset=2,
    follow_liquid=True,
    liquid_class=surface_class,
)

dispense_params = CoRe96DispenseParameterSet(
    volume=100,
    lld_mode=LLDMode.CAPACITIVE,
    liquid_offset=2,
    follow_liquid=False,
    liquid_class=surface_class,
    mixing=MixingParameterSet(cycles=3, volume=600, follow_liquid=True),
)

await vantage.core96.pick_up_tips_from(rack=tip_rack_1000_2)

await vantage.core96.aspirate(source=bead_trough, parameters=aspirate_params)
await vantage.core96.dispense(target=plate, parameters=dispense_params)

await vantage.core96.discard_tips()
The Vantage CO-RE 96 head only uses channels A1 and H12 for capacitive liquid level detection. If you aspirate with cLLD from a plate whose wells have different fill levels, some channels can aspirate air. When pipetting in SURFACE mode, all channels use the liquid level of well A1, even without cLLD.

Pipetting Parameters

aspirate() and dispense() take the same settings either as keyword arguments or as a parameters set. Use one or the other, you cannot mix both.

ParameterCommandsDefaultDescription
source, targetaspirate, dispenseRequiredThe labware to take liquid from or put it into.
parametersaspirate, dispenseNoneA CoRe96AspirateParameterSet or CoRe96DispenseParameterSet that replaces the keyword arguments. A device-independent set is adopted onto the head.
volumeaspirate, dispenseInferred from the tip and the containerVolume in µL.
pipette_modeaspirate, dispenseSURFACEWhere the tip pipettes. SURFACE follows the liquid level and BOTTOM the container bottom. Dispense also has JET, which dispenses above the liquid without touching it.
liquid_classaspirate, dispensePicked by the SDK for the tip, liquid, and modeThe liquid class with flow rates and air volumes.
lld_modeaspirate, dispenseCAPACITIVE in SURFACE mode, OFF in BOTTOM and JET modeLLDMode.CAPACITIVE detects the surface with the capacitive sensor, LLDMode.OFF does not. Only used in SURFACE mode. The head has no pressure-based detection.
liquid_offsetaspirate, dispense0.5 mmExtra z offset in mm. In SURFACE mode with cLLD, a positive value moves into the liquid and a negative one out of it. With liquid level detection off, in SURFACE and JET mode, the offset counts up from the liquid surface the SDK tracks for well A1 and must be positive. In BOTTOM mode it counts up from the container bottom and must be positive.
follow_liquidaspirate, dispenseAspirate: on, distance calculated from the volume. Dispense: offTrue lowers the tip with the liquid level by a distance calculated from the volume. A number sets that distance in mm. Used in SURFACE mode, and in JET mode for dispense.
pull_out_distanceaspirate, dispense5 mmDistance in mm above the liquid level the tip pulls out to before it takes up transport air. Only used with liquid level detection off.
touch_sidedispenseOffDispense while touching the side of the target.
mix_cyclesaspirate, dispense0 - no mixingNumber of mix cycles after the step.
mix_volumeaspirate, dispenseThe tip volume, when mix_cycles is setVolume in µL of each mix cycle.
mix_liquid_offsetaspirate, dispense0 mmExtra z offset in mm during mixing, relative to the pipette mode.
mix_follow_liquidaspirate, dispenseOffWhether the tip follows the liquid level during mixing.
end_z_offsetaspirate, dispenseNone, the head ends at the minimum traverse heightDistance in mm above the container top the head moves to after the step.
offsetaspirate, dispenseNo shiftVector with an extra x and y offset in mm.
min_traverse_heightaspirate, dispense245 mmHeight in mm the head travels at for this step. Can't exceed 390 mm.

In a parameter set, the four mix_* arguments become a nested MixingParameterSet (cycles, volume, liquid_offset, follow_liquid). A parameter set also takes well_offset for pipetting with a shifted head.

Want to validate and reuse parameter sets? Advanced Pipetting covers contexts, validation, serialization, and the compiled parameters.

Movement

Use the movement commands to move the head without performing any other task.

Read the position of the A1 tip of the head with current_location(), or the position of the bottom of the A1 channel if no tips are picked up.

location = await vantage.core96.current_location()
print(location)
# Vector(x=0.0, y=540.0, z=390.0)

Move to an absolute position with move_to(). The head rises to the traverse height, moves in x and y, and lowers to the target. You can use it to jog the head and check labware locations before pipetting.

await vantage.core96.move_to(Vector(x=300, y=200, z=300))

To travel higher than the default traverse height for one move, pass min_traverse_height:

# Travel higher than usual for this move
await vantage.core96.move_to(Vector(x=300, y=200, z=300), min_traverse_height=300)

Move relative to the current position with move_by(). This command travels at the higher of the start and target heights and does not rise to the safe traverse height. Use it for small adjustments only.

await vantage.core96.move_by(Vector(z=-20))
move_by() does not retract to the traverse height before it moves. Make sure there is no labware in the way that the head can collide with. If in doubt, use the safe move_to() command instead.

Go to the configured home location with home(), for example before turning off the power to the instrument or at the end of a workflow.

await vantage.core96.home()

Movement Parameters

ParameterCommandsDescription
locationmove_toAbsolute position of the A1 tip in mm as Vector.
min_traverse_heightmove_toHeight in mm the head travels at. Defaults to the global safe height of 245 mm. Values above 390 mm raise an error.
offsetmove_byRelative offset in mm as Vector. Leave an axis out to keep it unchanged.

The SDK checks every x and y position against the area the head can reach before it sends the command. A position outside raises a ValueError instead of reaching the firmware.

Heights and Park Position

The head moves between positions at a traverse height, so it clears labware on the way.

HeightValueDescription
Minimum traverse height245 mm (default)The lowest height the head travels at between positions. Set it per command with min_traverse_height (see Movement).
Maximum height390 mmThe highest height the head accepts. This is also the park height used by deactivate() and the default home.

A traverse or end height above 390 mm raises a ValueError. Heights the SDK derives from the current head position, for example in move_by(), are limited to 390 mm.

If the IPG is mounted on the same Vantage arm as the CO-RE 96 head, discard the tips and park the head at the maximum height before you use the IPG. The head's deactivate() command does the parking: it raises the head to 390 mm and keeps its x and y. Activating the pipetting channels, the XL channels, the IPG, or the IDL deactivates the head automatically, and activating the head deactivates them.

# Deactivate the head, which moves it up to 390 mm
await vantage.core96.deactivate()
Do not send low-level IPG commands while the head is lowered. Use deactivate() first, because only the maximum height keeps the head out of the IPG's way.

Last updated