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

fix(api): enable deck conflict checker for the flex #13189

Merged
merged 35 commits into from
Aug 7, 2023

Conversation

TamarZanzouri
Copy link
Contributor

@TamarZanzouri TamarZanzouri commented Jul 28, 2023

Overview

closes https://opentrons.atlassian.net/browse/RSS-294 -> enable deck_conflict checker for the flex..
closes https://opentrons.atlassian.net/browse/RSS-273 -> fixes bug when loading a thermocycler in slots that are not allowed.
closes https://opentrons.atlassian.net/browse/RQA-993 -> does not allow loading mag deck's on an OT-3. just mag blocks.

Test Plan

  • Allow an OT-3 protocol with modules as described here. make sure no exception is being raise.
from opentrons import protocol_api, types

metadata = {
    "apiLevel": "2.15",
}

requirements = {
    "robotType": "OT-3"
}

def run(ctx: protocol_api.ProtocolContext) -> None:
    tip_rack_50 = ctx.load_labware("opentrons_ot3_96_tiprack_50ul", 4)
    tip_rack_200 = ctx.load_labware("opentrons_flex_96_tiprack_200ul", 5)
    tip_rack_1000 = ctx.load_labware("opentrons_ot3_96_tiprack_1000ul", 6)
    heatershaker = ctx.load_module('heaterShakerModuleV1',1)
    heatershaker = ctx.load_module('thermocyclerModuleV2')
    mag_block = ctx.load_module('magneticBlockV1',2)
    temp = ctx.load_module('temperatureModuleV2', 3)
  • Try loading a module on the flex in a middle slot. make sure you are getting an exception.
from opentrons import protocol_api, types

metadata = {
    "apiLevel": "2.15",
}

requirements = {
    "robotType": "OT-3"
}

def run(ctx: protocol_api.ProtocolContext) -> None:
    # this should fail bc h/s is not allowed in the middle.
    mag_block = ctx.load_module('heaterShakerModuleV1',2)
  • Try loading 2 modules on the flex in same slot slot. make sure you are getting an exception.
from opentrons import protocol_api, types

metadata = {
    "apiLevel": "2.15",
}

requirements = {
    "robotType": "OT-3"
}

def run(ctx: protocol_api.ProtocolContext) -> None:
    tip_rack_50 = ctx.load_labware("opentrons_ot3_96_tiprack_50ul", 4)
    tip_rack_200 = ctx.load_labware("opentrons_flex_96_tiprack_200ul", 5)
    tip_rack_1000 = ctx.load_labware("opentrons_ot3_96_tiprack_1000ul", 2)
    heatershaker = ctx.load_module('heaterShakerModuleV1',1)
    # this should fail bc h/s is already loaded in slot 1
    mag_block = ctx.load_module('magneticBlockV1',1)
  • Should fail bc mag decks are not allowed on the flex.
from opentrons import protocol_api, types

metadata = {
    "apiLevel": "2.15",
}

requirements = {
    "robotType": "OT-3"
}

def run(ctx: protocol_api.ProtocolContext) -> None:
    # this should fail bc h/s is not allowed in the middle.
    mag_deck = ctx.load_module('magneticModuleV2',1)
  • Should fail bc thermocyclers are not allowed in slot 1.
from opentrons import protocol_api, types

metadata = {
    "apiLevel": "2.15",
}

requirements = {
    "robotType": "OT-3"
}

def run(ctx: protocol_api.ProtocolContext) -> None:
    # this should fail bc h/s is not allowed in the middle.
    thermo = ctx.load_module('thermocyclerModuleV2',1)
  • Smoke test OT-2 protocols and make sure it all works as expected.
  • I have also created an integration test for that
  • We should test this with the app and a mag block in a protocol to make sure that it appears properly in the app

Changelog

  • Change deck_conflict.check to get DeckSlotName for the new location and and existing location instead of int.
  • Added robot_type arg inorder to know what restrictions to load.
  • Changed all access with method to DeckSlotName instead of int.
  • Added integration test for a failed protocol
  • Updated all tests to use DeckSlotName instead of int/str
  • Make sure you are able to load the thermocycler in allowed slots.
  • Added slot validation for load_module in protocol core

Review requests

Changes make sense? Did I forget anything?

Risk assessment

Medium. need to smoke test OT-2 protocols both json on python for all version (We care about) to make sure loading labware/modules on deck has been affected. need to test OT-3 protocols and to make sure load_module is raising an exception for the restrictions in the ticket.

@codecov
Copy link

codecov bot commented Jul 28, 2023

Codecov Report

Merging #13189 (759061c) into edge (8d6e391) will increase coverage by 0.23%.
Report is 60 commits behind head on edge.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##             edge   #13189      +/-   ##
==========================================
+ Coverage   72.18%   72.42%   +0.23%     
==========================================
  Files        1567     2393     +826     
  Lines       51763    66292   +14529     
  Branches     3268     7364    +4096     
