Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(shared-data, api): Add evo tips definition and restrictions on loading #16710

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
0061a32
chore(shared-data): remove NODE_OPTIONS=--openssl-legacy-provider (#1…
koji Jan 6, 2025
d9ceb54
test(analyses): add 8.2 features to analyses battery (#17134)
y3rsh Jan 6, 2025
be4a6ee
feat(shared-data): add flex stacker definition and update module sche…
ahiuchingau Jan 6, 2025
d8bfa18
refactor(api): Delete obsolete re-exports (#17172)
SyntaxColoring Jan 7, 2025
189e325
feat(api): inner well geometry unit tests (#17082)
caila-marashaj Jan 7, 2025
b80b7b2
chore: fix canbus test warnings (#17192)
sfoster1 Jan 7, 2025
a699d48
chore: set abr-testing pydantic to 2.9 explicitly (#17200)
sfoster1 Jan 7, 2025
6621cea
fix(protocol-designer): add align-items to title part (#17165)
koji Jan 7, 2025
b070d8a
chore(protocol-designer): remove * as React from react (#17168)
koji Jan 7, 2025
7004a9f
fix(protocol-designer): fix paddings in release note modal (#17175)
koji Jan 7, 2025
692598f
fix(protocol-designer): allow custom labware on adapters (#17162)
jerader Jan 7, 2025
42fdc70
fix(protocol-designer): moving labware into waste chute step summary …
jerader Jan 7, 2025
ad0775d
fix(protocol-designer): remove unused packages from pd (#17166)
koji Jan 7, 2025
2adae99
fix(protocol-designer): release notes banner dismisses upon clicking …
jerader Jan 7, 2025
7dfa8bc
fix(components, protocol-designer, app) fix some broken stories (#17208)
koji Jan 8, 2025
68e8042
fix(protocol-designer): fix small condition issues (#17182)
koji Jan 8, 2025
09310aa
fix(protocol-designer): tooltip under path animation copy update (#17…
jerader Jan 8, 2025
62eb162
refactor(protocol-designer): liquid class ff reducer typo fix (#17211)
jerader Jan 8, 2025
4c498d7
chore(api): add absorbance reader module state update test (#17205)
TamarZanzouri Jan 8, 2025
de3813c
chore: update vite version to 5.4.11 (#17075)
koji Jan 8, 2025
a967f92
fix(step-generation): only aspirate disposal volume in first chunk (#…
jerader Jan 8, 2025
94cb0fa
refactor(components): refactor modal for web (app and pd) (#17193)
koji Jan 8, 2025
b63d5dc
feat(shared-data): add flex stacker addressable area to deck definiti…
ahiuchingau Jan 8, 2025
0fbd12f
fix(shared-data): find latest definition if version not specified (#…
caila-marashaj Jan 8, 2025
60af487
fix(protocol-designer): unify time format to display the time (#17221)
koji Jan 8, 2025
0ffff96
Revert "fix(shared-data): find latest definition if version not speci…
caila-marashaj Jan 8, 2025
b588c02
fix(protocol-designer): editing labware on top of a module and adapte…
jerader Dec 20, 2024
a683d37
fix(protocol-designer): allow minutesSeconds timer fields to add more…
jerader Jan 6, 2025
1970421
fix(step-generation): configureForVolume volume correctly set to am… …
jerader Jan 6, 2025
6aed4a7
fix(protocol-designer): padding adjustments with forms (#17227)
jerader Jan 9, 2025
7544b29
fix(protocol-designer): fix small DQA bugs (#17228)
ncdiehl11 Jan 9, 2025
2e0ebba
fix(robot-server): Fix `None` ambiguity in labware offset filtering (…
SyntaxColoring Jan 9, 2025
f761aa2
feat(protocol-designer): Make createNew.ts more robust and use it to …
alexjoel42 Jan 9, 2025
498a41b
feat(protocol-designer): yaml upload and download artifact version to…
jerader Jan 9, 2025
8557df7
feat(api, robot-server, shared-data): add FlexStacker module to the h…
vegano1 Jan 9, 2025
de12772
feat(shared-data, api): Add evo tips definition and restrictions on l…
Laura-Danielle Nov 6, 2024
455e066
feat(shared-data): Add evo flex tiprack adapter (#16707)
Laura-Danielle Dec 9, 2024
0f9b0f2
update definitions and fix typing issue
Laura-Danielle Dec 9, 2024
2e36fe9
fix: ensure wells are the same height and the schema has the new labw…
Laura-Danielle Dec 10, 2024
c49a87f
remove validation, add some additional quirks
Laura-Danielle Dec 12, 2024
fba9115
add additonal role for evo tips labware
Laura-Danielle Dec 12, 2024
06a47db
add labware defs to new def list and modify validation
Laura-Danielle Dec 13, 2024
1f947f9
update stacking only command
Laura-Danielle Dec 13, 2024
2c45fb1
modify the stacking depth for evotips and nest deepwell plate
Laura-Danielle Jan 8, 2025
8610479
include stack limit in evotips
CaseyBatten Jan 9, 2025
61019c0
update labware definition for new stacking rules
CaseyBatten Jan 9, 2025
67bbea9
update XYZ coordinates for the evotips opentrons 96 labware
Laura-Danielle Jan 9, 2025
37bc817
update compatible parent for evotip definitions
Laura-Danielle Jan 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/pd-test-build-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ jobs:
run: |
make -C protocol-designer NODE_ENV=development
- name: 'upload github artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: 'pd-artifact'
path: protocol-designer/dist
Expand Down Expand Up @@ -197,7 +197,7 @@ jobs:
const { buildComplexEnvVars } = require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/utils.js`)
buildComplexEnvVars(core, context)
- name: 'download PD build'
uses: 'actions/download-artifact@v3'
uses: 'actions/download-artifact@v4'
with:
name: pd-artifact
path: ./dist
Expand Down
1 change: 1 addition & 0 deletions abr-testing/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pandas = "*"
pandas-stubs = "*"
paramiko = "*"
prettier = "*"
pydantic = "==2.9.0"

[dev-packages]
atomicwrites = "==1.4.1"
Expand Down
1,261 changes: 569 additions & 692 deletions abr-testing/Pipfile.lock

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions analyses-snapshot-testing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,20 @@ You have the option to specify one or many protocols to run the analyses on. Thi
### Updating the snapshots locally

- `make snapshot-test-update-local` - this target builds the base image, builds the local code into the base image, then runs the analyses battery against the image you just created, updating the snapshots by passing the `--update-snapshots` flag to the test

### Add some protocols to the analyses battery

> The below instructions avoid needing docker and executing snapshot tests locally.

1. create new protocol file(s) in the [files/protocols](./files/protocols) directory following the naming convention in [files/README.md](./files/README.md)
1. add the protocol(s) to the [protocols.py](./automation/data/protocols.py)
1. `make format` (make sure you have followed setup instructions)
1. commit and push your branch
1. open a PR and add the label `gen-analyses-snapshot-pr`
1. when the snapshot fails because your new protocols don't have snapshots a PR will be created that heals.
1. merge the healing PR if the snapshots are as expected
1. get a review and merge! 🎉 now your protocols are a part of the test

### Add a protocol with overrides to the analyses battery

> TODO when we have a more straight forward example
42 changes: 42 additions & 0 deletions analyses-snapshot-testing/automation/data/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,48 @@ class Protocols:
file_extension="py",
robot="Flex",
)
# analyses-snapshot-testing/files/protocols/Flex_X_v2_21_plate_reader_no_trash.py
Flex_X_v2_21_plate_reader_no_trash: Protocol = Protocol(
file_stem="Flex_X_v2_21_plate_reader_no_trash",
file_extension="py",
robot="Flex",
)
# analyses-snapshot-testing/files/protocols/Flex_X_v2_21_plate_reader_wrong_plate.py
Flex_X_v2_21_plate_reader_wrong_plate: Protocol = Protocol(
file_stem="Flex_X_v2_21_plate_reader_wrong_plate",
file_extension="py",
robot="Flex",
)
# analyses-snapshot-testing/files/protocols/Flex_X_v2_21_plate_reader_wrong_plate2.py
Flex_X_v2_21_plate_reader_wrong_plate2: Protocol = Protocol(
file_stem="Flex_X_v2_21_plate_reader_wrong_plate2",
file_extension="py",
robot="Flex",
)
# analyses-snapshot-testing/files/protocols/Flex_X_v2_21_plate_reader_bad_slot.py
Flex_X_v2_21_plate_reader_bad_slot: Protocol = Protocol(
file_stem="Flex_X_v2_21_plate_reader_bad_slot",
file_extension="py",
robot="Flex",
)
# analyses-snapshot-testing/files/protocols/Flex_X_v2_21_plate_reader_no_close_lid.py
Flex_X_v2_21_plate_reader_no_close_lid: Protocol = Protocol(
file_stem="Flex_X_v2_21_plate_reader_no_close_lid",
file_extension="py",
robot="Flex",
)
# analyses-snapshot-testing/files/protocols/Flex_S_v2_21_tc_lids_happy_path.py
Flex_S_v2_21_tc_lids_happy_path: Protocol = Protocol(
file_stem="Flex_S_v2_21_tc_lids_happy_path",
file_extension="py",
robot="Flex",
)
# analyses-snapshot-testing/files/protocols/Flex_X_v2_21_tc_lids_wrong_target.py
Flex_X_v2_21_tc_lids_wrong_target: Protocol = Protocol(
file_stem="Flex_X_v2_21_tc_lids_wrong_target",
file_extension="py",
robot="Flex",
)

OT2_X_v2_18_None_None_duplicateRTPVariableName: Protocol = Protocol(
file_stem="OT2_X_v2_18_None_None_duplicateRTPVariableName",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
from typing import List, Dict, Any, Optional
from opentrons.protocol_api import ProtocolContext, Labware

metadata = {"protocolName": "Opentrons Flex Deck Riser with TC Lids Test"}
requirements = {"robotType": "Flex", "apiLevel": "2.21"}


"""
Setup:
- 1-5x lids are stacked in deck D2
- Thermocycler installed

Run:
- For each lid in the stack (1-5x)
- Move lid in D2 to Thermocycler
- Remove top-most lid
- PAUSE, wait for tester to press continue
- Move lid from Thermocycler to new slot C2
- Stacked onto any previously placed lids
"""

LID_STARTING_SLOT = "B2"
LID_ENDING_SLOT = "C2"
LID_COUNT = 3
LID_DEFINITION = "opentrons_tough_pcr_auto_sealing_lid"
LID_BOTTOM_DEFINITION = "opentrons_tough_pcr_auto_sealing_lid"
DECK_RISER_NAME = "opentrons_flex_deck_riser"
USING_THERMOCYCLER = True

OFFSET_DECK = {
"pick-up": {"x": 0, "y": 0, "z": 0},
"drop": {"x": 0, "y": 0, "z": 0},
}
OFFSET_THERMOCYCLER = {
"pick-up": {"x": 0, "y": 0, "z": 0},
"drop": {"x": 0, "y": 0, "z": 0},
}


def _move_labware_with_offset_and_pause(
protocol: ProtocolContext,
labware: Labware,
destination: Any,
pick_up_offset: Optional[Dict[str, float]] = None,
drop_offset: Optional[Dict[str, float]] = None,
) -> None:
protocol.move_labware(
labware,
destination,
use_gripper=True,
pick_up_offset=pick_up_offset,
drop_offset=drop_offset,
)


def run(protocol: ProtocolContext):
# SETUP
deck_riser_adapter = protocol.load_adapter(DECK_RISER_NAME, "B2")

lids: List[Labware] = [deck_riser_adapter.load_labware(LID_BOTTOM_DEFINITION)]
for i in range(LID_COUNT - 1):
lids.append(lids[-1].load_labware(LID_DEFINITION))
lids.reverse() # NOTE: reversing to more easily loop through lids from top-to-bottom
if USING_THERMOCYCLER:
# TODO: confirm if we need to load 96-well adapter onto Thermocycler
thermocycler = protocol.load_module("thermocyclerModuleV2")
thermocycler.open_lid()
plate_in_cycler = thermocycler.load_labware("armadillo_96_wellplate_200ul_pcr_full_skirt")
else:
plate_in_cycler = None

# RUN
prev_moved_lid: Optional[Labware] = None
for lid in lids:

if USING_THERMOCYCLER:
_move_labware_with_offset_and_pause(
protocol,
lid,
plate_in_cycler,
pick_up_offset=OFFSET_DECK["pick-up"],
drop_offset=OFFSET_THERMOCYCLER["drop"],
)
_move_labware_with_offset_and_pause(
protocol,
lid,
prev_moved_lid if prev_moved_lid else LID_ENDING_SLOT,
pick_up_offset=OFFSET_THERMOCYCLER["pick-up"],
drop_offset=OFFSET_DECK["drop"],
)
else:
_move_labware_with_offset_and_pause(
protocol,
lid,
prev_moved_lid if prev_moved_lid else LID_ENDING_SLOT,
pick_up_offset=OFFSET_DECK["pick-up"],
drop_offset=OFFSET_DECK["drop"],
)
prev_moved_lid = lid
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import cast
from opentrons import protocol_api
from opentrons.protocol_api.module_contexts import AbsorbanceReaderContext

from opentrons import protocol_api
from opentrons.protocol_api import SINGLE, ALL

requirements = {"robotType": "Flex", "apiLevel": "2.21"}
metadata = {"protocolName": "plate_reader bad slot"}


def run(protocol: protocol_api.ProtocolContext):
partial_rack = protocol.load_labware(load_name="opentrons_flex_96_tiprack_1000ul", location="D3")
trash = protocol.load_trash_bin("A3")
instrument = protocol.load_instrument(instrument_name="flex_8channel_1000", mount="right")
instrument.configure_nozzle_layout(style=SINGLE, start="H1", tip_racks=[partial_rack])

plate_1 = protocol.load_labware("nest_96_wellplate_200ul_flat", "D1")
mod = protocol.load_module("absorbanceReaderV1", "C1")
mod.open_lid()
protocol.move_labware(plate_1, mod, use_gripper=True)
mod.close_lid()
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from typing import cast
from opentrons import protocol_api
from opentrons.protocol_api.module_contexts import AbsorbanceReaderContext

# metadata
metadata = {
"protocolName": "Absorbance Reader no close lid",
"author": "Platform Expansion",
}

requirements = {
"robotType": "Flex",
"apiLevel": "2.21",
}


# protocol run function
def run(protocol: protocol_api.ProtocolContext):
mod = cast(AbsorbanceReaderContext, protocol.load_module("absorbanceReaderV1", "D3"))
plate = protocol.load_labware("nest_96_wellplate_200ul_flat", "C2")
tiprack_1000 = protocol.load_labware(load_name="opentrons_flex_96_tiprack_50ul", location="B2")
trash_labware = protocol.load_trash_bin("B3")
instrument = protocol.load_instrument("flex_8channel_50", "right", tip_racks=[tiprack_1000])

# pick up tip and perform action
instrument.pick_up_tip(tiprack_1000.wells_by_name()["A1"])
instrument.aspirate(30, plate.wells_by_name()["A1"])
instrument.dispense(30, plate.wells_by_name()["B1"])
instrument.return_tip()

# Initialize to a single wavelength with reference wavelength
# Issue: Make sure there is no labware here or youll get an error
# mod.close_lid()
mod.initialize("single", [600], 450)

# NOTE: CANNOT INITIALIZE WITH THE LID OPEN

# Remove the Plate Reader lid using the Gripper.
mod.open_lid()
protocol.move_labware(plate, mod, use_gripper=True)
mod.close_lid()

# Take a reading and show the resulting absorbance values.
# Issue: cant read before you initialize or you an get an error
result = mod.read()
msg = f"single: {result}"
protocol.comment(msg=msg)
protocol.pause(msg=msg)

# Initialize to multiple wavelengths
protocol.pause(msg="Perform Multi Read")
mod.open_lid()
protocol.move_labware(plate, "C2", use_gripper=True)

mod.close_lid()

# mod.initialize('multi', [450, 570, 600])
mod.initialize("multi", [450, 600])
# Open the lid and move the labware into the reader
mod.open_lid()
protocol.move_labware(plate, mod, use_gripper=True)

# pick up tip and perform action on labware inside plate reader
instrument.pick_up_tip(tiprack_1000.wells_by_name()["A1"])
instrument.aspirate(30, plate.wells_by_name()["A1"])
instrument.dispense(30, plate.wells_by_name()["B1"])
instrument.return_tip()

mod.close_lid()

# Take reading
result = mod.read()
msg = f"multi: {result}"
protocol.comment(msg=msg)
protocol.pause(msg=msg)

# Take a reading and save to csv
protocol.pause(msg="Perform Read and Save to CSV")
result = mod.read(export_filename="plate_reader_csv.csv")
msg = f"csv: {result}"
protocol.pause(msg=msg)

# Place the Plate Reader lid back on using the Gripper.
mod.open_lid()
protocol.move_labware(plate, "C2", use_gripper=True)
mod.close_lid()

mod.read(export_filename="csv_name.csv")
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from typing import cast
from opentrons import protocol_api
from opentrons.protocol_api.module_contexts import AbsorbanceReaderContext

from opentrons import protocol_api
from opentrons.protocol_api import SINGLE, ALL

requirements = {"robotType": "Flex", "apiLevel": "2.21"}
metadata = {"protocolName": "plate_reader no trash"}


def run(protocol: protocol_api.ProtocolContext):
partial_rack = protocol.load_labware(load_name="opentrons_flex_96_tiprack_1000ul", location="D2")
trash = protocol.load_trash_bin("A3")
instrument = protocol.load_instrument(instrument_name="flex_8channel_1000", mount="right")
instrument.configure_nozzle_layout(style=SINGLE, start="H1", tip_racks=[partial_rack])

plate_1 = protocol.load_labware("nest_96_wellplate_200ul_flat", "C1")

mod = protocol.load_module("absorbanceReaderV1", "B3")

mod.open_lid()
protocol.move_labware(plate_1, mod, use_gripper=True)
protocol.move_labware(plate_1, trash, use_gripper=True)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from typing import cast
from opentrons import protocol_api
from opentrons.protocol_api.module_contexts import AbsorbanceReaderContext

from opentrons import protocol_api
from opentrons.protocol_api import SINGLE, ALL

requirements = {"robotType": "Flex", "apiLevel": "2.21"}
metadata = {"protocolName": "plate_reader wrong plate"}


def run(protocol: protocol_api.ProtocolContext):
partial_rack = protocol.load_labware(load_name="opentrons_flex_96_tiprack_1000ul", location="D2")
trash = protocol.load_trash_bin("A3")
instrument = protocol.load_instrument(instrument_name="flex_8channel_1000", mount="right")
instrument.configure_nozzle_layout(style=SINGLE, start="H1", tip_racks=[partial_rack])

plate_1 = protocol.load_labware("corning_12_wellplate_6.9ml_flat", "C2")

mod = protocol.load_module("absorbanceReaderV1", "B3")

mod.open_lid()
protocol.move_labware(plate_1, mod, use_gripper=True)
protocol.move_labware(plate_1, trash, use_gripper=True)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from typing import cast
from opentrons import protocol_api
from opentrons.protocol_api.module_contexts import AbsorbanceReaderContext

from opentrons import protocol_api
from opentrons.protocol_api import SINGLE, ALL

requirements = {"robotType": "Flex", "apiLevel": "2.21"}
metadata = {"protocolName": "plate_reader wrong plate"}


def run(protocol: protocol_api.ProtocolContext):
partial_rack = protocol.load_labware(load_name="opentrons_flex_96_tiprack_1000ul", location="D2")
trash = protocol.load_trash_bin("A3")
instrument = protocol.load_instrument(instrument_name="flex_8channel_1000", mount="right")
instrument.configure_nozzle_layout(style=SINGLE, start="H1", tip_racks=[partial_rack])

plate_1 = protocol.load_labware("thermoscientificnunc_96_wellplate_2000ul", "C2")

mod = protocol.load_module("absorbanceReaderV1", "B3")

mod.open_lid()
protocol.move_labware(plate_1, mod, use_gripper=True)
protocol.move_labware(plate_1, trash, use_gripper=True)
Loading
Loading