Skip to content

Commit

Permalink
fix(api): preserve pre-v2.18 API tip drop alternating behavior (#15052)
Browse files Browse the repository at this point in the history
# Overview

Closes AUTH-42

In PR #14560, the ability to provide custom offsets for disposal
location objects (trash bins and waste chutes loaded in API v2.16 and
above) was added to be introduced in v2.18. With this addition came a
slight change in behavior to our alternate tip drop behavior.

For context, automatic tip drop alternation was something added in API
v2.15, that when no explicit location was provided for `drop_tip`, the
pipette's location it dropped the tip in would cycle between a left bias
and right bias, to prevent tips from stacking up as quickly.

When deck configured trash was introduced initially, there was no way to
provide custom offsets, and so we'd always do the tip alternation
regardless of whether the trash location was passed or not. With the
addition of offsets, we've gone back to the pattern we used for labware
based trash, where if you provide it even with no offset, we go to the
center of the trash. However, the PR did not add a version gate for this
change in behavior, which meant that 2.16 and 2.17 protocols would
behave slightly differently in this new robot version. This PR fixes
that and preserves parity with those API levels.

# Test Plan

Tested the following two protocols on robot and ensured that the 2.17
protocol and 2.18 worked as expected.

```
metadata = {
    'protocolName': 'Tip Drop Alternation 2.17 test',
}

requirements = {
    "robotType": "Flex",
    "apiLevel": "2.17"
}

def run(context):
    trash = context.load_trash_bin('A3')
    tip_rack = context.load_labware('opentrons_flex_96_tiprack_200ul', 'C2')
    pipette = context.load_instrument("flex_1channel_1000", mount="left", tip_racks=[tip_rack])

    # On 2.17 it should alternate for all four drop tip calls, regardless of trash being provided as location or not
    pipette.pick_up_tip()
    pipette.drop_tip(trash)

    pipette.pick_up_tip()
    pipette.drop_tip(trash)

    pipette.pick_up_tip()
    pipette.drop_tip()

    pipette.pick_up_tip()
    pipette.drop_tip()
```
```
metadata = {
    'protocolName': 'Tip Drop Alternation 2.18 test',
}

requirements = {
    "robotType": "Flex",
    "apiLevel": "2.18"
}

def run(context):
    trash = context.load_trash_bin('A3')
    tip_rack = context.load_labware('opentrons_flex_96_tiprack_200ul', 'C2')
    pipette = context.load_instrument("flex_1channel_1000", mount="left", tip_racks=[tip_rack])

    # On 2.18 it should alternate only for the latter two calls, and go to the XY center for the first two
    pipette.pick_up_tip()
    pipette.drop_tip(trash)

    pipette.pick_up_tip()
    pipette.drop_tip(trash)

    pipette.pick_up_tip()
    pipette.drop_tip()

    pipette.pick_up_tip()
    pipette.drop_tip()
```

# Changelog

- added a version gate for `alternate_tip_drop` to preserve 2.16 and
2.17 tip dropping behavior.

# Review requests

Is there anything that should be added to the docstring or release notes
regarding this change?

# Risk assessment

Low.
  • Loading branch information
jbleon95 authored Apr 30, 2024
1 parent 6eb85a8 commit 117f26f
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
14 changes: 11 additions & 3 deletions api/src/opentrons/protocol_api/instrument_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
"""The version after which a partial nozzle configuration became available for the 96 Channel Pipette."""
_PARTIAL_NOZZLE_CONFIGURATION_AUTOMATIC_TIP_TRACKING_IN = APIVersion(2, 18)
"""The version after which automatic tip tracking supported partially configured nozzle layouts."""
_DISPOSAL_LOCATION_OFFSET_ADDED_IN = APIVersion(2, 18)
"""The version after which offsets for deck configured trash containers and changes to alternating tip drop behavior were introduced."""


class InstrumentContext(publisher.CommandPublisher):
Expand Down Expand Up @@ -1086,16 +1088,22 @@ def drop_tip(
well = maybe_well

elif isinstance(location, (TrashBin, WasteChute)):
# In 2.16 and 2.17, we would always automatically use automatic alternate tip drop locations regardless
# of whether you explicitly passed the disposal location as a location or if none was provided. Now, in
# 2.18 and moving forward, passing it in will bypass the automatic behavior and instead go to the set
# offset or the XY center if none is provided.
if self.api_version < _DISPOSAL_LOCATION_OFFSET_ADDED_IN:
alternate_drop_location = True
with publisher.publish_context(
broker=self.broker,
command=cmds.drop_tip_in_disposal_location(
instrument=self, location=location
),
):
# TODO(jbl 2024-02-28) when adding 2.18 api version checks, set alternate_tip_drop
# if below that version for compatability
self._core.drop_tip_in_disposal_location(
location, home_after=home_after
location,
home_after=home_after,
alternate_tip_drop=alternate_drop_location,
)
self._last_tip_picked_up_from = None
return self
Expand Down
12 changes: 12 additions & 0 deletions api/tests/opentrons/protocol_api/test_instrument_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,9 +753,14 @@ def test_drop_tip_to_randomized_trash_location(
)


@pytest.mark.parametrize(
["api_version", "alternate_drop"],
[(APIVersion(2, 17), True), (APIVersion(2, 18), False)],
)
def test_drop_tip_in_trash_bin(
decoy: Decoy,
mock_instrument_core: InstrumentCore,
alternate_drop: bool,
subject: InstrumentContext,
) -> None:
"""It should drop a tip in a deck configured trash bin."""
Expand All @@ -767,14 +772,20 @@ def test_drop_tip_in_trash_bin(
mock_instrument_core.drop_tip_in_disposal_location(
trash_bin,
home_after=None,
alternate_tip_drop=alternate_drop,
),
times=1,
)


@pytest.mark.parametrize(
["api_version", "alternate_drop"],
[(APIVersion(2, 17), True), (APIVersion(2, 18), False)],
)
def test_drop_tip_in_waste_chute(
decoy: Decoy,
mock_instrument_core: InstrumentCore,
alternate_drop: bool,
subject: InstrumentContext,
) -> None:
"""It should drop a tip in a deck configured trash bin or waste chute."""
Expand All @@ -786,6 +797,7 @@ def test_drop_tip_in_waste_chute(
mock_instrument_core.drop_tip_in_disposal_location(
waste_chute,
home_after=None,
alternate_tip_drop=alternate_drop,
),
times=1,
)
Expand Down

0 comments on commit 117f26f

Please sign in to comment.