Skip to content

Commit

Permalink
test: rework to support partial tip
Browse files Browse the repository at this point in the history
add pipetting
  • Loading branch information
DerekMaggio committed Dec 11, 2023
1 parent 3200e27 commit 18478e2
Showing 1 changed file with 115 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
"apiLevel": "2.16",
}

#############
### FLAGS ###
#############

# prefer to move off deck, instead of waste chute disposal, if possible
PREFER_MOVE_OFF_DECK = True

#################
### CONSTANTS ###
#################

HEATER_SHAKER_NAME = "heaterShakerModuleV1"
MAGNETIC_BLOCK_NAME = "magneticBlockV1"
PCR_PLATE_96_NAME = "nest_96_wellplate_100ul_pcr_full_skirt"
Expand All @@ -22,33 +33,9 @@
RESET_AFTER_EACH_MOVE = True
DONT_RESET_AFTER_EACH_MOVE = False


LABWARE_MOVEMENT_DECK_SLOT_1 = "D1"
LABWARE_MOVEMENT_DECK_SLOT_2 = "B3"
LABWARE_MOVEMENT_STAGING_AREA_SLOT_3 = "C3"
LABWARE_MOVEMENT_STAGING_AREA_SLOT_4 = "A4"

TIP_RACK_LOCATION_1 = "C3"
TIP_RACK_LOCATION_2 = "D2"

# NO STAGING AREA IN ROW A or B because of modules

# A1 - B1: Thermocycler
# C1: Trash Bin
# D1: EMPTY
# A2: Magnetic Block
# B2: Source PCR Plate
# C2: EMPTY for now, will load from off deck - Dest PCR Plate
# D2: Tip Rack 2
# A3: Heater-Shaker
# B3: Temperature Module
# C3: Tip Rack 1
# D3: EMPTY
# A4: EMPTY
# B4: EMPTY
# C4: EMPTY for now, will load from off deck - Staging Area Tip Rack 1
# D4: EMPTY for now, will load from off deck - Staging Area Tip Rack 2


def default_well(tiprack: protocol_api.labware) -> protocol_api.labware.Well:
return tiprack["A1"]
Expand All @@ -60,22 +47,20 @@ def run(ctx: protocol_api.ProtocolContext) -> None:
### FIXTURES ###
################

trash_bin_1 = ctx.load_trash_bin("C1")
trash_bin = ctx.load_trash_bin("B3")
waste_chute = ctx.load_waste_chute()

###############
### MODULES ###
###############
thermocycler = ctx.load_module(THERMOCYCLER_NAME) # A1 & B1
magnetic_block = ctx.load_module(MAGNETIC_BLOCK_NAME, "A2")
magnetic_block = ctx.load_module(MAGNETIC_BLOCK_NAME, "C1")
heater_shaker = ctx.load_module(HEATER_SHAKER_NAME, "A3")
temperature_module = ctx.load_module(TEMPERATURE_MODULE_NAME, "B3")
temperature_module = ctx.load_module(TEMPERATURE_MODULE_NAME, "D1")

thermocycler.open_lid()
heater_shaker.open_labware_latch()

modules = [thermocycler, heater_shaker, magnetic_block, temperature_module]

#######################
### MODULE ADAPTERS ###
#######################
Expand All @@ -89,31 +74,21 @@ def run(ctx: protocol_api.ProtocolContext) -> None:
### LABWARE ###
###############

source_pcr_plate = ctx.load_labware(PCR_PLATE_96_NAME, "B2")
dest_pcr_plate = ctx.load_labware(PCR_PLATE_96_NAME, protocol_api.OFF_DECK)
source_reservoir = ctx.load_labware("nest_1_reservoir_290ml", "D2")
dest_pcr_plate = ctx.load_labware(PCR_PLATE_96_NAME, "C2")

