Skip to content

Commit 1430984

Browse files
authored
refactor(abr-testing): updated ABR protocols to include 8.5 features (#18841)
<!-- 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 8.5.0 Updates to ABR Protocols ## Test Plan and Hands on Testing Ran each protocol in ABR ## Changelog - Added usage of `opentrons_tough_12_reservoir_22ml` - Added usage of `opentrons_tough_universal_lid` - liquid class pipetting + meniscus relative movement - remove unneeded custom labware - removed unneeded liquid set up protocols ## 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 f9b63bc commit 1430984

24 files changed

+4874
-2551
lines changed

abr-testing/abr_testing/protocols/active_protocols/10_ZymoBIOMICS_Magbead_DNA_Cells_Flex.py

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
}
2020

2121

22-
requirements = {"robotType": "Flex", "apiLevel": "2.23"}
22+
requirements = {"robotType": "Flex", "apiLevel": "2.24"}
2323
"""
2424
Slot A1: Tips 1000
2525
Slot A2: Tips 1000
@@ -76,7 +76,7 @@ def run(protocol: protocol_api.ProtocolContext) -> None:
7676
deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined]
7777
probe_height_bool = protocol.params.probe_liquid_height # type: ignore[attr-defined]
7878
meniscus_z = protocol.params.meniscus_z # type: ignore[attr-defined]
79-
helpers.comment_protocol_version(protocol, "01")
79+
helpers.comment_protocol_version(protocol, "02")
8080
if not protocol.is_simulating():
8181
slack_bot = helpers.set_up_slack()
8282
slack_bot.send_run_started_message(metadata["protocolName"])
@@ -85,7 +85,7 @@ def run(protocol: protocol_api.ProtocolContext) -> None:
8585
TIP_TRASH = (
8686
False # True = Used tips go i n Trash, False = Used tips go back into rack
8787
)
88-
res_type = "nest_12_reservoir_15ml"
88+
res_type = "opentrons_tough_12_reservoir_22ml"
8989
global m1000_tips
9090
num_samples = 96
9191
wash1_vol = wash2_vol = wash3_vol = 400.0
@@ -148,7 +148,8 @@ def tipcheck(m1000: InstrumentContext) -> None:
148148
waste_reservoir = protocol.load_labware(
149149
"opentrons_tough_1_reservoir_300ml", "B3", "Liquid Waste"
150150
)
151-
waste = waste_reservoir.wells()[0].top()
151+
waste = waste_reservoir.wells()[0]
152+
waste_reservoir.load_empty(waste_reservoir.wells())
152153
res1 = protocol.load_labware(res_type, "D2", "reagent reservoir 1")
153154
res2 = protocol.load_labware(res_type, "C2", "reagent reservoir 2")
154155
res3 = protocol.load_labware(res_type, "B2", "reagent reservoir 3")
@@ -160,9 +161,17 @@ def tipcheck(m1000: InstrumentContext) -> None:
160161
tips1002 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "B1", "Tips 3")
161162
tips_sn = tips1000.wells()[:num_samples]
162163
# load instruments
163-
m1000 = protocol.load_instrument(
164-
"flex_8channel_1000", mount, tip_racks=[tips1000, tips1001, tips1002]
165-
)
164+
tip_racks = [tips1000, tips1001, tips1002]
165+
166+
m1000 = protocol.load_instrument("flex_8channel_1000", mount, tip_racks=tip_racks)
167+
water = protocol.get_liquid_class("water")
168+
lm = "liquid-meniscus"
169+
for tip in tip_racks:
170+
props = water.get_for(m1000, tip)
171+
props.aspirate.aspirate_position.position_reference = lm # type: ignore[assignment]
172+
props.aspirate.aspirate_position.offset.z = meniscus_z
173+
props.dispense.dispense_position.position_reference = lm # type: ignore[assignment]
174+
props.dispense.dispense_position.offset.z = meniscus_z
166175

167176
def remove_supernatant(vol: float) -> None:
168177
"""Remove supernatant."""
@@ -172,13 +181,21 @@ def remove_supernatant(vol: float) -> None:
172181
vol_per_trans = vol / num_trans
173182

174183
for i, m in enumerate(samples_m):
175-
m1000.pick_up_tip(tips_sn[8 * i])
176-
loc = m.meniscus(z=meniscus_z, target="end")
184+
tipcheck(m1000)
185+
loc = m
177186
for _ in range(num_trans):
178187
m1000.move_to(m.center())
179188
if vol_per_trans > m.current_liquid_volume():
180189
vol_per_trans = m.current_liquid_volume() - 100 # type: ignore
181-
m1000.transfer(vol_per_trans, loc, waste, new_tip="never", air_gap=20)
190+
m1000.transfer_with_liquid_class(
191+
water,
192+
vol_per_trans,
193+
loc,
194+
waste,
195+
new_tip="never",
196+
return_tip=True,
197+
group_wells=False,
198+
)
182199
m1000.blow_out(waste)
183200
m1000.air_gap(20)
184201
m1000.drop_tip(tips_sn[8 * i]) if TIP_TRASH else m1000.return_tip()
@@ -330,15 +347,22 @@ def bind(vol1: float, vol2: float) -> None:
330347
else:
331348
reps = 2
332349
bead_mixing(source, m1000, vol_per_trans, reps=reps if not dry_run else 1)
350+
m1000.return_tip()
351+
tipcheck(m1000)
333352
# Transfer beads and binding from source to H-S plate
334353
for t in range(num_trans):
335354
if m1000.current_volume > 0:
336355
# void air gap if necessary
337356
m1000.dispense(m1000.current_volume, source.top())
338-
m1000.transfer(
339-
vol_per_trans, source, well.top(), air_gap=20, new_tip="never"
357+
m1000.transfer_with_liquid_class(
358+
water,
359+
vol_per_trans,
360+
source,
361+
well,
362+
new_tip="never",
363+
return_tip=True,
364+
group_wells=False,
340365
)
341-
m1000.air_gap(20)
342366
bead_mixing(well, m1000, vol_per_trans, reps=bead_reps_2)
343367
m1000.blow_out()
344368
m1000.air_gap(10)
@@ -375,12 +399,14 @@ def bind(vol1: float, vol2: float) -> None:
375399
if m1000.current_volume > 0:
376400
# void air gap if necessary
377401
m1000.dispense(m1000.current_volume, source.top())
378-
m1000.transfer(
402+
m1000.transfer_with_liquid_class(
403+
water,
379404
vol_per_trans,
380-
source.meniscus(z=meniscus_z, target="end"),
381-
well.top(),
382-
air_gap=20,
405+
source,
406+
well,
383407
new_tip="never",
408+
return_tip=True,
409+
group_wells=False,
384410
)
385411
m1000.air_gap(20)
386412

@@ -415,21 +441,23 @@ def wash(vol: float, source: List[Well]) -> None:
415441
protocol.comment("-----Now starting Wash #" + str(whichwash) + "-----")
416442
global wash_volume_tracker
417443

418-
num_trans = math.ceil(vol / 980)
444+
num_trans = math.ceil(vol / 980.0)
419445
vol_per_trans = vol / num_trans
420-
421446
tipcheck(m1000)
422447
for i, m in enumerate(samples_m):
423448
src = source[whichwash]
424449
for n in range(num_trans):
425-
if vol_per_trans > src.current_liquid_height():
426-
vol_per_trans = src.current_liquid_height() - 100 # type: ignore[assignment]
427-
m1000.transfer(
450+
if vol_per_trans > src.current_liquid_volume():
451+
vol_per_trans = src.current_liquid_volume() # type: ignore[assignment]
452+
453+
m1000.transfer_with_liquid_class(
454+
water,
428455
vol_per_trans,
429-
src.meniscus(z=meniscus_z, target="end"),
430-
m.top(),
431-
air_gap=20,
456+
src,
457+
m,
432458
new_tip="never",
459+
return_tip=True,
460+
group_wells=False,
433461
)
434462
wash_volume_tracker += vol_per_trans * 8
435463
if wash_volume_tracker >= 9600:
@@ -483,12 +511,8 @@ def elute(vol: float) -> None:
483511
tipcheck(m1000)
484512
m1000.flow_rate.dispense = 100
485513
m1000.flow_rate.aspirate = 25
486-
m1000.transfer(
487-
vol,
488-
m.meniscus(z=meniscus_z, target="end"),
489-
e.meniscus(z=5, target="end"),
490-
air_gap=20,
491-
new_tip="never",
514+
m1000.transfer_with_liquid_class(
515+
water, vol, m, e, new_tip="never", return_tip=True, group_wells=False
492516
)
493517
m1000.blow_out(e.top(-2))
494518
m1000.air_gap(20)

abr-testing/abr_testing/protocols/active_protocols/1_Simple Normalize Long Right.py

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"source": "Protocol Library",
1616
}
1717

18-
requirements = {"robotType": "Flex", "apiLevel": "2.23"}
18+
requirements = {"robotType": "Flex", "apiLevel": "2.24"}
1919

2020

2121
def add_parameters(parameters: ParameterContext) -> None:
@@ -31,7 +31,7 @@ def run(protocol: ProtocolContext) -> None:
3131
probe_height_bool = protocol.params.probe_liquid_height # type: ignore[attr-defined]
3232
meniscus_z = protocol.params.meniscus_z # type: ignore[attr-defined]
3333
data = all_data[1:]
34-
helpers.comment_protocol_version(protocol, "02")
34+
helpers.comment_protocol_version(protocol, "03")
3535
if not protocol.is_simulating():
3636
slack_bot = helpers.set_up_slack()
3737
slack_bot.send_run_started_message(metadata["protocolName"])
@@ -45,7 +45,7 @@ def run(protocol: ProtocolContext) -> None:
4545
"armadillo_96_wellplate_200ul_pcr_full_skirt", "D3"
4646
)
4747

48-
reservoir = protocol.load_labware("nest_12_reservoir_15ml", "B3")
48+
reservoir = protocol.load_labware("opentrons_tough_12_reservoir_22ml", "B3")
4949
waste_reservoir = protocol.load_labware(
5050
"opentrons_tough_1_reservoir_300ml", "C1", "Liquid Waste"
5151
)
@@ -90,6 +90,23 @@ def run(protocol: ProtocolContext) -> None:
9090
"Dye": [{"well": [Dye_1, Dye_2, Dye_3], "volume": 675.0}],
9191
"Diluent": [{"well": [Diluent_1, Diluent_2, Diluent_3], "volume": 675.0}],
9292
}
93+
water = protocol.get_liquid_class("water")
94+
lm = "liquid-meniscus"
95+
tip_racks = [tiprack_x_2, tiprack_x_3]
96+
for tip in tip_racks:
97+
props = water.get_for(p1000_single, tip)
98+
props.aspirate.aspirate_position.position_reference = lm # type: ignore[assignment]
99+
props.aspirate.aspirate_position.offset.z = meniscus_z
100+
props.dispense.dispense_position.position_reference = lm # type: ignore[assignment]
101+
props.dispense.dispense_position.offset.z = meniscus_z
102+
tip_racks_multi = [tiprack_x_1]
103+
for tip in tip_racks_multi:
104+
props = water.get_for(p1000, tip)
105+
props.aspirate.aspirate_position.position_reference = lm # type: ignore[assignment]
106+
props.aspirate.aspirate_position.offset.z = meniscus_z
107+
props.dispense.dispense_position.position_reference = lm # type: ignore[assignment]
108+
props.dispense.dispense_position.offset.z = meniscus_z
109+
93110
# CONFIGURE SINGLE LAYOUT
94111
p1000.configure_nozzle_layout(style=SINGLE, start="H1", tip_racks=[tiprack_x_1])
95112
try:
@@ -107,21 +124,18 @@ def run(protocol: ProtocolContext) -> None:
107124

108125
current = 0
109126

110-
p1000.pick_up_tip()
111127
while current < len(data):
112128
CurrentWell = str(data[current][0])
113129
DyeVol = float(data[current][1])
114130
while Dye_1.current_liquid_volume() < (DyeVol * 8):
115-
p1000.transfer(
131+
p1000.transfer_with_liquid_class(
132+
water,
116133
DyeVol,
117-
Dye_1.meniscus(z=meniscus_z, target="end"),
118-
sample_plate_1.wells_by_name()[CurrentWell].top(z=1),
119-
new_tip="never",
134+
Dye_1,
135+
sample_plate_1.wells_by_name()[CurrentWell],
136+
return_tip=True,
120137
)
121138
current += 1
122-
p1000.blow_out(location=waste_reservoir["A1"])
123-
p1000.touch_tip()
124-
p1000.drop_tip()
125139

126140
protocol.comment("==============================================")
127141
protocol.comment("Adding Diluent Sample Plate 1")
@@ -151,21 +165,18 @@ def run(protocol: ProtocolContext) -> None:
151165
protocol.comment("Adding Dye Sample Plate 2")
152166
protocol.comment("==============================================")
153167
current = 0
154-
p1000_single.pick_up_tip()
155168
while current < len(data):
156169
CurrentWell = str(data[current][0])
157170
DyeVol = float(data[current][1])
158171
while Dye_2.current_liquid_volume() < (DyeVol * 8):
159-
p1000_single.transfer(
172+
p1000_single.transfer_with_liquid_class(
173+
water,
160174
DyeVol,
161-
Dye_2.meniscus(z=meniscus_z, target="end"),
162-
sample_plate_2.wells_by_name()[CurrentWell].top(z=1),
175+
Dye_2,
176+
sample_plate_2.wells_by_name()[CurrentWell],
163177
new_tip="never",
164178
)
165179
current += 1
166-
p1000_single.blow_out(location=waste_reservoir["A1"])
167-
p1000_single.touch_tip()
168-
p1000_single.return_tip()
169180

170181
protocol.comment("==============================================")
171182
protocol.comment("Adding Diluent Sample Plate 2")
@@ -194,23 +205,18 @@ def run(protocol: ProtocolContext) -> None:
194205
protocol.comment("==============================================")
195206

196207
current = 0
197-
p1000_single.pick_up_tip()
198208
while current < len(data):
199209
CurrentWell = str(data[current][0])
200210
DyeVol = float(data[current][1])
201211
if Dye_3.current_liquid_volume() < (DyeVol * 8):
202-
p1000_single.transfer(
212+
p1000_single.transfer_with_liquid_class(
213+
water,
203214
DyeVol,
204-
Dye_3.meniscus(z=meniscus_z, target="end"),
205-
sample_plate_3.wells_by_name()[CurrentWell].top(z=1),
206-
blow_out=True,
207-
blowout_location="destination well",
208-
new_tip="never",
215+
Dye_3,
216+
sample_plate_3.wells_by_name()[CurrentWell],
217+
return_tip=True,
209218
)
210219
current += 1
211-
p1000_single.blow_out(location=waste_reservoir["A1"])
212-
p1000_single.touch_tip()
213-
p1000_single.return_tip()
214220
protocol.comment("==============================================")
215221
protocol.comment("Adding Diluent Sample Plate 3")
216222
protocol.comment("==============================================")
@@ -237,25 +243,20 @@ def run(protocol: ProtocolContext) -> None:
237243
protocol.comment("==============================================")
238244
p1000_single.reset_tipracks()
239245
current = 0
240-
p1000_single.pick_up_tip()
241246
while current < len(data):
242247
CurrentWell = str(data[current][0])
243248
DyeVol = float(data[current][1])
244249
if DyeVol != 0 and DyeVol < 100:
245-
p1000_single.transfer(
250+
p1000_single.transfer_with_liquid_class(
251+
water,
246252
DyeVol,
247-
Dye_3.bottom(z=2),
248-
sample_plate_4.wells_by_name()[CurrentWell].top(z=1),
249-
blow_out=True,
250-
blowout_location="destination well",
251-
new_tip="never",
253+
Dye_3,
254+
sample_plate_4.wells_by_name()[CurrentWell],
255+
return_tip=True,
252256
)
253257
if DyeVol > 20:
254258
wells.append(sample_plate_4.wells_by_name()[CurrentWell])
255259
current += 1
256-
p1000_single.blow_out(location=waste_reservoir["A1"])
257-
p1000_single.touch_tip()
258-
p1000_single.return_tip()
259260
protocol.comment("==============================================")
260261
protocol.comment("Adding Diluent Sample Plate 4")
261262
protocol.comment("==============================================")

abr-testing/abr_testing/protocols/active_protocols/2_BMS_PCR_Protocol.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"protocolName": "PCR Protocol with TC Auto Sealing Lid",
1515
"author": "Rami Farawi <[email protected]",
1616
}
17-
requirements = {"robotType": "Flex", "apiLevel": "2.23"}
17+
requirements = {"robotType": "Flex", "apiLevel": "2.24"}
1818

1919

2020
def add_parameters(parameters: ParameterContext) -> None:
@@ -37,7 +37,7 @@ def run(protocol: ProtocolContext) -> None:
3737
deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined]
3838
probe_height_bool = protocol.params.probe_liquid_height # type: ignore[attr-defined]
3939
meniscus_z = protocol.params.meniscus_z # type: ignore[attr-defined]
40-
helpers.comment_protocol_version(protocol, "03")
40+
helpers.comment_protocol_version(protocol, "04")
4141
if not protocol.is_simulating():
4242
slack_bot = helpers.set_up_slack()
4343
slack_bot.send_run_started_message(metadata["protocolName"])

abr-testing/abr_testing/protocols/active_protocols/4_Illumina DNA Enrichment.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
requirements = {
2626
"robotType": "Flex",
27-
"apiLevel": "2.23",
27+
"apiLevel": "2.24",
2828
}
2929

3030
# SCRIPT SETTINGS
@@ -77,7 +77,7 @@ def run(protocol: ProtocolContext) -> None:
7777
probe_liquid_height_bool = protocol.params.probe_liquid_height # type: ignore[attr-defined]
7878
deactivate_modules_bool = protocol.params.deactivate_modules # type: ignore[attr-defined]
7979
meniscus_z = protocol.params.meniscus_z # type: ignore[attr-defined]
80-
helpers.comment_protocol_version(protocol, "02")
80+
helpers.comment_protocol_version(protocol, "03")
8181
if not protocol.is_simulating():
8282
slack_bot = helpers.set_up_slack()
8383
slack_bot.send_run_started_message(metadata["protocolName"])
@@ -107,7 +107,7 @@ def run(protocol: ProtocolContext) -> None:
107107
reagent_plate, temp_adapter = helpers.load_temp_adapter_and_labware(
108108
"opentrons_96_wellplate_200ul_pcr_full_skirt", temp_block, "Reagent Plate"
109109
)
110-
lid = protocol.load_lid_stack("custom_opentrons_tough_universal_lid", "B4", 2)
110+
lid = protocol.load_lid_stack("opentrons_tough_universal_lid", "B4", 2)
111111
# ========== SECOND ROW ==========
112112
MAG_PLATE_SLOT: MagneticBlockContext = protocol.load_module(
113113
helpers.mag_str, "C1"
@@ -155,7 +155,7 @@ def trash_liquid(
155155
) -> None:
156156
"""Determine which wells to use as liquid waste."""
157157
remaining_volume = vol_to_trash
158-
max_capacity = 1500.0 # Maximum capacity of a well in µL
158+
max_capacity = 1200.0 # Maximum capacity of a well in µL
159159
for well, current_volume in liquid_trash_list.items():
160160
if remaining_volume <= 0 or pipette.current_volume == 0.0:
161161
break

0 commit comments

Comments
 (0)