Skip to content

Commit 383f7ce

Browse files
authored
feat(abr-testing): protocol to test disposable lid with any pcr plate type (#16837)
<!-- 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 Protocol for testing `opentrons_tough_pcr_auto_sealing_lid` with any pcr plate ## Test Plan and Hands on Testing - Simulated profile with each lid type - Physically tested lid on thermocycler with biorad plate ## Changelog - added helper function for parameter with pcr plate types - added evaporation protocol - fixed abr1 bug where it resets a tip rack twice which causes the pipette to pick up from an empty slot - changed abr10 protocol to reflect comments about liquids at top ## Review requests <!-- - What do you need from reviewers to feel confident this PR is ready to merge? - Ask questions. --> ## Risk assessment - lid is currently not compatible with biorad plate or nest plate, but pr in progress for this.
1 parent 450c562 commit 383f7ce

File tree

5 files changed

+162
-24
lines changed

5 files changed

+162
-24
lines changed

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

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ def run(ctx: protocol_api.ProtocolContext) -> None:
9494
bind_time_1 = bind_time_2 = wash_time = 0.25
9595
drybeads = 0.5
9696
lysis_rep_1 = lysis_rep_2 = bead_reps_2 = 1
97-
PK_vol = 20.0
9897
bead_vol = 25.0
9998
starting_vol = lysis_vol + sample_vol
10099
binding_buffer_vol = bind_vol + bead_vol
@@ -137,7 +136,7 @@ def run(ctx: protocol_api.ProtocolContext) -> None:
137136
"""
138137
lysis_ = res1.wells()[0]
139138
binding_buffer = res1.wells()[1:4]
140-
bind2_res = res1.wells()[4:6]
139+
bind2_res = res1.wells()[4:8]
141140
wash1 = res1.wells()[6:8]
142141
elution_solution = res1.wells()[-1]
143142
wash2 = res2.wells()[:6]
@@ -149,16 +148,12 @@ def run(ctx: protocol_api.ProtocolContext) -> None:
149148
samps = sample_plate.wells()[: (8 * num_cols)]
150149

151150
liquid_vols_and_wells: Dict[str, List[Dict[str, Well | List[Well] | float]]] = {
152-
"Lysis": [{"well": lysis_, "volume": lysis_vol}],
153-
"PK": [{"well": lysis_, "volume": PK_vol}],
154-
"Beads": [{"well": binding_buffer, "volume": bead_vol}],
155-
"Binding": [{"well": binding_buffer, "volume": bind_vol}],
156-
"Binding 2": [{"well": bind2_res, "volume": bind2_vol}],
157-
"Wash 1": [{"well": wash1_vol, "volume": wash1}],
158-
"Wash 2": [{"well": wash2_vol, "volume": wash2}],
159-
"Wash 3": [{"well": wash3_vol, "volume": wash3}],
160-
"Final Elution": [{"well": elution_solution, "volume": elution_vol}],
161-
"Samples": [{"well": samps, "volume": 0}],
151+
"Lysis and PK": [{"well": lysis_, "volume": 12320.0}],
152+
"Beads and Binding": [{"well": binding_buffer, "volume": 11875.0}],
153+
"Binding 2": [{"well": bind2_res, "volume": 13500.0}],
154+
"Final Elution": [{"well": elution_solution, "volume": 52000}],
155+
"Samples": [{"well": samps, "volume": 0.0}],
156+
"Reagents": [{"well": res2.wells(), "volume": 9000.0}],
162157
}
163158
flattened_list_of_wells = helpers.find_liquid_height_of_loaded_liquids(
164159
ctx, liquid_vols_and_wells, m1000

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,6 @@ def run(protocol: ProtocolContext) -> None:
121121
style=SINGLE, start="H1", tip_racks=[tiprack_x_1, tiprack_x_2, tiprack_x_3]
122122
)
123123
helpers.find_liquid_height_of_all_wells(protocol, p1000, wells)
124-
tiprack_x_1.reset()
125-
126124
sample_quant_csv = """
127125
sample_plate_1, Sample_well,DYE,DILUENT
128126
sample_plate_1,A1,0,100

abr-testing/abr_testing/protocols/helpers.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
ThermocyclerContext,
1515
TemperatureModuleContext,
1616
)
17-
1817
from typing import List, Union, Dict
1918
from opentrons.hardware_control.modules.types import ThermocyclerStep
2019
from opentrons_shared_data.errors.exceptions import PipetteLiquidNotFoundError
@@ -225,6 +224,31 @@ def create_hs_speed_parameter(parameters: ParameterContext) -> None:
225224
)
226225