on_deck_tip_rack_1 = ctx.load_labware(
TIPRACK_96_NAME, TIP_RACK_LOCATION_1, adapter="opentrons_flex_96_tiprack_adapter"
tip_rack_1 = ctx.load_labware(
TIPRACK_96_NAME, "A2", adapter="opentrons_flex_96_tiprack_adapter"
)
tip_rack_adapter_1 = on_deck_tip_rack_1.parent

on_deck_tip_rack_2 = ctx.load_labware(
TIPRACK_96_NAME, TIP_RACK_LOCATION_2, adapter="opentrons_flex_96_tiprack_adapter"
)
tip_rack_adapter_2 = on_deck_tip_rack_2.parent

off_deck_tip_rack_1 = ctx.load_labware(TIPRACK_96_NAME, protocol_api.OFF_DECK)
off_deck_tip_rack_2 = ctx.load_labware(TIPRACK_96_NAME, protocol_api.OFF_DECK)
staging_area_tip_rack_1 = ctx.load_labware(TIPRACK_96_NAME, protocol_api.OFF_DECK)
staging_area_tip_rack_2 = ctx.load_labware(TIPRACK_96_NAME, protocol_api.OFF_DECK)
tip_rack_adapter = tip_rack_1.parent

tip_rack_2 = ctx.load_labware(TIPRACK_96_NAME, "C3")
tip_rack_3 = ctx.load_labware(TIPRACK_96_NAME, "C4")

tip_racks = [
on_deck_tip_rack_1,
on_deck_tip_rack_2,
# staging_area_tip_rack_1,
# staging_area_tip_rack_2,
off_deck_tip_rack_1,
off_deck_tip_rack_2,
tip_rack_1,
tip_rack_2,
tip_rack_3,
]

##########################
Expand All @@ -132,7 +107,7 @@ def run(ctx: protocol_api.ProtocolContext) -> None:

[
well.load_liquid(liquid=water if i % 2 == 0 else acetone, volume=STARTING_VOL)
for i, column in enumerate(source_pcr_plate.columns())
for i, column in enumerate(source_reservoir.columns())
for well in column
]

Expand All @@ -157,29 +132,26 @@ def run(ctx: protocol_api.ProtocolContext) -> None:

# Staging Area Slot 4 -> Staging Area Slot 4
# Staging Area Slot 4 -> Staging Area Slot 3
# Staging Area Slot 4 -> Each Module
# Staging Area Slot 4 -> Each ModuleSTAGING_AREA_SLOT_3_RESET_LOCATION
# Staging Area Slot 4 -> Deck

# Module -> Staging Area Slot 3
# Module -> Staging Area Slot 4
# Module -> Deck
# Module -> Other Module

def get_disposal_preference():
return (protocol_api.OFF_DECK, not USING_GRIPPER) if PREFER_MOVE_OFF_DECK else (waste_chute, USING_GRIPPER)

def run_moves(labware, move_sequences, reset_location, use_gripper):
def move_to_locations(labware_to_move, move_locations, reset_after_each_move, use_gripper, reset_location):
def reset_labware():
ctx.comment(
f"Moving {labware_to_move.name} back to {reset_location.__str__} from {labware_to_move.parent.__str__}"
)
ctx.move_labware(labware_to_move, reset_location, use_gripper=use_gripper)

if len(move_locations) == 0:
return

for location in move_locations:
ctx.comment(
f"Moving {labware_to_move.name} from {labware_to_move.parent.__str__} to {location.__str__}"
)
ctx.move_labware(labware_to_move, location, use_gripper=use_gripper)

if reset_after_each_move:
Expand All @@ -194,21 +166,18 @@ def reset_labware():

def test_gripper_moves():
def deck_moves(pcr_plate, reset_location):

# Deck -> Deck
deck_move_sequence = [
["D1", "C2"], # Deck Moves
["D3"], # Staging Area Slot 3 Moves
["B2"], # Deck Moves
["C3"], # Staging Area Slot 3 Moves
["C4", "D4"], # Staging Area Slot 4 Moves
[thermocycler, temperature_module_adapter, heater_shaker_adapter, magnetic_block], # Module Moves
]

run_moves(pcr_plate, deck_move_sequence, reset_location, USING_GRIPPER)

def staging_area_slot_3_moves(labware, reset_location):

staging_area_slot_3_move_sequence = [
["D1", "C2", "B2"], # Deck Moves
["B2", "C2"], # Deck Moves
[], # Don't have Staging Area Slot 3 open
["C4", "D4"], # Staging Area Slot 4 Moves
[thermocycler, temperature_module_adapter, heater_shaker_adapter, magnetic_block], # Module Moves
Expand All @@ -219,9 +188,9 @@ def staging_area_slot_3_moves(labware, reset_location):
def staging_area_slot_4_moves(labware, reset_location):

staging_area_slot_4_move_sequence = [
["D1", "C2", "B2"], # Deck Moves
["D3"], # Staging Area Slot 3 Moves
["D4"], # Staging Area Slot 4 Moves
["C2", "B2"], # Deck Moves
["C3"], # Staging Area Slot 3 Moves
["C4"], # Staging Area Slot 4 Moves
[thermocycler, temperature_module_adapter, heater_shaker_adapter, magnetic_block], # Module Moves
]

Expand All @@ -230,8 +199,8 @@ def staging_area_slot_4_moves(labware, reset_location):
def module_moves(labware, module_locations):

module_move_sequence = [
["D1", "C2", "B2"], # Deck Moves
["D3"], # Staging Area Slot 3 Moves
["C2", "B2"], # Deck Moves
["C3"], # Staging Area Slot 3 Moves
["C4", "D4"], # Staging Area Slot 4 Moves
]

Expand All @@ -240,27 +209,91 @@ def module_moves(labware, module_locations):
labware_move_to_locations.remove(module_starting_location)
all_sequences = module_move_sequence.copy()
all_sequences.append(labware_move_to_locations)
ctx.move_labware(source_pcr_plate, module_starting_location, use_gripper=USING_GRIPPER)
ctx.move_labware(labware, module_starting_location, use_gripper=USING_GRIPPER)
run_moves(labware, all_sequences, module_starting_location, USING_GRIPPER)

DECK_MOVE_RESET_LOCATION = "B2"
STAGING_AREA_SLOT_3_RESET_LOCATION = "D3"
STAGING_AREA_SLOT_4_RESET_LOCATION = "C4"
DECK_MOVE_RESET_LOCATION = "C2"
STAGING_AREA_SLOT_3_RESET_LOCATION = "C3"
STAGING_AREA_SLOT_4_RESET_LOCATION = "D4"

deck_moves(source_pcr_plate, DECK_MOVE_RESET_LOCATION)
deck_moves(dest_pcr_plate, DECK_MOVE_RESET_LOCATION)

ctx.move_labware(source_pcr_plate, STAGING_AREA_SLOT_3_RESET_LOCATION, use_gripper=USING_GRIPPER)
staging_area_slot_3_moves(source_pcr_plate, STAGING_AREA_SLOT_3_RESET_LOCATION)
ctx.move_labware(dest_pcr_plate, STAGING_AREA_SLOT_3_RESET_LOCATION, use_gripper=USING_GRIPPER)
staging_area_slot_3_moves(dest_pcr_plate, STAGING_AREA_SLOT_3_RESET_LOCATION)

ctx.move_labware(source_pcr_plate, STAGING_AREA_SLOT_4_RESET_LOCATION, use_gripper=USING_GRIPPER)
staging_area_slot_4_moves(source_pcr_plate, STAGING_AREA_SLOT_4_RESET_LOCATION)
ctx.move_labware(dest_pcr_plate, STAGING_AREA_SLOT_4_RESET_LOCATION, use_gripper=USING_GRIPPER)
staging_area_slot_4_moves(dest_pcr_plate, STAGING_AREA_SLOT_4_RESET_LOCATION)

module_locations = [thermocycler, magnetic_block] + adapters
module_moves(source_pcr_plate, module_locations)
module_moves(dest_pcr_plate, module_locations)

def test_manual_moves():
# In C4 currently
ctx.move_labware(source_pcr_plate, "D4", use_gripper=not USING_GRIPPER)

test_gripper_moves()
ctx.move_labware(source_reservoir, "D4", use_gripper=not USING_GRIPPER)

def test_pipetting():

def test_partial_tip_pickup_usage():
pipette_96_channel.configure_nozzle_layout(style=protocol_api.COLUMN, start="A12")
for i in range(1, 13):
pipette_96_channel.pick_up_tip(tip_rack_2[f"A{i}"])

pipette_96_channel.aspirate(5, source_reservoir["A1"])
pipette_96_channel.touch_tip()

pipette_96_channel.dispense(5, dest_pcr_plate[f"A{i}"])
pipette_96_channel.drop_tip(trash_bin)

# leave this dropping in waste chute, do not use get_disposal_preference
# want to test partial drop
ctx.move_labware(tip_rack_2, waste_chute, use_gripper=USING_GRIPPER)

def test_full_tip_rack_usage():
pipette_96_channel.configure_nozzle_layout(style=protocol_api.ALL, start="A1")
pipette_96_channel.pick_up_tip(tip_rack_1["A1"])

pipette_96_channel.aspirate(5, source_reservoir["A1"])
pipette_96_channel.touch_tip()

# Waiting for https://opentrons.atlassian.net/browse/RQA-2056
# pipette_96_channel.air_gap(height=30)

pipette_96_channel.blow_out(waste_chute)

pipette_96_channel.aspirate(10, source_reservoir["A1"])
pipette_96_channel.touch_tip()

pipette_96_channel.dispense(10, dest_pcr_plate["A1"])
pipette_96_channel.mix(repetitions=5, volume=15)
pipette_96_channel.return_tip()

ctx.move_labware(tip_rack_1, get_disposal_preference()[0], use_gripper=get_disposal_preference()[1])
ctx.move_labware(tip_rack_3, tip_rack_adapter, use_gripper=USING_GRIPPER)

pipette_96_channel.pick_up_tip(tip_rack_3["A1"])
pipette_96_channel.transfer(
volume=10,
source=source_reservoir["A1"],
dest=dest_pcr_plate["A1"],
new_tip="never",
touch_tip=True,
blow_out=True,
blowout_location="trash",
mix_before=(3, 5),
mix_after=(1, 5),
)
pipette_96_channel.return_tip()

ctx.move_labware(tip_rack_3, get_disposal_preference()[0], use_gripper=get_disposal_preference()[1])

test_partial_tip_pickup_usage()
test_full_tip_rack_usage()

test_manual_moves()
test_pipetting()
test_gripper_moves()


# Cannot test in this protocol
# - Waste Chute w/ Lid

0 comments on commit 18478e2

Please sign in to comment.