==========================================
+ Hits        37366    48010   +10644     
- Misses      13881    16515    +2634     
- Partials      516     1767    +1251     
Flag Coverage Δ
app 71.32% <ø> (+27.38%) ⬆️
g-code-testing 96.44% <ø> (ø)
notify-server 89.13% <ø> (ø)
protocol-designer 47.13% <ø> (-0.16%) ⬇️
shared-data 75.11% <ø> (-3.06%) ⬇️
step-generation 87.18% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

see 874 files with indirect coverage changes

@@ -184,10 +191,13 @@ def check(
DeckConflictError: Adding this item should not be allowed.
"""
restrictions: List[_DeckRestriction] = [_FixedTrashOnly()]

if robot_type == "OT-2 Standard":
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hate this

Copy link
Contributor

@Laura-Danielle Laura-Danielle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial comments, but overall looks pretty good to me. Agree w/ Max that you should not be using Unions here though.

)
)

elif isinstance(item, (HeaterShakerModule, TemperatureModule)):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these restrictions still valid? The spacing between slots is very different on the flex.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed with Chris that this is still mandatory. also PD still has restrictions.

new_item: DeckItem,
new_location: int,
new_location: Union[int, str],
robot_type: str = "OT-2 Standard",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is totally reasonable to do, but if you really hate it you could create a enum and/or bitfield in which you can specify what items you want to check for collisions and push up the robot type check higher.

restrictions: List[_DeckRestriction] = []

if isinstance(item, ThermocyclerModule):
for covered_location in _flex_slots_covered_by_thermocycler():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the TC could be in multiple slots, is this not the case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its no slot 7,10. I am setting both slots as occupied if we are in the TC case

api/src/opentrons/motion_planning/deck_conflict.py Outdated Show resolved Hide resolved
@TamarZanzouri TamarZanzouri changed the title Rss 294 deck conflict checker for flex fix(api): enable deck conflict checker for the flex Aug 2, 2023
@TamarZanzouri TamarZanzouri marked this pull request as ready for review August 2, 2023 18:17
@TamarZanzouri TamarZanzouri requested review from a team as code owners August 2, 2023 18:17
@TamarZanzouri TamarZanzouri marked this pull request as draft August 3, 2023 01:07
if module_type == ModuleType.THERMOCYCLER:
deck_slot = (
DeckSlotName.SLOT_7
if self._engine_client.state.config.robot_type == "OT-2 Standard"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can also use deck robot property but this feels the same. comparing a string.

@TamarZanzouri TamarZanzouri marked this pull request as ready for review August 3, 2023 20:39
@@ -167,7 +167,8 @@
"magneticModuleType",
"temperatureModuleType",
"thermocyclerModuleType",
"heaterShakerModuleType"
"heaterShakerModuleType",
"magneticBlockType"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do we think about this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with it. We treat it as a module essentially anyways.

Copy link
Contributor

@Laura-Danielle Laura-Danielle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Have some small comments that you can ignore.

source_item=item,
source_location=location,
)
)

for covered_location in get_east_west_slots(location):
for hs_covered_location in get_east_west_slots(location.as_int()):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these functions also take in DeckSlotNames and perform the check on that type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tired doing it but its tied to much to the legacy implementation and we are already parsing this as int in other places so might as well leave it

api/src/opentrons/protocol_api/core/engine/protocol.py Outdated Show resolved Hide resolved
@@ -167,7 +167,8 @@
"magneticModuleType",
"temperatureModuleType",
"thermocyclerModuleType",
"heaterShakerModuleType"
"heaterShakerModuleType",
"magneticBlockType"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with it. We treat it as a module essentially anyways.

Copy link
Contributor

@SyntaxColoring SyntaxColoring left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! One question about the fixed trash, and a few other minor suggestions.

Copy link
Contributor

@SyntaxColoring SyntaxColoring left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good to me. Thanks!

) -> None:
"""Check a deck layout for conflicts.

Args:
existing_items: Existing items on the deck, assumed to be valid.
new_item: New item to add to the deck.
new_location: Location where the new item will be added.
robot_type: Robot deck definition.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nitpick and I think we should merge this now anyway, but for future reference, the RobotType is not exactly the deck definition.

The OT-2 has one RobotType ("OT-2 Standard"), but two possible deck definitions (ot2_standard and ot2_short_trash). The names are very confusing.

@TamarZanzouri
Copy link
Contributor Author

TamarZanzouri commented Aug 7, 2023

Tested ot OT-3:
loading modules where they are allowed
loading modules where they are not allowed and getting the proper error.
loading mag decks will raise an error.

Smoke tested OT-2 as well. Works as expected!

Copy link
Contributor

@SyntaxColoring SyntaxColoring left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yep. Fix makes sense to me. Nice catch.

Copy link
Member

@sanni-t sanni-t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 🙌

api/src/opentrons/motion_planning/deck_conflict.py Outdated Show resolved Hide resolved
@TamarZanzouri TamarZanzouri merged commit 136f933 into edge Aug 7, 2023
48 checks passed
@TamarZanzouri TamarZanzouri deleted the RSS-294-deck-conflict-checker-for-flex branch August 7, 2023 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants