Skip to content

Commit

Permalink
feat(abr-testing): protocol to test disposable lid with any pcr plate…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
rclarke0 authored Nov 15, 2024
1 parent 450c562 commit 383f7ce
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ def run(ctx: protocol_api.ProtocolContext) -> None:
bind_time_1 = bind_time_2 = wash_time = 0.25
drybeads = 0.5
lysis_rep_1 = lysis_rep_2 = bead_reps_2 = 1
PK_vol = 20.0
bead_vol = 25.0
starting_vol = lysis_vol + sample_vol
binding_buffer_vol = bind_vol + bead_vol
Expand Down Expand Up @@ -137,7 +136,7 @@ def run(ctx: protocol_api.ProtocolContext) -> None:
"""
lysis_ = res1.wells()[0]
binding_buffer = res1.wells()[1:4]
bind2_res = res1.wells()[4:6]
bind2_res = res1.wells()[4:8]
wash1 = res1.wells()[6:8]
elution_solution = res1.wells()[-1]
wash2 = res2.wells()[:6]
Expand All @@ -149,16 +148,12 @@ def run(ctx: protocol_api.ProtocolContext) -> None:
samps = sample_plate.wells()[: (8 * num_cols)]

liquid_vols_and_wells: Dict[str, List[Dict[str, Well | List[Well] | float]]] = {
"Lysis": [{"well": lysis_, "volume": lysis_vol}],
"PK": [{"well": lysis_, "volume": PK_vol}],
"Beads": [{"well": binding_buffer, "volume": bead_vol}],
"Binding": [{"well": binding_buffer, "volume": bind_vol}],
"Binding 2": [{"well": bind2_res, "volume": bind2_vol}],
"Wash 1": [{"well": wash1_vol, "volume": wash1}],
"Wash 2": [{"well": wash2_vol, "volume": wash2}],
"Wash 3": [{"well": wash3_vol, "volume": wash3}],
"Final Elution": [{"well": elution_solution, "volume": elution_vol}],
"Samples": [{"well": samps, "volume": 0}],
"Lysis and PK": [{"well": lysis_, "volume": 12320.0}],
"Beads and Binding": [{"well": binding_buffer, "volume": 11875.0}],
"Binding 2": [{"well": bind2_res, "volume": 13500.0}],
"Final Elution": [{"well": elution_solution, "volume": 52000}],
"Samples": [{"well": samps, "volume": 0.0}],
"Reagents": [{"well": res2.wells(), "volume": 9000.0}],
}
flattened_list_of_wells = helpers.find_liquid_height_of_loaded_liquids(
ctx, liquid_vols_and_wells, m1000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ def run(protocol: ProtocolContext) -> None:
style=SINGLE, start="H1", tip_racks=[tiprack_x_1, tiprack_x_2, tiprack_x_3]
)
helpers.find_liquid_height_of_all_wells(protocol, p1000, wells)
tiprack_x_1.reset()

sample_quant_csv = """
sample_plate_1, Sample_well,DYE,DILUENT
sample_plate_1,A1,0,100
Expand Down
26 changes: 25 additions & 1 deletion abr-testing/abr_testing/protocols/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
ThermocyclerContext,
TemperatureModuleContext,
)

from typing import List, Union, Dict
from opentrons.hardware_control.modules.types import ThermocyclerStep
from opentrons_shared_data.errors.exceptions import PipetteLiquidNotFoundError
Expand Down Expand Up @@ -225,6 +224,31 @@ def create_hs_speed_parameter(parameters: ParameterContext) -> None:
)


def create_tc_compatible_labware_parameter(parameters: ParameterContext) -> None:
"""Create parameter for labware type compatible with thermocycler."""
parameters.add_str(
variable_name="labware_tc_compatible",
display_name="Labware Type for Thermocycler",
description="labware compatible with thermocycler.",
default="biorad_96_wellplate_200ul_pcr",
choices=[
{
"display_name": "Armadillo_200ul",
"value": "armadillo_96_wellplate_200ul_pcr_full_skirt",
},
{"display_name": "Bio-Rad_200ul", "value": "biorad_96_wellplate_200ul_pcr"},
{
"display_name": "NEST_100ul",
"value": "nest_96_wellplate_100ul_pcr_full_skirt",
},
{
"display_name": "Opentrons_200ul",
"value": "opentrons_96_wellplate_200ul_pcr_full_skirt",
},
],
)


# FUNCTIONS FOR COMMON MODULE SEQUENCES


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,35 @@ def run(protocol: protocol_api.ProtocolContext) -> None:
res1 = protocol.load_labware("nest_12_reservoir_15ml", "C3", "R1")
res2 = protocol.load_labware("nest_12_reservoir_15ml", "B3", "R2")