227226

227+
def create_tc_compatible_labware_parameter(parameters: ParameterContext) -> None:
228+
"""Create parameter for labware type compatible with thermocycler."""
229+
parameters.add_str(
230+
variable_name="labware_tc_compatible",
231+
display_name="Labware Type for Thermocycler",
232+
description="labware compatible with thermocycler.",
233+
default="biorad_96_wellplate_200ul_pcr",
234+
choices=[
235+
{
236+
"display_name": "Armadillo_200ul",
237+
"value": "armadillo_96_wellplate_200ul_pcr_full_skirt",
238+
},
239+
{"display_name": "Bio-Rad_200ul", "value": "biorad_96_wellplate_200ul_pcr"},
240+
{
241+
"display_name": "NEST_100ul",
242+
"value": "nest_96_wellplate_100ul_pcr_full_skirt",
243+
},
244+
{
245+
"display_name": "Opentrons_200ul",
246+
"value": "opentrons_96_wellplate_200ul_pcr_full_skirt",
247+
},
248+
],
249+
)
250+
251+
228252
# FUNCTIONS FOR COMMON MODULE SEQUENCES
229253

230254

abr-testing/abr_testing/protocols/liquid_setups/10_ZymoBIOMICS Magbead Liquid Setup.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,35 @@ def run(protocol: protocol_api.ProtocolContext) -> None:
2929
res1 = protocol.load_labware("nest_12_reservoir_15ml", "C3", "R1")
3030
res2 = protocol.load_labware("nest_12_reservoir_15ml", "B3", "R2")
3131

