diff --git a/api/src/opentrons/protocol_engine/commands/aspirate_while_tracking.py b/api/src/opentrons/protocol_engine/commands/aspirate_while_tracking.py index ae7431de70b1..efe0bb5cb2ad 100644 --- a/api/src/opentrons/protocol_engine/commands/aspirate_while_tracking.py +++ b/api/src/opentrons/protocol_engine/commands/aspirate_while_tracking.py @@ -29,7 +29,7 @@ from ..errors.exceptions import PipetteNotReadyToAspirateError from opentrons.hardware_control import HardwareControlAPI from ..state.update_types import CLEAR -from ..types import CurrentWell, DeckPoint +from ..types import DeckPoint if TYPE_CHECKING: from ..execution import PipettingHandler, GantryMover, MovementHandler @@ -104,16 +104,8 @@ async def execute(self, params: AspirateWhileTrackingParams) -> _ExecuteReturn: " The first aspirate following a blow-out must be from a specific well" " so the plunger can be reset in a known safe position." ) - - current_position = await self._gantry_mover.get_position(params.pipetteId) - current_location = self._state_view.pipettes.get_current_location() - state_update = StateUpdate() - current_well = CurrentWell( - pipette_id=params.pipetteId, - labware_id=params.labwareId, - well_name=params.wellName, - ) + move_result = await move_to_well( movement=self._movement, model_utils=self._model_utils, @@ -121,8 +113,6 @@ async def execute(self, params: AspirateWhileTrackingParams) -> _ExecuteReturn: labware_id=params.labwareId, well_name=params.wellName, well_location=params.wellLocation, - current_well=current_well, - operation_volume=-params.volume, ) state_update.append(move_result.state_update) if isinstance(move_result, DefinedErrorData): @@ -138,9 +128,9 @@ async def execute(self, params: AspirateWhileTrackingParams) -> _ExecuteReturn: flow_rate=params.flowRate, location_if_error={ "retryLocation": ( - current_position.x, - current_position.y, - current_position.z, + move_result.public.position.x, + move_result.public.position.y, + move_result.public.position.z, ) }, command_note_adder=self._command_note_adder, @@ -156,58 +146,40 @@ async def execute(self, params: AspirateWhileTrackingParams) -> _ExecuteReturn: z=position_after_aspirate.z, ) if isinstance(aspirate_result, DefinedErrorData): - if ( - isinstance(current_location, CurrentWell) - and current_location.pipette_id == params.pipetteId - ): - return DefinedErrorData( - public=aspirate_result.public, - state_update=aspirate_result.state_update.set_liquid_operated( - labware_id=current_location.labware_id, - well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well( - current_location.labware_id, - current_location.well_name, - params.pipetteId, - ), - volume_added=CLEAR, - ), - state_update_if_false_positive=aspirate_result.state_update_if_false_positive, - ) - else: - return aspirate_result - else: - if ( - isinstance(current_location, CurrentWell) - and current_location.pipette_id == params.pipetteId - ): - return SuccessData( - public=AspirateWhileTrackingResult( - volume=aspirate_result.public.volume, - position=result_deck_point, - ), - state_update=aspirate_result.state_update.set_liquid_operated( - labware_id=current_location.labware_id, - well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well( - current_location.labware_id, - current_location.well_name, - params.pipetteId, - ), - volume_added=-aspirate_result.public.volume - * self._state_view.geometry.get_nozzles_per_well( - current_location.labware_id, - current_location.well_name, - params.pipetteId, - ), - ), - ) - else: - return SuccessData( - public=AspirateWhileTrackingResult( - volume=aspirate_result.public.volume, - position=result_deck_point, + return DefinedErrorData( + public=aspirate_result.public, + state_update=aspirate_result.state_update.set_liquid_operated( + labware_id=params.labwareId, + well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well( + params.labwareId, + params.wellName, + params.pipetteId, ), - state_update=aspirate_result.state_update, - ) + volume_added=CLEAR, + ), + state_update_if_false_positive=aspirate_result.state_update_if_false_positive, + ) + + return SuccessData( + public=AspirateWhileTrackingResult( + volume=aspirate_result.public.volume, + position=result_deck_point, + ), + state_update=aspirate_result.state_update.set_liquid_operated( + labware_id=params.labwareId, + well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well( + params.labwareId, + params.wellName, + params.pipetteId, + ), + volume_added=-aspirate_result.public.volume + * self._state_view.geometry.get_nozzles_per_well( + params.labwareId, + params.wellName, + params.pipetteId, + ), + ), + ) class AspirateWhileTracking( diff --git a/api/src/opentrons/protocol_engine/commands/dispense_while_tracking.py b/api/src/opentrons/protocol_engine/commands/dispense_while_tracking.py index f84c3fda1900..a2da401b7078 100644 --- a/api/src/opentrons/protocol_engine/commands/dispense_while_tracking.py +++ b/api/src/opentrons/protocol_engine/commands/dispense_while_tracking.py @@ -9,7 +9,7 @@ from pydantic.json_schema import SkipJsonSchema from ..state.update_types import CLEAR, StateUpdate -from ..types import CurrentWell, DeckPoint +from ..types import DeckPoint from .pipetting_common import ( PipetteIdMixin, DispenseVolumeMixin, @@ -99,13 +99,6 @@ async def execute(self, params: DispenseWhileTrackingParams) -> _ExecuteReturn: # TODO(pbm, 10-15-24): call self._state_view.geometry.validate_dispense_volume_into_well() - current_location = self._state_view.pipettes.get_current_location() - current_position = await self._gantry_mover.get_position(params.pipetteId) - current_well = CurrentWell( - pipette_id=params.pipetteId, - labware_id=params.labwareId, - well_name=params.wellName, - ) state_update = StateUpdate() move_result = await move_to_well( movement=self._movement, @@ -114,8 +107,6 @@ async def execute(self, params: DispenseWhileTrackingParams) -> _ExecuteReturn: labware_id=params.labwareId, well_name=params.wellName, well_location=params.wellLocation, - current_well=current_well, - operation_volume=-params.volume, ) state_update.append(move_result.state_update) if isinstance(move_result, DefinedErrorData): @@ -132,9 +123,9 @@ async def execute(self, params: DispenseWhileTrackingParams) -> _ExecuteReturn: push_out=params.pushOut, location_if_error={ "retryLocation": ( - current_position.x, - current_position.y, - current_position.z, + move_result.public.position.x, + move_result.public.position.y, + move_result.public.position.z, ) }, pipetting=self._pipetting, @@ -150,67 +141,40 @@ async def execute(self, params: DispenseWhileTrackingParams) -> _ExecuteReturn: ) if isinstance(dispense_result, DefinedErrorData): - if ( - isinstance(current_location, CurrentWell) - and current_location.pipette_id == params.pipetteId - ): - return DefinedErrorData( - public=dispense_result.public, - state_update=dispense_result.state_update.set_liquid_operated( - labware_id=current_location.labware_id, - well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well( - current_location.labware_id, - current_location.well_name, - params.pipetteId, - ), - volume_added=CLEAR, - ), - state_update_if_false_positive=dispense_result.state_update_if_false_positive, - ) - else: - return dispense_result - else: - if ( - isinstance(current_location, CurrentWell) - and current_location.pipette_id == params.pipetteId - ): - volume_added = ( - self._state_view.pipettes.get_liquid_dispensed_by_ejecting_volume( - pipette_id=params.pipetteId, - volume=dispense_result.public.volume, - ) - ) - if volume_added is not None: - volume_added *= self._state_view.geometry.get_nozzles_per_well( - current_location.labware_id, - current_location.well_name, + return DefinedErrorData( + public=dispense_result.public, + state_update=dispense_result.state_update.set_liquid_operated( + labware_id=params.labwareId, + well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well( + params.labwareId, + params.wellName, params.pipetteId, - ) - return SuccessData( - public=DispenseWhileTrackingResult( - volume=dispense_result.public.volume, - position=result_deck_point, ), - state_update=dispense_result.state_update.set_liquid_operated( - labware_id=current_location.labware_id, - well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well( - current_location.labware_id, - current_location.well_name, - params.pipetteId, - ), - volume_added=volume_added - if volume_added is not None - else CLEAR, - ), - ) - else: - return SuccessData( - public=DispenseWhileTrackingResult( - volume=dispense_result.public.volume, - position=result_deck_point, - ), - state_update=dispense_result.state_update, - ) + volume_added=CLEAR, + ), + state_update_if_false_positive=dispense_result.state_update_if_false_positive, + ) + + return SuccessData( + public=DispenseWhileTrackingResult( + volume=dispense_result.public.volume, + position=result_deck_point, + ), + state_update=dispense_result.state_update.set_liquid_operated( + labware_id=params.labwareId, + well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well( + params.labwareId, + params.wellName, + params.pipetteId, + ), + volume_added=dispense_result.public.volume + * self._state_view.geometry.get_nozzles_per_well( + params.labwareId, + params.wellName, + params.pipetteId, + ), + ), + ) class DispenseWhileTracking( diff --git a/api/tests/opentrons/protocol_engine/commands/test_aspirate_while_tracking.py b/api/tests/opentrons/protocol_engine/commands/test_aspirate_while_tracking.py index 76574fcf5903..f10604e79707 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_aspirate_while_tracking.py +++ b/api/tests/opentrons/protocol_engine/commands/test_aspirate_while_tracking.py @@ -138,7 +138,6 @@ async def test_aspirate_while_tracking_implementation( pipette_id="pipette-id-abc", ) ).then_return(2) - decoy.when( state_store.geometry.get_wells_covered_by_pipette_with_active_well( stateupdateLabware, stateupdateWell, "pipette-id-abc" @@ -174,20 +173,17 @@ async def test_aspirate_while_tracking_implementation( _well_location = LiquidHandlingWellLocation( origin=WellOrigin.MENISCUS, offset=WellOffset(x=0.0, y=0.0, z=1.0) ) - _current_well = CurrentWell( - pipette_id="pipette-id-abc", labware_id="funky-labware", well_name="funky-well" - ) decoy.when( await subject._movement.move_to_well( pipette_id="pipette-id-abc", labware_id="funky-labware", well_name="funky-well", well_location=_well_location, - current_well=_current_well, + current_well=None, force_direct=False, minimum_z_height=None, speed=None, - operation_volume=-123.0, + operation_volume=None, ), ).then_return(Point(x=4, y=5, z=6)) @@ -219,7 +215,12 @@ async def test_aspirate_while_tracking_implementation( pipette_aspirated_fluid=update_types.PipetteAspiratedFluidUpdate( pipette_id="pipette-id-abc", fluid=AspiratedFluid(kind=FluidKind.LIQUID, volume=123), - ) + ), + liquid_operated=update_types.LiquidOperatedUpdate( + labware_id="funky-labware", + well_names=["A3", "A4"], + volume_added=-246.0, + ), ), ) @@ -311,20 +312,17 @@ async def test_aspirate_raises_volume_error( _well_location = LiquidHandlingWellLocation( origin=WellOrigin.MENISCUS, offset=WellOffset(x=0.0, y=0.0, z=1.0) ) - _current_well = CurrentWell( - pipette_id="pipette-id-abc", labware_id="funky-labware", well_name="funky-well" - ) decoy.when( await subject._movement.move_to_well( pipette_id="pipette-id-abc", labware_id="funky-labware", well_name="funky-well", well_location=_well_location, - current_well=_current_well, + current_well=None, force_direct=False, minimum_z_height=None, speed=None, - operation_volume=-50.0, + operation_volume=None, ), ).then_return(Point(x=4, y=5, z=6)) @@ -374,10 +372,9 @@ async def test_overpressure_error( pipette_id="pipette-id-abc", ) ).then_return(2) - decoy.when( state_store.geometry.get_wells_covered_by_pipette_with_active_well( - stateupdateLabware, stateupdateWell, "pipette-id-abc" + "funky-labware", "funky-well", "pipette-id-abc" ) ).then_return(["A3", "A4"]) well_location = LiquidHandlingWellLocation( @@ -418,20 +415,17 @@ async def test_overpressure_error( _well_location = LiquidHandlingWellLocation( origin=WellOrigin.MENISCUS, offset=WellOffset(x=0.0, y=0.0, z=1.0) ) - _current_well = CurrentWell( - pipette_id="pipette-id-abc", labware_id="funky-labware", well_name="funky-well" - ) decoy.when( await subject._movement.move_to_well( pipette_id=pipette_id, labware_id="funky-labware", well_name="funky-well", well_location=_well_location, - current_well=_current_well, + current_well=None, force_direct=False, minimum_z_height=None, speed=None, - operation_volume=-50.0, + operation_volume=None, ), ).then_return(Point(x=4, y=5, z=6)) @@ -443,7 +437,7 @@ async def test_overpressure_error( id=error_id, createdAt=error_timestamp, wrappedErrors=[matchers.Anything()], - errorInfo={"retryLocation": (position.x, position.y, position.z)}, + errorInfo={"retryLocation": (4, 5, 6)}, ), state_update=update_types.StateUpdate( liquid_operated=update_types.LiquidOperatedUpdate( @@ -462,11 +456,16 @@ async def test_overpressure_error( id=error_id, createdAt=error_timestamp, wrappedErrors=[matchers.Anything()], - errorInfo={"retryLocation": (position.x, position.y, position.z)}, + errorInfo={"retryLocation": (4, 5, 6)}, ), state_update=update_types.StateUpdate( pipette_aspirated_fluid=update_types.PipetteUnknownFluidUpdate( pipette_id="pipette-id-abc" - ) + ), + liquid_operated=update_types.LiquidOperatedUpdate( + labware_id="funky-labware", + well_names=["A3", "A4"], + volume_added=update_types.CLEAR, + ), ), ) diff --git a/api/tests/opentrons/protocol_engine/commands/test_dispense_while_tracking.py b/api/tests/opentrons/protocol_engine/commands/test_dispense_while_tracking.py index 6b7daccc8e62..846d87d7db15 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_dispense_while_tracking.py +++ b/api/tests/opentrons/protocol_engine/commands/test_dispense_while_tracking.py @@ -145,20 +145,17 @@ async def test_dispense_while_tracking_implementation( _well_location = LiquidHandlingWellLocation( origin=WellOrigin.MENISCUS, offset=WellOffset(x=0.0, y=0.0, z=1.0) ) - _current_well = CurrentWell( - pipette_id="pipette-id-abc", labware_id="funky-labware", well_name="funky-well" - ) decoy.when( await subject._movement.move_to_well( pipette_id="pipette-id-abc", labware_id="funky-labware", well_name="funky-well", well_location=_well_location, - current_well=_current_well, + current_well=None, force_direct=False, minimum_z_height=None, speed=None, - operation_volume=-123.0, + operation_volume=None, ), ).then_return(Point(x=4, y=5, z=6)) @@ -176,7 +173,7 @@ async def test_dispense_while_tracking_implementation( liquid_operated=update_types.LiquidOperatedUpdate( labware_id=stateupdateLabware, well_names=["A3", "A4"], - volume_added=68, + volume_added=84, ), ready_to_aspirate=update_types.PipetteAspirateReadyUpdate( pipette_id="pipette-id-abc", ready_to_aspirate=False @@ -184,17 +181,23 @@ async def test_dispense_while_tracking_implementation( ), ) else: + assert result == SuccessData( public=DispenseWhileTrackingResult( volume=42, position=DeckPoint(x=1, y=2, z=3) ), state_update=update_types.StateUpdate( pipette_aspirated_fluid=update_types.PipetteEjectedFluidUpdate( - pipette_id="pipette-id-abc", volume=42 + pipette_id="pipette-id-abc", volume=42, type="ejected" ), ready_to_aspirate=update_types.PipetteAspirateReadyUpdate( pipette_id="pipette-id-abc", ready_to_aspirate=False ), + liquid_operated=update_types.LiquidOperatedUpdate( + labware_id="funky-labware", + well_names=["A3", "A4"], + volume_added=84.0, + ), ), ) @@ -286,20 +289,17 @@ async def test_overpressure_error( _well_location = LiquidHandlingWellLocation( origin=WellOrigin.MENISCUS, offset=WellOffset(x=0.0, y=0.0, z=1.0) ) - _current_well = CurrentWell( - pipette_id="pipette-id", labware_id="funky-labware", well_name="funky-well" - ) decoy.when( await subject._movement.move_to_well( pipette_id="pipette-id", labware_id="funky-labware", well_name="funky-well", well_location=_well_location, - current_well=_current_well, + current_well=None, force_direct=False, minimum_z_height=None, speed=None, - operation_volume=-50.0, + operation_volume=None, ), ).then_return(Point(x=4, y=5, z=6)) @@ -311,7 +311,7 @@ async def test_overpressure_error( id=error_id, createdAt=error_timestamp, wrappedErrors=[matchers.Anything()], - errorInfo={"retryLocation": (position.x, position.y, position.z)}, + errorInfo={"retryLocation": (4.0, 5.0, 6.0)}, ), state_update=update_types.StateUpdate( liquid_operated=update_types.LiquidOperatedUpdate( @@ -333,9 +333,14 @@ async def test_overpressure_error( id=error_id, createdAt=error_timestamp, wrappedErrors=[matchers.Anything()], - errorInfo={"retryLocation": (position.x, position.y, position.z)}, + errorInfo={"retryLocation": (4.0, 5.0, 6.0)}, ), state_update=update_types.StateUpdate( + liquid_operated=update_types.LiquidOperatedUpdate( + labware_id="funky-labware", + well_names=["A3", "A4"], + volume_added=update_types.CLEAR, + ), pipette_aspirated_fluid=update_types.PipetteUnknownFluidUpdate( pipette_id="pipette-id" ), @@ -343,4 +348,5 @@ async def test_overpressure_error( pipette_id="pipette-id", ready_to_aspirate=False ), ), + state_update_if_false_positive=update_types.StateUpdate(), )