diff --git a/api/src/opentrons/protocol_api/core/engine/instrument.py b/api/src/opentrons/protocol_api/core/engine/instrument.py index 30ace69e63b..d9f0cbdd1d4 100644 --- a/api/src/opentrons/protocol_api/core/engine/instrument.py +++ b/api/src/opentrons/protocol_api/core/engine/instrument.py @@ -1008,7 +1008,12 @@ def transfer_liquid( # noqa: C901 source_dest_per_volume_step = tx_commons.expand_for_volume_constraints( volumes=[volume for _ in range(len(source))], targets=zip(source, dest), - max_volume=self.get_max_volume(), + max_volume=min( + self.get_max_volume(), + tip_racks[0][1] + .get_well_core("A1") + .get_max_volume(), # Assuming all tips in tiprack are of same volume + ), ) def _drop_tip() -> None: @@ -1175,10 +1180,11 @@ def aspirate_liquid_class( Return: List of liquid and air gap pairs in tip. """ aspirate_props = transfer_properties.aspirate + # TODO (spp, 2025-01-30): check if check_valid_volume_parameters is necessary and is enough. tx_commons.check_valid_volume_parameters( disposal_volume=0, # No disposal volume for 1-to-1 transfer air_gap=aspirate_props.retract.air_gap_by_volume.get_for_volume(volume), - max_volume=self.get_max_volume(), + max_volume=self.get_working_volume(), ) source_loc, source_well = source aspirate_point = ( diff --git a/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py b/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py index 8ac1ffc1dc8..12e658ab7ae 100644 --- a/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py +++ b/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py @@ -1786,6 +1786,42 @@ def test_aspirate_liquid_class( assert result == [LiquidAndAirGapPair(air_gap=222, liquid=111)] +def test_aspirate_liquid_class_raises_for_more_than_max_volume( + decoy: Decoy, + mock_engine_client: EngineClient, + subject: InstrumentCore, + minimal_liquid_class_def2: LiquidClassSchemaV1, + mock_transfer_components_executor: TransferComponentsExecutor, +) -> None: + """It should call aspirate sub-steps execution based on liquid class.""" + source_well = decoy.mock(cls=WellCore) + source_location = Location(Point(1, 2, 3), labware=None) + test_liquid_class = LiquidClass.create(minimal_liquid_class_def2) + test_transfer_properties = test_liquid_class.get_for( + "flex_1channel_50", "opentrons_flex_96_tiprack_50ul" + ) + decoy.when( + mock_engine_client.state.pipettes.get_working_volume("abc123") + ).then_return(100) + decoy.when( + tx_commons.check_valid_volume_parameters( + disposal_volume=0, + air_gap=test_transfer_properties.aspirate.retract.air_gap_by_volume.get_for_volume( + 123 + ), + max_volume=100, + ) + ).then_raise(ValueError("Oh oh!")) + with pytest.raises(ValueError, match="Oh oh!"): + subject.aspirate_liquid_class( + volume=123, + source=(source_location, source_well), + transfer_properties=test_transfer_properties, + transfer_type=TransferType.ONE_TO_ONE, + tip_contents=[], + ) + + def test_dispense_liquid_class( decoy: Decoy, mock_engine_client: EngineClient, diff --git a/api/tests/opentrons/protocol_api_integration/test_transfer_with_liquid_classes.py b/api/tests/opentrons/protocol_api_integration/test_transfer_with_liquid_classes.py index ba3d3facd6a..6fe2474cfba 100644 --- a/api/tests/opentrons/protocol_api_integration/test_transfer_with_liquid_classes.py +++ b/api/tests/opentrons/protocol_api_integration/test_transfer_with_liquid_classes.py @@ -27,8 +27,8 @@ def test_water_transfer_with_volume_more_than_tip_max( tiprack = simulated_protocol_context.load_labware( "opentrons_flex_96_tiprack_50ul", "D1" ) - pipette_50 = simulated_protocol_context.load_instrument( - "flex_1channel_50", mount="left", tip_racks=[tiprack] + pipette_1k = simulated_protocol_context.load_instrument( + "flex_1channel_1000", mount="left", tip_racks=[tiprack] ) nest_plate = simulated_protocol_context.load_labware( "nest_96_wellplate_200ul_flat", "C3" @@ -47,7 +47,7 @@ def test_water_transfer_with_volume_more_than_tip_max( mock_manager = mock.Mock() mock_manager.attach_mock(patched_pick_up_tip, "pick_up_tip") - pipette_50.transfer_liquid( + pipette_1k.transfer_liquid( liquid_class=water, volume=60, source=nest_plate.rows()[0], @@ -58,7 +58,7 @@ def test_water_transfer_with_volume_more_than_tip_max( assert patched_pick_up_tip.call_count == 24 patched_pick_up_tip.reset_mock() - pipette_50.transfer_liquid( + pipette_1k.transfer_liquid( liquid_class=water, volume=100, source=nest_plate.rows()[0], @@ -69,8 +69,8 @@ def test_water_transfer_with_volume_more_than_tip_max( assert patched_pick_up_tip.call_count == 12 patched_pick_up_tip.reset_mock() - pipette_50.pick_up_tip() - pipette_50.transfer_liquid( + pipette_1k.pick_up_tip() + pipette_1k.transfer_liquid( liquid_class=water, volume=50, source=nest_plate.rows()[0], @@ -78,7 +78,7 @@ def test_water_transfer_with_volume_more_than_tip_max( new_tip="never", trash_location=trash, ) - pipette_50.drop_tip() + pipette_1k.drop_tip() assert patched_pick_up_tip.call_count == 1