32-
lysis_and_pk = (3200 + 320) / 8
33-
beads_and_binding = (275 + 6600) / 8
34-
binding2 = 5500 / 8
35-
wash1 = 5500 / 8
36-
final_elution = 2100 / 8
32+
lysis_and_pk = 12320 / 8
33+
beads_and_binding = 11875 / 8
34+
binding2 = 13500 / 8
3735
wash2 = 9000 / 8
38-
wash3 = 9000 / 8
36+
wash2_list = [wash2] * 12
3937
# Fill up Plates
4038
# Res1
4139
p1000.transfer(
42-
volume=[lysis_and_pk, beads_and_binding, binding2, wash1, final_elution],
40+
volume=[
41+
lysis_and_pk,
42+
beads_and_binding,
43+
beads_and_binding,
44+
beads_and_binding,
45+
binding2,
46+
binding2,
47+
binding2,
48+
binding2,
49+
binding2,
50+
],
4351
source=source_reservoir["A1"].bottom(z=0.2),
4452
dest=[
4553
res1["A1"].top(),
4654
res1["A2"].top(),
55+
res1["A3"].top(),
56+
res1["A4"].top(),
4757
res1["A5"].top(),
58+
res1["A6"].top(),
4859
res1["A7"].top(),
60+
res1["A8"].top(),
4961
res1["A12"].top(),
5062
],
5163
blow_out=True,
@@ -54,9 +66,9 @@ def run(protocol: protocol_api.ProtocolContext) -> None:
5466
)
5567
# Res2
5668
p1000.transfer(
57-
volume=[wash2, wash3],
69+
volume=wash2_list,
5870
source=source_reservoir["A1"],
59-
dest=[res2["A1"].top(), res2["A7"].top()],
71+
dest=res2.wells(),
6072
blow_out=True,
6173
blowout_location="source well",
6274
trash=False,
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"""Test TC Disposable Lid with BioRad Plate."""
2+
3+
from opentrons.protocol_api import (
4+
ProtocolContext,
5+
ParameterContext,
6+
Well,
7+
Labware,
8+
InstrumentContext,
9+
)
10+
from typing import List
11+
from abr_testing.protocols import helpers
12+
from opentrons.protocol_api.module_contexts import ThermocyclerContext
13+
from opentrons.hardware_control.modules.types import ThermocyclerStep
14+
15+
metadata = {"protocolName": "Tough Auto Seal Lid Evaporation Test"}
16+
requirements = {"robotType": "Flex", "apiLevel": "2.21"}
17+
18+
19+
def add_parameters(parameters: ParameterContext) -> None:
20+
"""Add Parameters."""
21+
helpers.create_single_pipette_mount_parameter(parameters)
22+
helpers.create_tc_lid_deck_riser_parameter(parameters)
23+
helpers.create_tc_compatible_labware_parameter(parameters)
24+
25+
26+
def _pcr_cycle(thermocycler: ThermocyclerContext) -> None:
27+
"""30x cycles of: 70° for 30s 72° for 30s 95° for 10s."""
28+
profile_TAG2: List[ThermocyclerStep] = [
29+
{"temperature": 70, "hold_time_seconds": 30},
30+
{"temperature": 72, "hold_time_seconds": 30},
31+
{"temperature": 95, "hold_time_seconds": 10},
32+
]
33+
thermocycler.execute_profile(
34+
steps=profile_TAG2, repetitions=30, block_max_volume=50
35+
)
36+
37+
38+
def _fill_with_liquid_and_measure(
39+
protocol: ProtocolContext,
40+
pipette: InstrumentContext,
41+
reservoir: Labware,
42+
plate_in_cycler: Labware,
43+
) -> None:
44+
"""Fill plate with 10 ul per well."""
45+
locations: List[Well] = [
46+
plate_in_cycler["A1"],
47+
plate_in_cycler["A2"],
48+
plate_in_cycler["A3"],
49+
plate_in_cycler["A4"],
50+
plate_in_cycler["A5"],
51+
plate_in_cycler["A6"],
52+
plate_in_cycler["A7"],
53+
plate_in_cycler["A8"],
54+
plate_in_cycler["A9"],
55+
plate_in_cycler["A10"],
56+
plate_in_cycler["A11"],
57+
plate_in_cycler["A12"],
58+
]
59+
volumes = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
60+
protocol.pause("Weight Armadillo Plate, place on thermocycler")
61+
# pipette 10uL into Armadillo wells
62+
source_well: Well = reservoir["A1"]
63+
pipette.distribute(
64+
volume=volumes,
65+
source=source_well,
66+
dest=locations,
67+
return_tips=True,
68+
blow_out=False,
69+
)
70+
protocol.pause("Weight Armadillo Plate, place on thermocycler, put on lid")
71+
72+
73+
def run(ctx: ProtocolContext) -> None:
74+
"""Evaporation Test."""
75+
pipette_mount = ctx.params.pipette_mount # type: ignore[attr-defined]
76+
deck_riser = ctx.params.deck_riser # type: ignore[attr-defined]
77+
labware_tc_compatible = ctx.params.labware_tc_compatible # type: ignore[attr-defined]
78+
tiprack_50 = ctx.load_labware("opentrons_flex_96_tiprack_50ul", "B2")
79+
ctx.load_trash_bin("A3")
80+
tc_mod: ThermocyclerContext = ctx.load_module(
81+
helpers.tc_str
82+
) # type: ignore[assignment]
83+
plate_in_cycler = tc_mod.load_labware(labware_tc_compatible)
84+
p50 = ctx.load_instrument("flex_8channel_50", pipette_mount, tip_racks=[tiprack_50])
85+
unused_lids = helpers.load_disposable_lids(ctx, 5, ["D2"], deck_riser)
86+
top_lid = unused_lids[0]
87+
reservoir = ctx.load_labware("nest_12_reservoir_15ml", "A2")
88+
tc_mod.open_lid()
89+
tc_mod.set_block_temperature(4)
90+
tc_mod.set_lid_temperature(105)
91+
92+
# hold at 95° for 3 minutes
93+
profile_TAG: List[ThermocyclerStep] = [{"temperature": 95, "hold_time_minutes": 3}]
94+
# hold at 72° for 5min
95+
profile_TAG3: List[ThermocyclerStep] = [{"temperature": 72, "hold_time_minutes": 5}]
96+
tc_mod.open_lid()
97+
_fill_with_liquid_and_measure(ctx, p50, reservoir, plate_in_cycler)
98+
ctx.move_labware(top_lid, plate_in_cycler, use_gripper=True)
99+
tc_mod.close_lid()
100+
tc_mod.execute_profile(steps=profile_TAG, repetitions=1, block_max_volume=50)
101+
_pcr_cycle(tc_mod)
102+
tc_mod.execute_profile(steps=profile_TAG3, repetitions=1, block_max_volume=50)
103+
# # # Cool to 4°
104+
tc_mod.set_block_temperature(4)
105+
tc_mod.set_lid_temperature(105)
106+
# Open lid
107+
tc_mod.open_lid()
108+
ctx.move_labware(top_lid, "C2", use_gripper=True)
109+
ctx.move_labware(top_lid, unused_lids[1], use_gripper=True)

0 commit comments

Comments
 (0)