Skip to content

Commit

Permalink
error casing and tests for unsupported pipette configuration behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
CaseyBatten committed Aug 9, 2024
1 parent 42db1ee commit 14ef884
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 20 deletions.
61 changes: 41 additions & 20 deletions api/src/opentrons/protocol_api/instrument_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2077,6 +2077,8 @@ def configure_nozzle_layout( # noqa: C901
f"Nozzle layout configuration of style {style.value} is unsupported in API Versions lower than {_PARTIAL_NOZZLE_CONFIGURATION_SINGLE_ROW_PARTIAL_COLUMN_ADDED_IN}."
)

front_right_resolved = front_right
back_left_resolved = back_left
if style != NozzleLayout.ALL:
if start is None:
raise ValueError(
Expand All @@ -2086,30 +2088,49 @@ def configure_nozzle_layout( # noqa: C901
raise ValueError(
f"Starting nozzle specified is not one of {types.ALLOWED_PRIMARY_NOZZLES}"
)
if style == NozzleLayout.QUADRANT:
if front_right is None and back_left is None:
raise ValueError(
"Cannot configure a QUADRANT layout without a front right or back left nozzle."
)
elif not (front_right is None and back_left is None):
raise ValueError(
f"Parameters 'front_right' and 'back_left' cannot be used with {style.value} Nozzle Configuration Layout."
)
if style == NozzleLayout.ROW:
if self.channels != 96:
raise ValueError(
"Row configuraiton is only supported on 96-Channel Pipettes."
)
if style == NozzleLayout.PARTIAL_COLUMN:
if self.channels == 1 or self.channels == 96:
raise ValueError(
"Partial Column configuraiton is only supported on 8-Channel Pipettes."
)

front_right_resolved = front_right
back_left_resolved = back_left
if style == NozzleLayout.PARTIAL_COLUMN:
if end is None:
if end is None:
raise ValueError(
"Parameter 'end' is required for Partial Column Nozzle Configuration Layout."
)
if start[0] in end:
raise ValueError(
"When configuring in Partial Column the 'start' and 'end' parameters cannot be in the same row."
)
# Determine if 'end' will be configured as front_right or back_left
if start == "H1" or start == "H12":
if "A" in end:
raise ValueError(
f"When configuring in Partial Column with 'start'={start} the 'end' parameter cannot be in row A."
)
back_left_resolved = end
elif start == "A1" or start == "A12":
if "H" in end:
raise ValueError(
f"When configuring in Partial Column with 'start'={start} the 'end' parameter cannot be in row H."
)
front_right_resolved = end

if style == NozzleLayout.QUADRANT:
if front_right is None and back_left is None:
raise ValueError(
"Cannot configure a QUADRANT layout without a front right or back left nozzle."
)
elif not (front_right is None and back_left is None):
raise ValueError(
"Parameter 'end' is required for Partial Column Nozzle Configuration Layout."
f"Parameters 'front_right' and 'back_left' cannot be used with {style.value} Nozzle Configuration Layout."
)

# Determine if 'end' will be configured as front_right or back_left
if start == "H1" or start == "H12":
back_left_resolved = end
elif start == "A1" or start == "A12":
front_right_resolved = end

self._core.configure_nozzle_layout(
style,
primary_nozzle=start,
Expand Down
36 changes: 36 additions & 0 deletions api/tests/opentrons/protocol_api/test_instrument_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,7 @@ def test_prepare_to_aspirate_checks_volume(
[NozzleLayout.ROW, "E1", None, None, pytest.raises(ValueError)],
[NozzleLayout.PARTIAL_COLUMN, "H1", None, "G1", does_not_raise()],
[NozzleLayout.PARTIAL_COLUMN, "H1", "H1", "G1", pytest.raises(ValueError)],
[NozzleLayout.PARTIAL_COLUMN, "H1", None, "A1", pytest.raises(ValueError)],
],
)
def test_configure_nozzle_layout(
Expand All @@ -1152,6 +1153,41 @@ def test_configure_nozzle_layout(
)


@pytest.mark.parametrize(
argnames=[
"pipette_channels",
"style",
"primary_nozzle",
"front_right_nozzle",
"end",
"exception",
],
argvalues=[
[8, NozzleLayout.PARTIAL_COLUMN, "A1", None, "G1", does_not_raise()],
[96, NozzleLayout.PARTIAL_COLUMN, "H1", None, "G1", pytest.raises(ValueError)],
[8, NozzleLayout.ROW, "H1", None, None, pytest.raises(ValueError)],
[96, NozzleLayout.ROW, "H1", None, None, does_not_raise()],
],
)
def test_pipette_supports_nozzle_layout(
subject: InstrumentContext,
decoy: Decoy,
mock_instrument_core: InstrumentCore,
pipette_channels: int,
style: NozzleLayout,
primary_nozzle: Optional[str],
front_right_nozzle: Optional[str],
end: Optional[str],
exception: ContextManager[None],
) -> None:
"""Test that error is raised when a pipette attempts to use an unsupported layout."""
decoy.when(mock_instrument_core.get_channels()).then_return(pipette_channels)
with exception:
subject.configure_nozzle_layout(
style=style, start=primary_nozzle, end=end, front_right=front_right_nozzle
)


@pytest.mark.parametrize("api_version", [APIVersion(2, 15)])
def test_dispense_0_volume_means_dispense_everything(
decoy: Decoy,
Expand Down

0 comments on commit 14ef884

Please sign in to comment.