Skip to content

Commit 458b193

Browse files
authored
feat(abr-testing): Stacker Stamping Protocol (#18915)
<!-- Thanks for taking the time to open a Pull Request (PR)! Please make sure you've read the "Opening Pull Requests" section of our Contributing Guide: https://github.com/Opentrons/opentrons/blob/edge/CONTRIBUTING.md#opening-pull-requests GitHub provides robust markdown to format your PR. Links, diagrams, pictures, and videos along with text formatting make it possible to create a rich and informative PR. For more information on GitHub markdown, see: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax To ensure your code is reviewed quickly and thoroughly, please fill out the sections below to the best of your ability! --> # Overview Flex Stacker Stamping Protocol ## Test Plan and Hands on Testing - Run with PVT stackers before 8.6 release ## Changelog - Protocol loads 1 stacker with tips and the remaining with labware - The protocol unloads labware and transfers liquid to them using liquid class behavior - Then the protocol stores the labware back into the stacker and moves on to the next set of plates ## Review requests <!-- - What do you need from reviewers to feel confident this PR is ready to merge? - Ask questions. --> ## Risk assessment <!-- - Indicate the level of attention this PR needs. - Provide context to guide reviewers. - Discuss trade-offs, coupling, and side effects. - Look for the possibility, even if you think it's small, that your change may affect some other part of the system. - For instance, changing return tip behavior may also change the behavior of labware calibration. - How do your unit tests and on hands on testing mitigate this PR's risks and the risk of future regressions? - Especially in high risk PRs, explain how you know your testing is enough. -->
1 parent 85a098f commit 458b193

File tree

1 file changed

+210
-0
lines changed

1 file changed

+210
-0
lines changed
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
"""Labware Stamping Protocol."""
2+
from opentrons.protocol_api import (
3+
ProtocolContext,
4+
ParameterContext,
5+
InstrumentContext,
6+
Labware,
7+
LiquidClass,
8+
)
9+
from opentrons.protocol_api.module_contexts import (
10+
FlexStackerContext,
11+
TemperatureModuleContext,
12+
)
13+
14+
from typing import List
15+
16+
metadata = {
17+
"protocolName": "Flex Stacker Stamping Protocol",
18+
"author": "Rhyann Clarke <[email protected]",
19+
}
20+
21+
requirements = {"robotType": "Flex", "apiLevel": "2.25"}
22+
23+
24+
DECK_SLOTS = ["A1", "A2", "B1", "B2", "B3", "C1", "C2", "C3", "D2", "D3"]
25+
TIP_RACK_SLOTS = DECK_SLOTS[:2]
26+
LABWARE_SLOTS = DECK_SLOTS[2:]
27+
28+
29+
def set_liquid_class_behavior(
30+
ctx: ProtocolContext,
31+
pipette: InstrumentContext,
32+
tip_racks: List[Labware],
33+
water: LiquidClass,
34+
) -> None:
35+
"""Set Liquid Class Behavior."""
36+
lm = "liquid-meniscus"
37+
for lbw in tip_racks:
38+
props = water.get_for(pipette, lbw)
39+
props.aspirate.aspirate_position.position_reference = lm # type: ignore[assignment]
40+
props.aspirate.aspirate_position.offset.z = -2
41+
props.dispense.dispense_position.position_reference = lm # type: ignore[assignment]
42+
props.dispense.dispense_position.offset.z = 1
43+
44+
45+
def add_parameters(parameters: ParameterContext) -> None:
46+
"""Parameters."""
47+
parameters.add_bool(
48+
display_name="Use Temperature Module",
49+
variable_name="use_temp_mod",
50+
default=False,
51+
description="Use temperature module in protocol.",
52+
)
53+
parameters.add_int(
54+
display_name="# of PCR Plates",
55+
variable_name="num_pcr_plates",
56+
default=6,
57+
maximum=40,
58+
minimum=1,
59+
)
60+
parameters.add_int(
61+
display_name="# of 384 Plates",
62+
variable_name="num_384_plates",
63+
default=6,
64+
maximum=40,
65+
minimum=1,
66+
)
67+
parameters.add_int(
68+
display_name="# of NEST Deep Well Plates",
69+
variable_name="num_nest_plates",
70+
default=6,
71+
maximum=40,
72+
minimum=1,
73+
)
74+
75+
76+
def move_plates_to_deck_fill_and_store(
77+
stacker: FlexStackerContext,
78+
ctx: ProtocolContext,
79+
p96: InstrumentContext,
80+
water: LiquidClass,
81+
reservoir: Labware,
82+
) -> None:
83+
"""Move plates to the deck, fill them with water, and store back in stacker."""
84+
# Move PCR Plates and Fill
85+
plates_on_deck = []
86+
for i in range(6):
87+
plate = stacker.retrieve()
88+
ctx.move_labware(plate, LABWARE_SLOTS[i], use_gripper=True)
89+
plate.load_empty(plate.wells())
90+
if i % 2 == 0:
91+
p96.reset_tipracks()
92+
set_liquid_class_behavior(ctx, p96, p96.tip_racks, water)
93+
p96.transfer_with_liquid_class(
94+
water,
95+
50,
96+
reservoir["A1"],
97+
plate["A1"],
98+
new_tip="once",
99+
return_tip=True,
100+
group_wells=False,
101+
)
102+
plates_on_deck.append(plate)
103+
for plate in plates_on_deck:
104+
ctx.move_labware(plate, stacker, use_gripper=True)
105+
stacker.store()
106+
107+
108+
def unload_tipracks_from_stacker(
109+
ctx: ProtocolContext,
110+
p96: InstrumentContext,
111+
stacker: FlexStackerContext,
112+
tiprack_adapters: List[Labware],
113+
) -> None:
114+
"""Unload tipracks and assign to pipette."""
115+
p96.tip_racks.clear()
116+
for i in range(2):
117+
tip_rack = stacker.retrieve()
118+
ctx.move_labware(tip_rack, tiprack_adapters[i], use_gripper=True)
119+
# 🔁 Liquid class must be configured *after* tip rack is on deck
120+
water = ctx.get_liquid_class("water")
121+
set_liquid_class_behavior(ctx, p96, [tip_rack], water)
122+
p96.tip_racks.append(tip_rack)
123+
124+
125+
def run(ctx: ProtocolContext) -> None:
126+
"""Run the protocol."""
127+
use_temp_mod = ctx.params.use_temp_mod # type: ignore[attr-defined]
128+
129+
tiprack_adapters = [
130+
ctx.load_adapter("opentrons_flex_96_tiprack_adapter", slot)
131+
for slot in TIP_RACK_SLOTS
132+
]
133+
# Load Instrument and Liquids
134+
p96: InstrumentContext = ctx.load_instrument(
135+
"flex_96channel_1000",
136+
mount="left",
137+
tip_racks=[],
138+
)
139+
reservoir = ctx.load_labware("nest_1_reservoir_195ml", "D1")
140+
water_liq = ctx.define_liquid("water", "#C0C0C0")
141+
reservoir["A1"].load_liquid(water_liq, 10000)
142+
if use_temp_mod:
143+
temp_mod: TemperatureModuleContext = ctx.load_module(
144+
"temperaturModuleV1", "D1"
145+
) # type: ignore[assignment]
146+
temp_mod.set_temperature(4)
147+
DECK_SLOTS.remove("D1")
148+
stackers = []
149+
# Use tuples for labware name and count
150+
labware_dict = {
151+
"A4": ("opentrons_flex_96_tiprack_50ul", 6),
152+
"B4": (
153+
"opentrons_96_wellplate_200ul_pcr_full_skirt",
154+
ctx.params.num_pcr_plates, # type: ignore[attr-defined]
155+
),
156+
"C4": (
157+
"appliedbiosystemsmicroamp_384_wellplate_40ul",
158+
ctx.params.num_384_plates, # type: ignore[attr-defined]
159+
),
160+
"D4": (
161+
"nest_96_wellplate_2ml_deep",
162+
ctx.params.num_nest_plates, # type: ignore[attr-defined]
163+
),
164+
}
165+
166+
for slot, (labware_name, count) in labware_dict.items():
167+
stacker: FlexStackerContext = ctx.load_module(
168+
"flexStackerModuleV1",
169+
slot,
170+
) # type: ignore[assignment]
171+
stacker.set_stored_labware(labware_name, count=count)
172+
stackers.append(stacker)
173+
stacker_50ul = stackers[0]
174+
stacker_pcrplates = stackers[1]
175+
stacker_384plates = stackers[2]
176+
stacker_nest96deep = stackers[3]
177+
water = ctx.get_liquid_class("water")
178+
ctx.load_trash_bin("A3")
179+
# unload tipracks
180+
unload_tipracks_from_stacker(ctx, p96, stacker_50ul, tiprack_adapters)
181+
move_plates_to_deck_fill_and_store(stacker_pcrplates, ctx, p96, water, reservoir)
182+
# Move old tipracks
183+
old_tipracks = p96.tip_racks
184+
ctx.move_labware(old_tipracks[0], "D2", use_gripper=True)
185+
ctx.move_labware(old_tipracks[1], "D3", use_gripper=True)
186+
# Get new tipracks
187+
unload_tipracks_from_stacker(ctx, p96, stacker_50ul, tiprack_adapters)
188+
# Second labware
189+
move_plates_to_deck_fill_and_store(stacker_384plates, ctx, p96, water, reservoir)
190+
191+
# Unload last tip racks
192+
unused_tiprack1 = stacker_50ul.retrieve()
193+
ctx.move_labware(unused_tiprack1, "B1", use_gripper=True)
194+
unused_tiprack2 = stacker_50ul.retrieve()
195+
ctx.move_labware(unused_tiprack2, "B2", use_gripper=True)
196+
197+
# Store extra tip racks
198+
for tip in p96.tip_racks:
199+
ctx.move_labware(tip, stacker_50ul, use_gripper=True)
200+
stacker_50ul.store()
201+
# Move Tip racks to adapters
202+
ctx.move_labware(unused_tiprack1, tiprack_adapters[0], use_gripper=True)
203+
ctx.move_labware(unused_tiprack2, tiprack_adapters[1], use_gripper=True)
204+
205+
# Next Labware Type
206+
p96.tip_racks.clear()
207+
p96.tip_racks.append(unused_tiprack1)
208+
p96.tip_racks.append(unused_tiprack2)
209+
set_liquid_class_behavior(ctx, p96, [unused_tiprack1, unused_tiprack2], water)
210+
move_plates_to_deck_fill_and_store(stacker_nest96deep, ctx, p96, water, reservoir)

0 commit comments

Comments
 (0)