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): add custom & default thermocycler overlap offsets … #13750

Merged
merged 1 commit into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 16 additions & 1 deletion api/src/opentrons/protocol_engine/state/labware.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,12 +560,27 @@ def get_module_overlap_offsets(
"""Get the labware's overlap with requested module model."""
definition = self.get_definition(labware_id)
stacking_overlap = definition.stackingOffsetWithModule.get(
str(module_model.value), OverlapOffset(x=0, y=0, z=0)
str(module_model.value)
)
if not stacking_overlap:
if self._is_thermocycler_on_ot2(module_model):
return OverlapOffset(x=0, y=0, z=10.7)
else:
return OverlapOffset(x=0, y=0, z=0)

return OverlapOffset(
x=stacking_overlap.x, y=stacking_overlap.y, z=stacking_overlap.z
)

def _is_thermocycler_on_ot2(self, module_model: ModuleModel) -> bool:
"""Whether the given module is a thermocycler with the current deck being an OT2 deck."""
robot_model = self.get_deck_definition()["robot"]["model"]
return (
module_model
in [ModuleModel.THERMOCYCLER_MODULE_V1, ModuleModel.THERMOCYCLER_MODULE_V2]
and robot_model == "OT-2 Standard"
)

def get_default_magnet_height(self, module_id: str, offset: float) -> float:
"""Return a labware's default Magnetic Module engage height with added offset, if supplied.

Expand Down
92 changes: 81 additions & 11 deletions api/tests/opentrons/protocol_engine/state/test_labware_view.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Labware state store tests."""
import pytest
from datetime import datetime
from typing import Dict, Optional, cast, ContextManager, Any, Union
from typing import Dict, Optional, cast, ContextManager, Any, Union, NamedTuple, List
from contextlib import nullcontext as does_not_raise

from opentrons_shared_data.deck import load as load_deck
from opentrons_shared_data.deck.dev_types import DeckDefinitionV3
from opentrons_shared_data.pipette.dev_types import LabwareUri
from opentrons_shared_data.labware.labware_definition import (
Expand All @@ -13,6 +14,11 @@
GripperOffsets,
OffsetVector,
)

from opentrons.protocols.api_support.deck_type import (
STANDARD_OT2_DECK,
STANDARD_OT3_DECK,
)
from opentrons.protocols.models import LabwareDefinition
from opentrons.types import DeckSlotName, Point, MountType

Expand All @@ -39,7 +45,6 @@
LabwareLoadParams,
)