lysis_and_pk = (3200 + 320) / 8
beads_and_binding = (275 + 6600) / 8
binding2 = 5500 / 8
wash1 = 5500 / 8
final_elution = 2100 / 8
lysis_and_pk = 12320 / 8
beads_and_binding = 11875 / 8
binding2 = 13500 / 8
wash2 = 9000 / 8
wash3 = 9000 / 8
wash2_list = [wash2] * 12
# Fill up Plates
# Res1
p1000.transfer(
volume=[lysis_and_pk, beads_and_binding, binding2, wash1, final_elution],
volume=[
lysis_and_pk,
beads_and_binding,
beads_and_binding,
beads_and_binding,
binding2,
binding2,
binding2,
binding2,
binding2,
],
source=source_reservoir["A1"].bottom(z=0.2),
dest=[
res1["A1"].top(),
res1["A2"].top(),
res1["A3"].top(),
res1["A4"].top(),
res1["A5"].top(),
res1["A6"].top(),
res1["A7"].top(),
res1["A8"].top(),
res1["A12"].top(),
],
blow_out=True,
Expand All @@ -54,9 +66,9 @@ def run(protocol: protocol_api.ProtocolContext) -> None:
)
# Res2
p1000.transfer(
volume=[wash2, wash3],
volume=wash2_list,
source=source_reservoir["A1"],
dest=[res2["A1"].top(), res2["A7"].top()],
dest=res2.wells(),
blow_out=True,
blowout_location="source well",
trash=False,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""Test TC Disposable Lid with BioRad Plate."""

from opentrons.protocol_api import (
ProtocolContext,
ParameterContext,
Well,
Labware,
InstrumentContext,
)
from typing import List
from abr_testing.protocols import helpers
from opentrons.protocol_api.module_contexts import ThermocyclerContext
from opentrons.hardware_control.modules.types import ThermocyclerStep

metadata = {"protocolName": "Tough Auto Seal Lid Evaporation Test"}
requirements = {"robotType": "Flex", "apiLevel": "2.21"}


def add_parameters(parameters: ParameterContext) -> None:
"""Add Parameters."""
helpers.create_single_pipette_mount_parameter(parameters)
helpers.create_tc_lid_deck_riser_parameter(parameters)
helpers.create_tc_compatible_labware_parameter(parameters)


def _pcr_cycle(thermocycler: ThermocyclerContext) -> None:
"""30x cycles of: 70° for 30s 72° for 30s 95° for 10s."""
profile_TAG2: List[ThermocyclerStep] = [
{"temperature": 70, "hold_time_seconds": 30},
{"temperature": 72, "hold_time_seconds": 30},
{"temperature": 95, "hold_time_seconds": 10},
]
thermocycler.execute_profile(
steps=profile_TAG2, repetitions=30, block_max_volume=50
)


def _fill_with_liquid_and_measure(
protocol: ProtocolContext,
pipette: InstrumentContext,
reservoir: Labware,
plate_in_cycler: Labware,
) -> None:
"""Fill plate with 10 ul per well."""
locations: List[Well] = [
plate_in_cycler["A1"],
plate_in_cycler["A2"],
plate_in_cycler["A3"],
plate_in_cycler["A4"],
plate_in_cycler["A5"],
plate_in_cycler["A6"],
plate_in_cycler["A7"],
plate_in_cycler["A8"],
plate_in_cycler["A9"],
plate_in_cycler["A10"],
plate_in_cycler["A11"],
plate_in_cycler["A12"],
]
volumes = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
protocol.pause("Weight Armadillo Plate, place on thermocycler")
# pipette 10uL into Armadillo wells
source_well: Well = reservoir["A1"]
pipette.distribute(
volume=volumes,
source=source_well,
dest=locations,
return_tips=True,
blow_out=False,
)
protocol.pause("Weight Armadillo Plate, place on thermocycler, put on lid")


def run(ctx: ProtocolContext) -> None:
"""Evaporation Test."""
pipette_mount = ctx.params.pipette_mount # type: ignore[attr-defined]
deck_riser = ctx.params.deck_riser # type: ignore[attr-defined]
labware_tc_compatible = ctx.params.labware_tc_compatible # type: ignore[attr-defined]
tiprack_50 = ctx.load_labware("opentrons_flex_96_tiprack_50ul", "B2")
ctx.load_trash_bin("A3")
tc_mod: ThermocyclerContext = ctx.load_module(
helpers.tc_str
) # type: ignore[assignment]
plate_in_cycler = tc_mod.load_labware(labware_tc_compatible)
p50 = ctx.load_instrument("flex_8channel_50", pipette_mount, tip_racks=[tiprack_50])
unused_lids = helpers.load_disposable_lids(ctx, 5, ["D2"], deck_riser)
top_lid = unused_lids[0]
reservoir = ctx.load_labware("nest_12_reservoir_15ml", "A2")
tc_mod.open_lid()
tc_mod.set_block_temperature(4)
tc_mod.set_lid_temperature(105)

# hold at 95° for 3 minutes
profile_TAG: List[ThermocyclerStep] = [{"temperature": 95, "hold_time_minutes": 3}]
# hold at 72° for 5min
profile_TAG3: List[ThermocyclerStep] = [{"temperature": 72, "hold_time_minutes": 5}]
tc_mod.open_lid()
_fill_with_liquid_and_measure(ctx, p50, reservoir, plate_in_cycler)
ctx.move_labware(top_lid, plate_in_cycler, use_gripper=True)
tc_mod.close_lid()
tc_mod.execute_profile(steps=profile_TAG, repetitions=1, block_max_volume=50)
_pcr_cycle(tc_mod)
tc_mod.execute_profile(steps=profile_TAG3, repetitions=1, block_max_volume=50)
# # # Cool to 4°
tc_mod.set_block_temperature(4)
tc_mod.set_lid_temperature(105)
# Open lid
tc_mod.open_lid()
ctx.move_labware(top_lid, "C2", use_gripper=True)
ctx.move_labware(top_lid, unused_lids[1], use_gripper=True)

0 comments on commit 383f7ce

Please sign in to comment.