diff --git a/api/src/opentrons/protocol_engine/commands/configuring_common.py b/api/src/opentrons/protocol_engine/commands/configuring_common.py index ec5917d9931..17ffc2adef4 100644 --- a/api/src/opentrons/protocol_engine/commands/configuring_common.py +++ b/api/src/opentrons/protocol_engine/commands/configuring_common.py @@ -1,7 +1,6 @@ """Common configuration command base models.""" from pydantic import BaseModel, Field -from typing import Optional from dataclasses import dataclass from opentrons.hardware_control.nozzle_manager import ( NozzleMap, @@ -22,7 +21,7 @@ class PipetteNozzleLayoutResultMixin(BaseModel): """A nozzle layout result for updating the pipette state.""" pipette_id: str - nozzle_map: Optional[NozzleMap] = Field( - default=None, + nozzle_map: NozzleMap = Field( + ..., description="A dataclass object holding information about the current nozzle configuration.", ) diff --git a/api/src/opentrons/protocol_engine/state/pipettes.py b/api/src/opentrons/protocol_engine/state/pipettes.py index 7cb7401581f..16e8a96aeed 100644 --- a/api/src/opentrons/protocol_engine/state/pipettes.py +++ b/api/src/opentrons/protocol_engine/state/pipettes.py @@ -102,6 +102,7 @@ class StaticPipetteConfig: home_position: float nozzle_offset_z: float bounding_nozzle_offsets: BoundingNozzlesOffsets + default_nozzle_map: NozzleMap @dataclass @@ -170,6 +171,7 @@ def _handle_command( # noqa: C901 back_left_offset=config.nozzle_map.back_left_nozzle_offset, front_right_offset=config.nozzle_map.front_right_nozzle_offset, ), + default_nozzle_map=config.nozzle_map, ) self._state.flow_rates_by_id[private_result.pipette_id] = config.flow_rates self._state.nozzle_configuration_by_id[ @@ -191,7 +193,11 @@ def _handle_command( # noqa: C901 self._state.aspirated_volume_by_id[pipette_id] = None self._state.movement_speed_by_id[pipette_id] = None self._state.attached_tip_by_id[pipette_id] = None - self._state.nozzle_configuration_by_id[pipette_id] = None + static_config = self._state.static_config_by_id.get(pipette_id) + if static_config: + self._state.nozzle_configuration_by_id[ + pipette_id + ] = static_config.default_nozzle_map elif isinstance(command.result, (AspirateResult, AspirateInPlaceResult)): pipette_id = command.params.pipetteId diff --git a/api/tests/opentrons/protocol_engine/commands/test_configure_nozzle_layout.py b/api/tests/opentrons/protocol_engine/commands/test_configure_nozzle_layout.py index 43b140c81fe..23cdddd98be 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_configure_nozzle_layout.py +++ b/api/tests/opentrons/protocol_engine/commands/test_configure_nozzle_layout.py @@ -73,11 +73,6 @@ ), {"primary_nozzle": "A1", "front_right_nozzle": "E1"}, ], - [ - AllNozzleLayoutConfiguration(), - None, - {}, - ], ], ) async def test_configure_nozzle_layout_implementation( diff --git a/api/tests/opentrons/protocol_engine/state/test_geometry_view.py b/api/tests/opentrons/protocol_engine/state/test_geometry_view.py index 93c3be8ebbe..b1b5453f144 100644 --- a/api/tests/opentrons/protocol_engine/state/test_geometry_view.py +++ b/api/tests/opentrons/protocol_engine/state/test_geometry_view.py @@ -57,6 +57,7 @@ ) from opentrons.protocol_engine.state.addressable_areas import AddressableAreaView from opentrons.protocol_engine.state.geometry import GeometryView, _GripperMoveType +from ..pipette_fixtures import get_default_nozzle_map @pytest.fixture @@ -1839,6 +1840,12 @@ def test_get_next_drop_tip_location( decoy.when( labware_view.get_well_size(labware_id="abc", well_name="A1") ).then_return((well_size, 0, 0)) + if pipette_channels == 96: + pip_type = PipetteNameType.P1000_96 + elif pipette_channels == 8: + pip_type = PipetteNameType.P300_MULTI + else: + pip_type = PipetteNameType.P300_SINGLE decoy.when(mock_pipette_view.get_config("pip-123")).then_return( StaticPipetteConfig( min_volume=1, @@ -1855,6 +1862,7 @@ def test_get_next_drop_tip_location( back_left_offset=Point(x=10, y=20, z=30), front_right_offset=Point(x=40, y=50, z=60), ), + default_nozzle_map=get_default_nozzle_map(pip_type), ) ) decoy.when(mock_pipette_view.get_mount("pip-123")).then_return(pipette_mount) diff --git a/api/tests/opentrons/protocol_engine/state/test_pipette_store.py b/api/tests/opentrons/protocol_engine/state/test_pipette_store.py index 4bf509176a1..6b43e8e5f77 100644 --- a/api/tests/opentrons/protocol_engine/state/test_pipette_store.py +++ b/api/tests/opentrons/protocol_engine/state/test_pipette_store.py @@ -705,6 +705,7 @@ def test_add_pipette_config( back_left_offset=Point(x=0, y=0, z=0), front_right_offset=Point(x=0, y=0, z=0), ), + default_nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE), ) assert subject.state.flow_rates_by_id["pipette-id"].default_aspirate == {"a": 1.0} assert subject.state.flow_rates_by_id["pipette-id"].default_dispense == {"b": 2.0} diff --git a/api/tests/opentrons/protocol_engine/state/test_pipette_view.py b/api/tests/opentrons/protocol_engine/state/test_pipette_view.py index b272ca6aa54..e4ef0dae930 100644 --- a/api/tests/opentrons/protocol_engine/state/test_pipette_view.py +++ b/api/tests/opentrons/protocol_engine/state/test_pipette_view.py @@ -37,6 +37,7 @@ EIGHT_CHANNEL_ROWS, EIGHT_CHANNEL_COLS, EIGHT_CHANNEL_MAP, + get_default_nozzle_map, ) _SAMPLE_NOZZLE_BOUNDS_OFFSETS = BoundingNozzlesOffsets( @@ -268,6 +269,7 @@ def test_get_pipette_working_volume( home_position=0, nozzle_offset_z=0, bounding_nozzle_offsets=_SAMPLE_NOZZLE_BOUNDS_OFFSETS, + default_nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE), ) }, ) @@ -296,6 +298,7 @@ def test_get_pipette_working_volume_raises_if_tip_volume_is_none( home_position=0, nozzle_offset_z=0, bounding_nozzle_offsets=_SAMPLE_NOZZLE_BOUNDS_OFFSETS, + default_nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE), ) }, ) @@ -333,6 +336,7 @@ def test_get_pipette_available_volume( home_position=0, nozzle_offset_z=0, bounding_nozzle_offsets=_SAMPLE_NOZZLE_BOUNDS_OFFSETS, + default_nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE), ), "pipette-id-none": StaticPipetteConfig( min_volume=1, @@ -346,6 +350,7 @@ def test_get_pipette_available_volume( home_position=0, nozzle_offset_z=0, bounding_nozzle_offsets=_SAMPLE_NOZZLE_BOUNDS_OFFSETS, + default_nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE), ), }, ) @@ -455,6 +460,7 @@ def test_get_static_config( home_position=10.12, nozzle_offset_z=12.13, bounding_nozzle_offsets=_SAMPLE_NOZZLE_BOUNDS_OFFSETS, + default_nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE), ) subject = get_pipette_view( @@ -503,6 +509,7 @@ def test_get_nominal_tip_overlap( home_position=0, nozzle_offset_z=0, bounding_nozzle_offsets=_SAMPLE_NOZZLE_BOUNDS_OFFSETS, + default_nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE), ) subject = get_pipette_view(static_config_by_id={"pipette-id": config}) @@ -738,6 +745,7 @@ def test_get_nozzle_bounds_at_location( home_position=0, nozzle_offset_z=0, bounding_nozzle_offsets=bounding_nozzle_offsets, + default_nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE), ) }, ) diff --git a/api/tests/opentrons/protocol_engine/state/test_tip_state.py b/api/tests/opentrons/protocol_engine/state/test_tip_state.py index 3b0a3598191..f7f86434e4e 100644 --- a/api/tests/opentrons/protocol_engine/state/test_tip_state.py +++ b/api/tests/opentrons/protocol_engine/state/test_tip_state.py @@ -614,7 +614,6 @@ def test_drop_tip( ), 5, ), - (None, 9), ], ) def test_active_channels( @@ -646,7 +645,7 @@ def test_active_channels( nominal_tip_overlap={}, nozzle_offset_z=1.23, home_position=4.56, - nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE_GEN2), + nozzle_map=nozzle_map, ), ) subject.handle_action(