plate = LoadedLabware(
id="plate-id",
loadName="plate-load-name",
Expand Down Expand Up @@ -686,26 +691,91 @@ def test_get_labware_overlap_offsets() -> None:
assert result == OverlapOffset(x=1, y=2, z=3)


def test_get_module_overlap_offsets() -> None:
class ModuleOverlapSpec(NamedTuple):
"""Spec data to test LabwareView.get_module_overlap_offsets."""

spec_deck_definition: DeckDefinitionV3
module_model: ModuleModel
stacking_offset_with_module: Dict[str, SharedDataOverlapOffset]
expected_offset: OverlapOffset


module_overlap_specs: List[ModuleOverlapSpec] = [
ModuleOverlapSpec(
# Labware on temp module on OT2, with stacking overlap for temp module
spec_deck_definition=load_deck(STANDARD_OT2_DECK, 3),
module_model=ModuleModel.TEMPERATURE_MODULE_V2,
stacking_offset_with_module={
str(ModuleModel.TEMPERATURE_MODULE_V2.value): SharedDataOverlapOffset(
x=1, y=2, z=3
),
},
expected_offset=OverlapOffset(x=1, y=2, z=3),
),
ModuleOverlapSpec(
# Labware on TC Gen1 on OT2, with stacking overlap for TC Gen1
spec_deck_definition=load_deck(STANDARD_OT2_DECK, 3),
module_model=ModuleModel.THERMOCYCLER_MODULE_V1,
stacking_offset_with_module={
str(ModuleModel.THERMOCYCLER_MODULE_V1.value): SharedDataOverlapOffset(
x=11, y=22, z=33
),
},
expected_offset=OverlapOffset(x=11, y=22, z=33),
),
ModuleOverlapSpec(
# Labware on TC Gen2 on OT2, with no stacking overlap
spec_deck_definition=load_deck(STANDARD_OT2_DECK, 3),
module_model=ModuleModel.THERMOCYCLER_MODULE_V2,
stacking_offset_with_module={},
expected_offset=OverlapOffset(x=0, y=0, z=10.7),
),
ModuleOverlapSpec(
# Labware on TC Gen2 on Flex, with no stacking overlap
spec_deck_definition=load_deck(STANDARD_OT3_DECK, 3),
module_model=ModuleModel.THERMOCYCLER_MODULE_V2,
stacking_offset_with_module={},
expected_offset=OverlapOffset(x=0, y=0, z=0),
),
ModuleOverlapSpec(
# Labware on TC Gen2 on Flex, with stacking overlap for TC Gen2
spec_deck_definition=load_deck(STANDARD_OT3_DECK, 3),
module_model=ModuleModel.THERMOCYCLER_MODULE_V2,
stacking_offset_with_module={
str(ModuleModel.THERMOCYCLER_MODULE_V2.value): SharedDataOverlapOffset(
x=111, y=222, z=333
),
},
expected_offset=OverlapOffset(x=111, y=222, z=333),
),
]


@pytest.mark.parametrize(
argnames=ModuleOverlapSpec._fields,
argvalues=module_overlap_specs,
)
def test_get_module_overlap_offsets(
spec_deck_definition: DeckDefinitionV3,
module_model: ModuleModel,
stacking_offset_with_module: Dict[str, SharedDataOverlapOffset],
expected_offset: OverlapOffset,
) -> None:
"""It should get the labware overlap offsets."""
subject = get_labware_view(
deck_definition=spec_deck_definition,
labware_by_id={"plate-id": plate},
definitions_by_uri={
"some-plate-uri": LabwareDefinition.construct( # type: ignore[call-arg]
stackingOffsetWithModule={
str(
ModuleModel.TEMPERATURE_MODULE_V2.value
): SharedDataOverlapOffset(x=1, y=2, z=3)
}
stackingOffsetWithModule=stacking_offset_with_module
)
},
)

result = subject.get_module_overlap_offsets(
labware_id="plate-id", module_model=ModuleModel.TEMPERATURE_MODULE_V2
labware_id="plate-id", module_model=module_model
)

assert result == OverlapOffset(x=1, y=2, z=3)
assert result == expected_offset


def test_get_default_magnet_height(
Expand Down
7 changes: 7 additions & 0 deletions protocol-designer/fixtures/protocol/7/doItAllV7.json
Original file line number Diff line number Diff line change
Expand Up @@ -2415,6 +2415,13 @@
"stackingOffsetWithLabware": {
"opentrons_96_pcr_adapter": { "x": 0, "y": 0, "z": 10.2 },
"opentrons_96_well_aluminum_block": { "x": 0, "y": 0, "z": 12.66 }
},
"stackingOffsetWithModule": {
"thermocyclerModuleV2": {
"x": 0,
"y": 0,
"z": 10.8
}
}
},
"opentrons/opentrons_24_aluminumblock_nest_1.5ml_snapcap/1": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1025,5 +1025,12 @@
"y": 0,
"z": 15.41
}
},
"stackingOffsetWithModule": {
"thermocyclerModuleV2": {
"x": 0,
"y": 0,
"z": 10.75
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1028,5 +1028,12 @@
"y": 0,
"z": 12.66
}
},
"stackingOffsetWithModule": {
"thermocyclerModuleV2": {
"x": 0,
"y": 0,
"z": 10.8
}
}
}
Loading