From c9aa373b786871b0d61b055a4edda2c2b5ec4b6f Mon Sep 17 00:00:00 2001 From: Toma Morris Date: Tue, 10 Sep 2019 13:56:18 -0400 Subject: [PATCH] feat(api): replace format with quirks for rectangular well behavior Related to #3894 and closes #3676 --- .../legacy_api/containers/__init__.py | 26 +++++++++++++--- api/src/opentrons/legacy_api/robot/robot.py | 6 ++-- api/tests/opentrons/api/test_session.py | 7 +++-- .../opentrons/containers/test_containers.py | 6 ++++ .../opentrons/integration/test_protocol.py | 2 +- api/tests/opentrons/robot/test_robot.py | 2 +- api/tests/opentrons/server/test_server.py | 31 ------------------- .../2/opentrons_1_trash_1100ml_fixed/1.json | 4 +-- .../2/opentrons_1_trash_850ml_fixed/1.json | 4 +-- 9 files changed, 41 insertions(+), 47 deletions(-) diff --git a/api/src/opentrons/legacy_api/containers/__init__.py b/api/src/opentrons/legacy_api/containers/__init__.py index da38f8919fad..f2353b4c0959 100644 --- a/api/src/opentrons/legacy_api/containers/__init__.py +++ b/api/src/opentrons/legacy_api/containers/__init__.py @@ -3,6 +3,7 @@ import logging import json from opentrons.config import CONFIG +from opentrons.config.pipette_config import Y_OFFSET_MULTI from opentrons.data_storage import database from opentrons.util.vector import Vector from opentrons.types import Point @@ -152,7 +153,11 @@ def save_custom_container(data): "labware, please use opentrons.containers.create()") -def _load_new_well(well_data, saved_offset, lw_format): +def _load_new_well(well_data, saved_offset, lw_quirks): + # We assume a labware is a trough (a.k.a. a reservoir) + # if it has the "centerMultichannelOnWells" quirk, and does + # *not* have the "fixedTrash" quirk. + # # There are two key hacks in here to make troughs work: # - do not specify the size of the well # - specify the center without subtracting the size (since @@ -160,6 +165,12 @@ def _load_new_well(well_data, saved_offset, lw_format): # so that the nominal center leaves the nozzle centered in # an imaginary well instead of centering itself over the # top wall of the trough. + # + # If a labware does have the "fixedTrash" quirk, we shift + # the center position back by the y-offset of multi-channel + # pipettes so that the pipettes get as close as they can + # reach to the center of the trash, without colliding with + # the back of the frame. props = { 'depth': well_data['depth'], 'total-liquid-volume': well_data['totalLiquidVolume'], @@ -167,7 +178,7 @@ def _load_new_well(well_data, saved_offset, lw_format): if well_data['shape'] == 'circular': props['diameter'] = well_data['diameter'] elif well_data['shape'] == 'rectangular': - if lw_format != 'trough': + if "centerMultichannelOnWells" not in lw_quirks: props['length'] = well_data['yDimension'] props['width'] = well_data['xDimension'] else: @@ -175,7 +186,12 @@ def _load_new_well(well_data, saved_offset, lw_format): f"Bad definition for well shape: {well_data['shape']}") well = Well(properties=props) - if lw_format == 'trough': + if "fixedTrash" in lw_quirks: + well_tuple = ( + well_data['x'] + saved_offset.x, + well_data['y'] + Y_OFFSET_MULTI + saved_offset.y, + well_data['z'] + saved_offset.z) + elif "centerMultichannelOnWells" in lw_quirks: well_tuple = ( well_data['x'] + saved_offset.x, well_data['y'] + 7 * well_data['yDimension'] / 16 + saved_offset.y, @@ -231,11 +247,11 @@ def load_new_labware_def(definition): log.info(f"Container name {container_name}, hash {labware_hash}") container.properties['labware_hash'] = labware_hash container.properties['type'] = container_name - lw_format = definition['parameters']['format'] + lw_quirks = definition['parameters'].get('quirks', []) container._coordinates = Vector(definition['cornerOffsetFromSlot']) for well_name in itertools.chain(*definition['ordering']): well_obj, well_pos = _load_new_well( - definition['wells'][well_name], saved_offset, lw_format) + definition['wells'][well_name], saved_offset, lw_quirks) container.add(well_obj, well_name, well_pos) return container diff --git a/api/src/opentrons/legacy_api/robot/robot.py b/api/src/opentrons/legacy_api/robot/robot.py index 18ebe85f3e88..ef4e9439135c 100755 --- a/api/src/opentrons/legacy_api/robot/robot.py +++ b/api/src/opentrons/legacy_api/robot/robot.py @@ -780,9 +780,11 @@ def setup_deck(self): # @TODO (Laura & Andy) Slot and type of trash # needs to be pulled from config file if fflags.short_fixed_trash(): - self._fixed_trash = self.add_container('fixed-trash', '12') + self._fixed_trash = self.add_container( + 'opentrons_1_trash_850ml_fixed', '12') else: - self._fixed_trash = self.add_container('tall-fixed-trash', '12') + self._fixed_trash = self.add_container( + 'opentrons_1_trash_1100ml_fixed', '12') @property def deck(self): diff --git a/api/tests/opentrons/api/test_session.py b/api/tests/opentrons/api/test_session.py index c910dbb22a4d..507c7b3bce95 100755 --- a/api/tests/opentrons/api/test_session.py +++ b/api/tests/opentrons/api/test_session.py @@ -313,7 +313,7 @@ def test_get_labware(labware_setup): async def test_session_model_functional(session_manager, protocol): session = session_manager.create(name='', text=protocol.text) assert [container.name for container in session.containers] == \ - ['tiprack', 'trough', 'plate', 'tall-fixed-trash'] + ['tiprack', 'trough', 'plate', 'opentrons_1_trash_1100ml_fixed'] names = [instrument.name for instrument in session.instruments] assert names == ['p300_single_v1'] @@ -331,9 +331,10 @@ async def test_drop_tip_with_trash(session_manager, protocol, protocol_file): """ session = session_manager.create(name='', text=protocol.text) - assert 'tall-fixed-trash' in [c.name for c in session.get_containers()] + assert 'opentrons_1_trash_1100ml_fixed' in [ + c.name for c in session.get_containers()] containers = sum([i.containers for i in session.get_instruments()], []) - assert 'tall-fixed-trash' in [c.name for c in containers] + assert 'opentrons_1_trash_1100ml_fixed' in [c.name for c in containers] @pytest.mark.api1_only diff --git a/api/tests/opentrons/containers/test_containers.py b/api/tests/opentrons/containers/test_containers.py index 4ce1832f63e9..17d2eb88f708 100644 --- a/api/tests/opentrons/containers/test_containers.py +++ b/api/tests/opentrons/containers/test_containers.py @@ -100,6 +100,12 @@ def test_load_new_trough(robot): == (13.94, 42.9 + 31.4475, 2.29) +def test_load_fixed_trash(robot): + from opentrons.config.pipette_config import Y_OFFSET_MULTI + assert robot.fixed_trash[0]._coordinates == ( + 82.84, 53.56 + Y_OFFSET_MULTI, 82) + + def test_containers_list(robot): res = containers_list() assert res diff --git a/api/tests/opentrons/integration/test_protocol.py b/api/tests/opentrons/integration/test_protocol.py index 10226cdb07d9..177e84ad2295 100644 --- a/api/tests/opentrons/integration/test_protocol.py +++ b/api/tests/opentrons/integration/test_protocol.py @@ -51,5 +51,5 @@ def test_deck_setup(robot): assert isinstance(tiprack, Container) assert isinstance(deck, Deck) # Check that well location is the same on the robot as the pipette - assert robot._deck['12']['tall-fixed-trash'][0] == trash + assert robot._deck['12']['opentrons_1_trash_1100ml_fixed'][0] == trash assert deck.has_container(tiprack) diff --git a/api/tests/opentrons/robot/test_robot.py b/api/tests/opentrons/robot/test_robot.py index b97d52925f04..beb4f53233ec 100644 --- a/api/tests/opentrons/robot/test_robot.py +++ b/api/tests/opentrons/robot/test_robot.py @@ -81,7 +81,7 @@ def test_calibrated_max_z(virtual_smoothie_env): robot.reset() instruments.P300_Single(mount='left') - assert robot.max_deck_height() == 85 + assert robot.max_deck_height() == 82 def test_get_serial_ports_list(monkeypatch): diff --git a/api/tests/opentrons/server/test_server.py b/api/tests/opentrons/server/test_server.py index c1dd95490f82..55a1c7ff1462 100755 --- a/api/tests/opentrons/server/test_server.py +++ b/api/tests/opentrons/server/test_server.py @@ -436,34 +436,3 @@ def message_key(message): meta = message['$'] data = message.get('data', '') return str(meta.get('type')) + meta.get('token', '') + str(data) - - -@pytest.mark.api1_only -@pytest.mark.parametrize('root', [TickTock()]) -async def test_concurrent_and_disconnect(loop, root, session, connect): # noqa C901 - n_sockets = 20 - sockets = await async_iterate([connect() for _ in range(n_sockets)]) - - # TODO (artyom, 20170920): look for pattern to call several coroutines - # and collect results in one line - tokens = await async_iterate([ - call(socket, id=id(root), name='start', args=[]) - for socket in sockets]) - - await sockets.pop(1).close() - - stop_messages = [result_message(token, 'Done!') for token in tokens] - results = await async_iterate( - [read_until(socket, stop_messages) for socket in sockets]) - - for res in results: - # First message is root info - assert res.pop(0)['$'] == {'type': 3, 'monitor': True} - expected = [] - # All acks received - expected.extend([ack_message(token) for token in tokens]) - # All results received - expected.extend([result_message(token, 'Done!') for token in tokens]) - # All notifications received. 5 ticks per notifications - expected.extend([notification_message(i) for i in range(5)] * n_sockets) # noqa - assert sorted(res, key=message_key) == sorted(expected, key=message_key) # noqa diff --git a/shared-data/labware/definitions/2/opentrons_1_trash_1100ml_fixed/1.json b/shared-data/labware/definitions/2/opentrons_1_trash_1100ml_fixed/1.json index f160975693f0..a1e178d811bc 100644 --- a/shared-data/labware/definitions/2/opentrons_1_trash_1100ml_fixed/1.json +++ b/shared-data/labware/definitions/2/opentrons_1_trash_1100ml_fixed/1.json @@ -27,10 +27,10 @@ "yDimension": 165.67, "xDimension": 107.11, "totalLiquidVolume": 1100000, - "depth": 77, + "depth": 0, "x": 82.84, "y": 53.56, - "z": 5 + "z": 82 } }, "brand": { diff --git a/shared-data/labware/definitions/2/opentrons_1_trash_850ml_fixed/1.json b/shared-data/labware/definitions/2/opentrons_1_trash_850ml_fixed/1.json index c963ecab817d..0e87fce16c9f 100644 --- a/shared-data/labware/definitions/2/opentrons_1_trash_850ml_fixed/1.json +++ b/shared-data/labware/definitions/2/opentrons_1_trash_850ml_fixed/1.json @@ -27,10 +27,10 @@ "yDimension": 165.67, "xDimension": 107.11, "totalLiquidVolume": 850000, - "depth": 53, + "depth": 0, "x": 82.84, "y": 53.56, - "z": 5 + "z": 58 } }, "brand": {