From cac1158daa28a3c22de9a0bc577b50ea4857cbe4 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Fri, 19 Apr 2024 13:03:06 -0400 Subject: [PATCH 01/10] feat(api): add ReloadLabware command The ReloadLabware command reloads the non-position details of a labware that has already been loaded. Its most common use case is to update the labware offset applied to the labware by rerunning the offset binding logic with presumably-updated stored offsets. --- .../protocol_engine/commands/__init__.py | 14 + .../commands/command_unions.py | 13 + .../commands/reload_labware.py | 139 +++ .../protocol_engine/execution/__init__.py | 2 + .../protocol_engine/execution/equipment.py | 51 + .../commands/test_reload_labware.py | 141 +++ shared-data/command/schemas/8.json | 1001 +++++++++++++---- 7 files changed, 1153 insertions(+), 208 deletions(-) create mode 100644 api/src/opentrons/protocol_engine/commands/reload_labware.py create mode 100644 api/tests/opentrons/protocol_engine/commands/test_reload_labware.py diff --git a/api/src/opentrons/protocol_engine/commands/__init__.py b/api/src/opentrons/protocol_engine/commands/__init__.py index 3dfe6eaf51f..b7aacc6b059 100644 --- a/api/src/opentrons/protocol_engine/commands/__init__.py +++ b/api/src/opentrons/protocol_engine/commands/__init__.py @@ -120,6 +120,14 @@ LoadLabwareCommandType, ) +from .reload_labware import ( + ReloadLabware, + ReloadLabwareParams, + ReloadLabwareCreate, + ReloadLabwareResult, + ReloadLabwareCommandType, +) + from .load_liquid import ( LoadLiquid, LoadLiquidParams, @@ -402,6 +410,12 @@ "LoadLabwareParams", "LoadLabwareResult", "LoadLabwareCommandType", + # reload labware command models + "ReloadLabware", + "ReloadLabwareCreate", + "ReloadLabwareParams", + "ReloadLabwareResult", + "ReloadLabwareCommandType", # load module command models "LoadModule", "LoadModuleCreate", diff --git a/api/src/opentrons/protocol_engine/commands/command_unions.py b/api/src/opentrons/protocol_engine/commands/command_unions.py index dc4cc18c35a..7674508cc96 100644 --- a/api/src/opentrons/protocol_engine/commands/command_unions.py +++ b/api/src/opentrons/protocol_engine/commands/command_unions.py @@ -100,6 +100,14 @@ LoadLabwareCommandType, ) +from .reload_labware import ( + ReloadLabware, + ReloadLabwareParams, + ReloadLabwareCreate, + ReloadLabwareResult, + ReloadLabwareCommandType, +) + from .load_liquid import ( LoadLiquid, LoadLiquidParams, @@ -304,6 +312,7 @@ Home, RetractAxis, LoadLabware, + ReloadLabware, LoadLiquid, LoadModule, LoadPipette, @@ -368,6 +377,7 @@ HomeParams, RetractAxisParams, LoadLabwareParams, + ReloadLabwareParams, LoadLiquidParams, LoadModuleParams, LoadPipetteParams, @@ -431,6 +441,7 @@ HomeCommandType, RetractAxisCommandType, LoadLabwareCommandType, + ReloadLabwareCommandType, LoadLiquidCommandType, LoadModuleCommandType, LoadPipetteCommandType, @@ -494,6 +505,7 @@ HomeCreate, RetractAxisCreate, LoadLabwareCreate, + ReloadLabwareCreate, LoadLiquidCreate, LoadModuleCreate, LoadPipetteCreate, @@ -558,6 +570,7 @@ HomeResult, RetractAxisResult, LoadLabwareResult, + ReloadLabwareResult, LoadLiquidResult, LoadModuleResult, LoadPipetteResult, diff --git a/api/src/opentrons/protocol_engine/commands/reload_labware.py b/api/src/opentrons/protocol_engine/commands/reload_labware.py new file mode 100644 index 00000000000..132ef9b3bef --- /dev/null +++ b/api/src/opentrons/protocol_engine/commands/reload_labware.py @@ -0,0 +1,139 @@ +"""Reload labware command request, result, and implementation models.""" +from __future__ import annotations +from pydantic import BaseModel, Field +from typing import TYPE_CHECKING, Optional, Type +from typing_extensions import Literal + +from opentrons_shared_data.labware.labware_definition import LabwareDefinition +from ..resources import labware_validation + +from ..errors import LabwareIsNotAllowedInLocationError +from ..types import ( + OnLabwareLocation, + DeckSlotLocation, +) + +from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate + +if TYPE_CHECKING: + from ..state import StateView + from ..execution import EquipmentHandler + + +ReloadLabwareCommandType = Literal["reloadLabware"] + + +class ReloadLabwareParams(BaseModel): + """Payload required to load a labware into a slot.""" + + labwareId: str = Field( + ..., description="The already-loaded labware instance to update." + ) + loadName: str = Field( + ..., + description="Name used to reference a labware definition.", + ) + namespace: str = Field( + ..., + description="The namespace the labware definition belongs to.", + ) + version: int = Field( + ..., + description="The labware definition version.", + ) + displayName: Optional[str] = Field( + None, + description="An optional user-specified display name " + "or label for this labware.", + ) + + +class ReloadLabwareResult(BaseModel): + """Result data from the execution of a LoadLabware command.""" + + labwareId: str = Field( + ..., + description="An ID to reference this labware in subsequent commands. Same as the one in the parameters.", + ) + definition: LabwareDefinition = Field( + ..., + description="The full definition data for this labware.", + ) + offsetId: Optional[str] = Field( + # Default `None` instead of `...` so this field shows up as non-required in + # OpenAPI. The server is allowed to omit it or make it null. + None, + description=( + "An ID referencing the labware offset that will apply" + " to the reloaded labware." + " This offset will be in effect until the labware is moved" + " with a `moveLabware` command." + " Null or undefined means no offset applies," + " so the default of (0, 0, 0) will be used." + ), + ) + + +class ReloadLabwareImplementation( + AbstractCommandImpl[ReloadLabwareParams, ReloadLabwareResult] +): + """Load labware command implementation.""" + + def __init__( + self, equipment: EquipmentHandler, state_view: StateView, **kwargs: object + ) -> None: + self._equipment = equipment + self._state_view = state_view + + async def execute(self, params: ReloadLabwareParams) -> ReloadLabwareResult: + """Reload the definition and calibration data for a specific labware.""" + reloaded_labware = await self._equipment.reload_labware( + labware_id=params.labwareId, + load_name=params.loadName, + namespace=params.namespace, + version=params.version, + ) + + # note: this check must be kept because somebody might specify the trash loadName + if ( + labware_validation.is_flex_trash(params.loadName) + and isinstance(reloaded_labware.location, DeckSlotLocation) + and self._state_view.geometry.get_slot_column( + reloaded_labware.location.slotName + ) + != 3 + ): + raise LabwareIsNotAllowedInLocationError( + f"{params.loadName} is not allowed in slot {reloaded_labware.location.slotName}" + ) + + if isinstance(reloaded_labware.location, OnLabwareLocation): + self._state_view.labware.raise_if_labware_cannot_be_stacked( + top_labware_definition=reloaded_labware.definition, + bottom_labware_id=reloaded_labware.location.labwareId, + ) + + return ReloadLabwareResult( + labwareId=params.labwareId, + definition=reloaded_labware.definition, + offsetId=reloaded_labware.offsetId, + ) + + +class ReloadLabware(BaseCommand[ReloadLabwareParams, ReloadLabwareResult]): + """Load labware command resource model.""" + + commandType: ReloadLabwareCommandType = "reloadLabware" + params: ReloadLabwareParams + result: Optional[ReloadLabwareResult] + + _ImplementationCls: Type[ReloadLabwareImplementation] = ReloadLabwareImplementation + + +class ReloadLabwareCreate(BaseCommandCreate[ReloadLabwareParams]): + """Load labware command creation request.""" + + commandType: ReloadLabwareCommandType = "reloadLabware" + params: ReloadLabwareParams + + _CommandCls: Type[ReloadLabware] = ReloadLabware diff --git a/api/src/opentrons/protocol_engine/execution/__init__.py b/api/src/opentrons/protocol_engine/execution/__init__.py index 5d2da5e6840..80f2dfd0d99 100644 --- a/api/src/opentrons/protocol_engine/execution/__init__.py +++ b/api/src/opentrons/protocol_engine/execution/__init__.py @@ -8,6 +8,7 @@ LoadedPipetteData, LoadedModuleData, LoadedConfigureForVolumeData, + ReloadedLabwareData, ) from .movement import MovementHandler from .gantry_mover import GantryMover @@ -29,6 +30,7 @@ "create_queue_worker", "EquipmentHandler", "LoadedLabwareData", + "ReloadedLabwareData", "LoadedPipetteData", "LoadedModuleData", "LoadedConfigureForVolumeData", diff --git a/api/src/opentrons/protocol_engine/execution/equipment.py b/api/src/opentrons/protocol_engine/execution/equipment.py index ee04653bda2..12eb3df6787 100644 --- a/api/src/opentrons/protocol_engine/execution/equipment.py +++ b/api/src/opentrons/protocol_engine/execution/equipment.py @@ -56,6 +56,15 @@ class LoadedLabwareData: offsetId: Optional[str] +@dataclass(frozen=True) +class ReloadedLabwareData: + """The result of a reload labware procedure.""" + + definition: LabwareDefinition + location: LabwareLocation + offsetId: Optional[str] + + @dataclass(frozen=True) class LoadedPipetteData: """The result of a load pipette procedure.""" @@ -171,6 +180,48 @@ async def load_labware( labware_id=labware_id, definition=definition, offsetId=offset_id ) + async def reload_labware( + self, labware_id: str, load_name: str, namespace: str, version: int + ) -> ReloadedLabwareData: + """Reload an already-loaded labware. This cannot change the labware location. + + Args: + labware_id: The ID of the already-loaded labware. + load_name: The labware's load name. + namespace: The labware's namespace. + version: The labware's version. + + Raises: + LabwareNotLoadedError: If `labware_id` does not reference a loaded labware. + + """ + definition_uri = uri_from_details( + load_name=load_name, + namespace=namespace, + version=version, + ) + location = self._state_store.labware.get_location(labware_id) + + try: + # Try to use existing definition in state. + definition = self._state_store.labware.get_definition_by_uri(definition_uri) + except LabwareDefinitionDoesNotExistError: + definition = await self._labware_data_provider.get_labware_definition( + load_name=load_name, + namespace=namespace, + version=version, + ) + + # Allow propagation of ModuleNotLoadedError. + offset_id = self.find_applicable_labware_offset_id( + labware_definition_uri=definition_uri, + labware_location=location, + ) + + return ReloadedLabwareData( + definition=definition, location=location, offsetId=offset_id + ) + async def load_pipette( self, pipette_name: PipetteNameType, diff --git a/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py b/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py new file mode 100644 index 00000000000..73d751a6609 --- /dev/null +++ b/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py @@ -0,0 +1,141 @@ +"""Test load labware commands.""" +import inspect +import pytest + +from decoy import Decoy + +from opentrons.types import DeckSlotName +from opentrons.protocols.models import LabwareDefinition + +from opentrons.protocol_engine.errors import ( + LabwareIsNotAllowedInLocationError, + LabwareNotLoadedError, +) + +from opentrons.protocol_engine.types import ( + DeckSlotLocation, +) +from opentrons.protocol_engine.execution import ReloadedLabwareData, EquipmentHandler +from opentrons.protocol_engine.resources import labware_validation +from opentrons.protocol_engine.state import StateView + +from opentrons.protocol_engine.commands.reload_labware import ( + ReloadLabwareParams, + ReloadLabwareResult, + ReloadLabwareImplementation, +) + + +@pytest.fixture(autouse=True) +def patch_mock_labware_validation( + decoy: Decoy, monkeypatch: pytest.MonkeyPatch +) -> None: + """Mock out move_types.py functions.""" + for name, func in inspect.getmembers(labware_validation, inspect.isfunction): + monkeypatch.setattr(labware_validation, name, decoy.mock(func=func)) + + +async def test_reload_labware_implementation( + decoy: Decoy, + well_plate_def: LabwareDefinition, + equipment: EquipmentHandler, + state_view: StateView, +) -> None: + """A ReloadLabware command should have an execution implementation.""" + subject = ReloadLabwareImplementation(equipment=equipment, state_view=state_view) + + data = ReloadLabwareParams( + labwareId="my-labware-id", + loadName="some-load-name", + namespace="opentrons-test", + version=1, + displayName="My custom display name", + ) + + decoy.when( + await equipment.reload_labware( + labware_id="my-labware-id", + load_name="some-load-name", + namespace="opentrons-test", + version=1, + ) + ).then_return( + ReloadedLabwareData( + location=DeckSlotLocation(slotName=DeckSlotName.SLOT_4), + definition=well_plate_def, + offsetId="labware-offset-id", + ) + ) + + result = await subject.execute(data) + + assert result == ReloadLabwareResult( + labwareId="my-labware-id", + definition=well_plate_def, + offsetId="labware-offset-id", + ) + + +async def test_reload_labware_raises_labware_does_not_exist( + decoy: Decoy, + well_plate_def: LabwareDefinition, + equipment: EquipmentHandler, + state_view: StateView, +) -> None: + """A ReloadLabware command should raise if the specified labware is not loaded.""" + subject = ReloadLabwareImplementation(equipment=equipment, state_view=state_view) + + data = ReloadLabwareParams( + labwareId="my-labware-id", + loadName="some-load-name", + namespace="opentrons-test", + version=1, + displayName="My custom display name", + ) + + decoy.when( + await equipment.reload_labware( + labware_id="my-labware-id", + load_name="some-load-name", + namespace="opentrons-test", + version=1, + ) + ).then_raise(LabwareNotLoadedError("What labware is this!")) + + with pytest.raises(LabwareNotLoadedError): + await subject.execute(data) + + +async def test_load_labware_raises_location_not_allowed( + decoy: Decoy, + equipment: EquipmentHandler, + state_view: StateView, + well_plate_def: LabwareDefinition, +) -> None: + """A ReloadLabware command should raise if the flex trash definition is not in a valid slot.""" + subject = ReloadLabwareImplementation(equipment=equipment, state_view=state_view) + decoy.when(labware_validation.is_flex_trash("some-load-name")).then_return(True) + decoy.when( + await equipment.reload_labware( + labware_id="my-labware-id", + load_name="some-load-name", + namespace="opentrons-test", + version=1, + ) + ).then_return( + ReloadedLabwareData( + location=DeckSlotLocation(slotName=DeckSlotName.SLOT_A3), + definition=well_plate_def, + offsetId="labware-offset-id", + ) + ) + data = ReloadLabwareParams( + labwareId="my-labware-id", + loadName="some-load-name", + namespace="opentrons-test", + version=1, + displayName="My custom display name", + ) + + with pytest.raises(LabwareIsNotAllowedInLocationError): + await subject.execute(data) diff --git a/shared-data/command/schemas/8.json b/shared-data/command/schemas/8.json index a17be9ee690..1a7adb09f69 100644 --- a/shared-data/command/schemas/8.json +++ b/shared-data/command/schemas/8.json @@ -19,6 +19,7 @@ "home": "#/definitions/HomeCreate", "retractAxis": "#/definitions/RetractAxisCreate", "loadLabware": "#/definitions/LoadLabwareCreate", + "reloadLabware": "#/definitions/ReloadLabwareCreate", "loadLiquid": "#/definitions/LoadLiquidCreate", "loadModule": "#/definitions/LoadModuleCreate", "loadPipette": "#/definitions/LoadPipetteCreate", @@ -112,6 +113,9 @@ { "$ref": "#/definitions/LoadLabwareCreate" }, + { + "$ref": "#/definitions/ReloadLabwareCreate" + }, { "$ref": "#/definitions/LoadLiquidCreate" }, @@ -249,7 +253,11 @@ "WellOrigin": { "title": "WellOrigin", "description": "Origin of WellLocation offset.\n\nProps:\n TOP: the top-center of the well\n BOTTOM: the bottom-center of the well\n CENTER: the middle-center of the well", - "enum": ["top", "bottom", "center"], + "enum": [ + "top", + "bottom", + "center" + ], "type": "string" }, "WellOffset": { @@ -334,12 +342,21 @@ "type": "string" } }, - "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"] + "required": [ + "labwareId", + "wellName", + "flowRate", + "volume", + "pipetteId" + ] }, "CommandIntent": { "title": "CommandIntent", "description": "Run intent for a given command.\n\nProps:\n PROTOCOL: the command is part of the protocol run itself.\n SETUP: the command is part of the setup phase of a run.", - "enum": ["protocol", "setup"], + "enum": [ + "protocol", + "setup" + ], "type": "string" }, "AspirateCreate": { @@ -350,7 +367,9 @@ "commandType": { "title": "Commandtype", "default": "aspirate", - "enum": ["aspirate"], + "enum": [ + "aspirate" + ], "type": "string" }, "params": { @@ -370,7 +389,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "AspirateInPlaceParams": { "title": "AspirateInPlaceParams", @@ -395,7 +416,11 @@ "type": "string" } }, - "required": ["flowRate", "volume", "pipetteId"] + "required": [ + "flowRate", + "volume", + "pipetteId" + ] }, "AspirateInPlaceCreate": { "title": "AspirateInPlaceCreate", @@ -405,7 +430,9 @@ "commandType": { "title": "Commandtype", "default": "aspirateInPlace", - "enum": ["aspirateInPlace"], + "enum": [ + "aspirateInPlace" + ], "type": "string" }, "params": { @@ -425,7 +452,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "CommentParams": { "title": "CommentParams", @@ -438,7 +467,9 @@ "type": "string" } }, - "required": ["message"] + "required": [ + "message" + ] }, "CommentCreate": { "title": "CommentCreate", @@ -448,7 +479,9 @@ "commandType": { "title": "Commandtype", "default": "comment", - "enum": ["comment"], + "enum": [ + "comment" + ], "type": "string" }, "params": { @@ -468,7 +501,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "ConfigureForVolumeParams": { "title": "ConfigureForVolumeParams", @@ -487,7 +522,10 @@ "type": "number" } }, - "required": ["pipetteId", "volume"] + "required": [ + "pipetteId", + "volume" + ] }, "ConfigureForVolumeCreate": { "title": "ConfigureForVolumeCreate", @@ -497,7 +535,9 @@ "commandType": { "title": "Commandtype", "default": "configureForVolume", - "enum": ["configureForVolume"], + "enum": [ + "configureForVolume" + ], "type": "string" }, "params": { @@ -517,7 +557,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "AllNozzleLayoutConfiguration": { "title": "AllNozzleLayoutConfiguration", @@ -527,7 +569,9 @@ "style": { "title": "Style", "default": "ALL", - "enum": ["ALL"], + "enum": [ + "ALL" + ], "type": "string" } } @@ -540,17 +584,26 @@ "style": { "title": "Style", "default": "SINGLE", - "enum": ["SINGLE"], + "enum": [ + "SINGLE" + ], "type": "string" }, "primaryNozzle": { "title": "Primarynozzle", "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", - "enum": ["A1", "H1", "A12", "H12"], + "enum": [ + "A1", + "H1", + "A12", + "H12" + ], "type": "string" } }, - "required": ["primaryNozzle"] + "required": [ + "primaryNozzle" + ] }, "RowNozzleLayoutConfiguration": { "title": "RowNozzleLayoutConfiguration", @@ -560,17 +613,26 @@ "style": { "title": "Style", "default": "ROW", - "enum": ["ROW"], + "enum": [ + "ROW" + ], "type": "string" }, "primaryNozzle": { "title": "Primarynozzle", "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", - "enum": ["A1", "H1", "A12", "H12"], + "enum": [ + "A1", + "H1", + "A12", + "H12" + ], "type": "string" } }, - "required": ["primaryNozzle"] + "required": [ + "primaryNozzle" + ] }, "ColumnNozzleLayoutConfiguration": { "title": "ColumnNozzleLayoutConfiguration", @@ -580,17 +642,26 @@ "style": { "title": "Style", "default": "COLUMN", - "enum": ["COLUMN"], + "enum": [ + "COLUMN" + ], "type": "string" }, "primaryNozzle": { "title": "Primarynozzle", "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", - "enum": ["A1", "H1", "A12", "H12"], + "enum": [ + "A1", + "H1", + "A12", + "H12" + ], "type": "string" } }, - "required": ["primaryNozzle"] + "required": [ + "primaryNozzle" + ] }, "QuadrantNozzleLayoutConfiguration": { "title": "QuadrantNozzleLayoutConfiguration", @@ -600,13 +671,20 @@ "style": { "title": "Style", "default": "QUADRANT", - "enum": ["QUADRANT"], + "enum": [ + "QUADRANT" + ], "type": "string" }, "primaryNozzle": { "title": "Primarynozzle", "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", - "enum": ["A1", "H1", "A12", "H12"], + "enum": [ + "A1", + "H1", + "A12", + "H12" + ], "type": "string" }, "frontRightNozzle": { @@ -616,7 +694,10 @@ "type": "string" } }, - "required": ["primaryNozzle", "frontRightNozzle"] + "required": [ + "primaryNozzle", + "frontRightNozzle" + ] }, "ConfigureNozzleLayoutParams": { "title": "ConfigureNozzleLayoutParams", @@ -649,7 +730,10 @@ ] } }, - "required": ["pipetteId", "configurationParams"] + "required": [ + "pipetteId", + "configurationParams" + ] }, "ConfigureNozzleLayoutCreate": { "title": "ConfigureNozzleLayoutCreate", @@ -659,7 +743,9 @@ "commandType": { "title": "Commandtype", "default": "configureNozzleLayout", - "enum": ["configureNozzleLayout"], + "enum": [ + "configureNozzleLayout" + ], "type": "string" }, "params": { @@ -679,7 +765,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "CustomParams": { "title": "CustomParams", @@ -695,7 +783,9 @@ "commandType": { "title": "Commandtype", "default": "custom", - "enum": ["custom"], + "enum": [ + "custom" + ], "type": "string" }, "params": { @@ -715,7 +805,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DispenseParams": { "title": "DispenseParams", @@ -764,7 +856,13 @@ "type": "number" } }, - "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"] + "required": [ + "labwareId", + "wellName", + "flowRate", + "volume", + "pipetteId" + ] }, "DispenseCreate": { "title": "DispenseCreate", @@ -774,7 +872,9 @@ "commandType": { "title": "Commandtype", "default": "dispense", - "enum": ["dispense"], + "enum": [ + "dispense" + ], "type": "string" }, "params": { @@ -794,7 +894,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DispenseInPlaceParams": { "title": "DispenseInPlaceParams", @@ -824,7 +926,11 @@ "type": "number" } }, - "required": ["flowRate", "volume", "pipetteId"] + "required": [ + "flowRate", + "volume", + "pipetteId" + ] }, "DispenseInPlaceCreate": { "title": "DispenseInPlaceCreate", @@ -834,7 +940,9 @@ "commandType": { "title": "Commandtype", "default": "dispenseInPlace", - "enum": ["dispenseInPlace"], + "enum": [ + "dispenseInPlace" + ], "type": "string" }, "params": { @@ -854,7 +962,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "BlowOutParams": { "title": "BlowOutParams", @@ -892,7 +1002,12 @@ "type": "string" } }, - "required": ["labwareId", "wellName", "flowRate", "pipetteId"] + "required": [ + "labwareId", + "wellName", + "flowRate", + "pipetteId" + ] }, "BlowOutCreate": { "title": "BlowOutCreate", @@ -902,7 +1017,9 @@ "commandType": { "title": "Commandtype", "default": "blowout", - "enum": ["blowout"], + "enum": [ + "blowout" + ], "type": "string" }, "params": { @@ -922,7 +1039,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "BlowOutInPlaceParams": { "title": "BlowOutInPlaceParams", @@ -941,7 +1060,10 @@ "type": "string" } }, - "required": ["flowRate", "pipetteId"] + "required": [ + "flowRate", + "pipetteId" + ] }, "BlowOutInPlaceCreate": { "title": "BlowOutInPlaceCreate", @@ -951,7 +1073,9 @@ "commandType": { "title": "Commandtype", "default": "blowOutInPlace", - "enum": ["blowOutInPlace"], + "enum": [ + "blowOutInPlace" + ], "type": "string" }, "params": { @@ -971,12 +1095,19 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DropTipWellOrigin": { "title": "DropTipWellOrigin", "description": "The origin of a DropTipWellLocation offset.\n\nProps:\n TOP: the top-center of the well\n BOTTOM: the bottom-center of the well\n CENTER: the middle-center of the well\n DEFAULT: the default drop-tip location of the well,\n based on pipette configuration and length of the tip.", - "enum": ["top", "bottom", "center", "default"], + "enum": [ + "top", + "bottom", + "center", + "default" + ], "type": "string" }, "DropTipWellLocation": { @@ -1038,7 +1169,11 @@ "type": "boolean" } }, - "required": ["pipetteId", "labwareId", "wellName"] + "required": [ + "pipetteId", + "labwareId", + "wellName" + ] }, "DropTipCreate": { "title": "DropTipCreate", @@ -1048,7 +1183,9 @@ "commandType": { "title": "Commandtype", "default": "dropTip", - "enum": ["dropTip"], + "enum": [ + "dropTip" + ], "type": "string" }, "params": { @@ -1068,7 +1205,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DropTipInPlaceParams": { "title": "DropTipInPlaceParams", @@ -1086,7 +1225,9 @@ "type": "boolean" } }, - "required": ["pipetteId"] + "required": [ + "pipetteId" + ] }, "DropTipInPlaceCreate": { "title": "DropTipInPlaceCreate", @@ -1096,7 +1237,9 @@ "commandType": { "title": "Commandtype", "default": "dropTipInPlace", - "enum": ["dropTipInPlace"], + "enum": [ + "dropTipInPlace" + ], "type": "string" }, "params": { @@ -1116,7 +1259,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "MotorAxis": { "title": "MotorAxis", @@ -1136,7 +1281,11 @@ "MountType": { "title": "MountType", "description": "An enumeration.", - "enum": ["left", "right", "extension"], + "enum": [ + "left", + "right", + "extension" + ], "type": "string" }, "HomeParams": { @@ -1169,7 +1318,9 @@ "commandType": { "title": "Commandtype", "default": "home", - "enum": ["home"], + "enum": [ + "home" + ], "type": "string" }, "params": { @@ -1189,7 +1340,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "RetractAxisParams": { "title": "RetractAxisParams", @@ -1205,7 +1358,9 @@ ] } }, - "required": ["axis"] + "required": [ + "axis" + ] }, "RetractAxisCreate": { "title": "RetractAxisCreate", @@ -1215,7 +1370,9 @@ "commandType": { "title": "Commandtype", "default": "retractAxis", - "enum": ["retractAxis"], + "enum": [ + "retractAxis" + ], "type": "string" }, "params": { @@ -1235,7 +1392,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DeckSlotName": { "title": "DeckSlotName", @@ -1281,7 +1440,9 @@ ] } }, - "required": ["slotName"] + "required": [ + "slotName" + ] }, "ModuleLocation": { "title": "ModuleLocation", @@ -1294,7 +1455,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "OnLabwareLocation": { "title": "OnLabwareLocation", @@ -1307,7 +1470,9 @@ "type": "string" } }, - "required": ["labwareId"] + "required": [ + "labwareId" + ] }, "AddressableAreaLocation": { "title": "AddressableAreaLocation", @@ -1320,7 +1485,9 @@ "type": "string" } }, - "required": ["addressableAreaName"] + "required": [ + "addressableAreaName" + ] }, "LoadLabwareParams": { "title": "LoadLabwareParams", @@ -1341,7 +1508,9 @@ "$ref": "#/definitions/OnLabwareLocation" }, { - "enum": ["offDeck"], + "enum": [ + "offDeck" + ], "type": "string" }, { @@ -1375,7 +1544,12 @@ "type": "string" } }, - "required": ["location", "loadName", "namespace", "version"] + "required": [ + "location", + "loadName", + "namespace", + "version" + ] }, "LoadLabwareCreate": { "title": "LoadLabwareCreate", @@ -1385,7 +1559,9 @@ "commandType": { "title": "Commandtype", "default": "loadLabware", - "enum": ["loadLabware"], + "enum": [ + "loadLabware" + ], "type": "string" }, "params": { @@ -1405,7 +1581,81 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] + }, + "ReloadLabwareParams": { + "title": "ReloadLabwareParams", + "description": "Payload required to load a labware into a slot.", + "type": "object", + "properties": { + "labwareId": { + "title": "Labwareid", + "description": "The already-loaded labware instance to update.", + "type": "string" + }, + "loadName": { + "title": "Loadname", + "description": "Name used to reference a labware definition.", + "type": "string" + }, + "namespace": { + "title": "Namespace", + "description": "The namespace the labware definition belongs to.", + "type": "string" + }, + "version": { + "title": "Version", + "description": "The labware definition version.", + "type": "integer" + }, + "displayName": { + "title": "Displayname", + "description": "An optional user-specified display name or label for this labware.", + "type": "string" + } + }, + "required": [ + "labwareId", + "loadName", + "namespace", + "version" + ] + }, + "ReloadLabwareCreate": { + "title": "ReloadLabwareCreate", + "description": "Load labware command creation request.", + "type": "object", + "properties": { + "commandType": { + "title": "Commandtype", + "default": "reloadLabware", + "enum": [ + "reloadLabware" + ], + "type": "string" + }, + "params": { + "$ref": "#/definitions/ReloadLabwareParams" + }, + "intent": { + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "allOf": [ + { + "$ref": "#/definitions/CommandIntent" + } + ] + }, + "key": { + "title": "Key", + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "type": "string" + } + }, + "required": [ + "params" + ] }, "LoadLiquidParams": { "title": "LoadLiquidParams", @@ -1431,7 +1681,11 @@ } } }, - "required": ["liquidId", "labwareId", "volumeByWell"] + "required": [ + "liquidId", + "labwareId", + "volumeByWell" + ] }, "LoadLiquidCreate": { "title": "LoadLiquidCreate", @@ -1441,7 +1695,9 @@ "commandType": { "title": "Commandtype", "default": "loadLiquid", - "enum": ["loadLiquid"], + "enum": [ + "loadLiquid" + ], "type": "string" }, "params": { @@ -1461,7 +1717,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "ModuleModel": { "title": "ModuleModel", @@ -1506,7 +1764,10 @@ "type": "string" } }, - "required": ["model", "location"] + "required": [ + "model", + "location" + ] }, "LoadModuleCreate": { "title": "LoadModuleCreate", @@ -1516,7 +1777,9 @@ "commandType": { "title": "Commandtype", "default": "loadModule", - "enum": ["loadModule"], + "enum": [ + "loadModule" + ], "type": "string" }, "params": { @@ -1536,7 +1799,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "PipetteNameType": { "title": "PipetteNameType", @@ -1589,7 +1854,10 @@ "type": "string" } }, - "required": ["pipetteName", "mount"] + "required": [ + "pipetteName", + "mount" + ] }, "LoadPipetteCreate": { "title": "LoadPipetteCreate", @@ -1599,7 +1867,9 @@ "commandType": { "title": "Commandtype", "default": "loadPipette", - "enum": ["loadPipette"], + "enum": [ + "loadPipette" + ], "type": "string" }, "params": { @@ -1619,12 +1889,18 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "LabwareMovementStrategy": { "title": "LabwareMovementStrategy", "description": "Strategy to use for labware movement.", - "enum": ["usingGripper", "manualMoveWithPause", "manualMoveWithoutPause"], + "enum": [ + "usingGripper", + "manualMoveWithPause", + "manualMoveWithoutPause" + ], "type": "string" }, "LabwareOffsetVector": { @@ -1645,7 +1921,11 @@ "type": "number" } }, - "required": ["x", "y", "z"] + "required": [ + "x", + "y", + "z" + ] }, "MoveLabwareParams": { "title": "MoveLabwareParams", @@ -1671,7 +1951,9 @@ "$ref": "#/definitions/OnLabwareLocation" }, { - "enum": ["offDeck"], + "enum": [ + "offDeck" + ], "type": "string" }, { @@ -1706,7 +1988,11 @@ ] } }, - "required": ["labwareId", "newLocation", "strategy"] + "required": [ + "labwareId", + "newLocation", + "strategy" + ] }, "MoveLabwareCreate": { "title": "MoveLabwareCreate", @@ -1716,7 +2002,9 @@ "commandType": { "title": "Commandtype", "default": "moveLabware", - "enum": ["moveLabware"], + "enum": [ + "moveLabware" + ], "type": "string" }, "params": { @@ -1736,12 +2024,18 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "MovementAxis": { "title": "MovementAxis", "description": "Axis on which to issue a relative movement.", - "enum": ["x", "y", "z"], + "enum": [ + "x", + "y", + "z" + ], "type": "string" }, "MoveRelativeParams": { @@ -1768,7 +2062,11 @@ "type": "number" } }, - "required": ["pipetteId", "axis", "distance"] + "required": [ + "pipetteId", + "axis", + "distance" + ] }, "MoveRelativeCreate": { "title": "MoveRelativeCreate", @@ -1778,7 +2076,9 @@ "commandType": { "title": "Commandtype", "default": "moveRelative", - "enum": ["moveRelative"], + "enum": [ + "moveRelative" + ], "type": "string" }, "params": { @@ -1798,7 +2098,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DeckPoint": { "title": "DeckPoint", @@ -1818,7 +2120,11 @@ "type": "number" } }, - "required": ["x", "y", "z"] + "required": [ + "x", + "y", + "z" + ] }, "MoveToCoordinatesParams": { "title": "MoveToCoordinatesParams", @@ -1856,7 +2162,10 @@ ] } }, - "required": ["pipetteId", "coordinates"] + "required": [ + "pipetteId", + "coordinates" + ] }, "MoveToCoordinatesCreate": { "title": "MoveToCoordinatesCreate", @@ -1866,7 +2175,9 @@ "commandType": { "title": "Commandtype", "default": "moveToCoordinates", - "enum": ["moveToCoordinates"], + "enum": [ + "moveToCoordinates" + ], "type": "string" }, "params": { @@ -1886,7 +2197,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "MoveToWellParams": { "title": "MoveToWellParams", @@ -1934,7 +2247,11 @@ "type": "string" } }, - "required": ["labwareId", "wellName", "pipetteId"] + "required": [ + "labwareId", + "wellName", + "pipetteId" + ] }, "MoveToWellCreate": { "title": "MoveToWellCreate", @@ -1944,7 +2261,9 @@ "commandType": { "title": "Commandtype", "default": "moveToWell", - "enum": ["moveToWell"], + "enum": [ + "moveToWell" + ], "type": "string" }, "params": { @@ -1964,7 +2283,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "AddressableOffsetVector": { "title": "AddressableOffsetVector", @@ -1984,7 +2305,11 @@ "type": "number" } }, - "required": ["x", "y", "z"] + "required": [ + "x", + "y", + "z" + ] }, "MoveToAddressableAreaParams": { "title": "MoveToAddressableAreaParams", @@ -2038,7 +2363,10 @@ "type": "boolean" } }, - "required": ["pipetteId", "addressableAreaName"] + "required": [ + "pipetteId", + "addressableAreaName" + ] }, "MoveToAddressableAreaCreate": { "title": "MoveToAddressableAreaCreate", @@ -2048,7 +2376,9 @@ "commandType": { "title": "Commandtype", "default": "moveToAddressableArea", - "enum": ["moveToAddressableArea"], + "enum": [ + "moveToAddressableArea" + ], "type": "string" }, "params": { @@ -2068,7 +2398,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "MoveToAddressableAreaForDropTipParams": { "title": "MoveToAddressableAreaForDropTipParams", @@ -2128,7 +2460,10 @@ "type": "boolean" } }, - "required": ["pipetteId", "addressableAreaName"] + "required": [ + "pipetteId", + "addressableAreaName" + ] }, "MoveToAddressableAreaForDropTipCreate": { "title": "MoveToAddressableAreaForDropTipCreate", @@ -2138,7 +2473,9 @@ "commandType": { "title": "Commandtype", "default": "moveToAddressableAreaForDropTip", - "enum": ["moveToAddressableAreaForDropTip"], + "enum": [ + "moveToAddressableAreaForDropTip" + ], "type": "string" }, "params": { @@ -2158,7 +2495,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "PrepareToAspirateParams": { "title": "PrepareToAspirateParams", @@ -2171,7 +2510,9 @@ "type": "string" } }, - "required": ["pipetteId"] + "required": [ + "pipetteId" + ] }, "PrepareToAspirateCreate": { "title": "PrepareToAspirateCreate", @@ -2181,7 +2522,9 @@ "commandType": { "title": "Commandtype", "default": "prepareToAspirate", - "enum": ["prepareToAspirate"], + "enum": [ + "prepareToAspirate" + ], "type": "string" }, "params": { @@ -2201,7 +2544,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "WaitForResumeParams": { "title": "WaitForResumeParams", @@ -2223,7 +2568,10 @@ "commandType": { "title": "Commandtype", "default": "waitForResume", - "enum": ["waitForResume", "pause"], + "enum": [ + "waitForResume", + "pause" + ], "type": "string" }, "params": { @@ -2243,7 +2591,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "WaitForDurationParams": { "title": "WaitForDurationParams", @@ -2261,7 +2611,9 @@ "type": "string" } }, - "required": ["seconds"] + "required": [ + "seconds" + ] }, "WaitForDurationCreate": { "title": "WaitForDurationCreate", @@ -2271,7 +2623,9 @@ "commandType": { "title": "Commandtype", "default": "waitForDuration", - "enum": ["waitForDuration"], + "enum": [ + "waitForDuration" + ], "type": "string" }, "params": { @@ -2291,7 +2645,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "PickUpTipParams": { "title": "PickUpTipParams", @@ -2323,7 +2679,11 @@ "type": "string" } }, - "required": ["labwareId", "wellName", "pipetteId"] + "required": [ + "labwareId", + "wellName", + "pipetteId" + ] }, "PickUpTipCreate": { "title": "PickUpTipCreate", @@ -2333,7 +2693,9 @@ "commandType": { "title": "Commandtype", "default": "pickUpTip", - "enum": ["pickUpTip"], + "enum": [ + "pickUpTip" + ], "type": "string" }, "params": { @@ -2353,7 +2715,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "SavePositionParams": { "title": "SavePositionParams", @@ -2377,7 +2741,9 @@ "type": "boolean" } }, - "required": ["pipetteId"] + "required": [ + "pipetteId" + ] }, "SavePositionCreate": { "title": "SavePositionCreate", @@ -2387,7 +2753,9 @@ "commandType": { "title": "Commandtype", "default": "savePosition", - "enum": ["savePosition"], + "enum": [ + "savePosition" + ], "type": "string" }, "params": { @@ -2407,7 +2775,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "SetRailLightsParams": { "title": "SetRailLightsParams", @@ -2420,7 +2790,9 @@ "type": "boolean" } }, - "required": ["on"] + "required": [ + "on" + ] }, "SetRailLightsCreate": { "title": "SetRailLightsCreate", @@ -2430,7 +2802,9 @@ "commandType": { "title": "Commandtype", "default": "setRailLights", - "enum": ["setRailLights"], + "enum": [ + "setRailLights" + ], "type": "string" }, "params": { @@ -2450,7 +2824,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "TouchTipParams": { "title": "TouchTipParams", @@ -2493,7 +2869,11 @@ "type": "number" } }, - "required": ["labwareId", "wellName", "pipetteId"] + "required": [ + "labwareId", + "wellName", + "pipetteId" + ] }, "TouchTipCreate": { "title": "TouchTipCreate", @@ -2503,7 +2883,9 @@ "commandType": { "title": "Commandtype", "default": "touchTip", - "enum": ["touchTip"], + "enum": [ + "touchTip" + ], "type": "string" }, "params": { @@ -2523,12 +2905,20 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "StatusBarAnimation": { "title": "StatusBarAnimation", "description": "Status Bar animation options.", - "enum": ["idle", "confirm", "updating", "disco", "off"] + "enum": [ + "idle", + "confirm", + "updating", + "disco", + "off" + ] }, "SetStatusBarParams": { "title": "SetStatusBarParams", @@ -2544,7 +2934,9 @@ ] } }, - "required": ["animation"] + "required": [ + "animation" + ] }, "SetStatusBarCreate": { "title": "SetStatusBarCreate", @@ -2554,7 +2946,9 @@ "commandType": { "title": "Commandtype", "default": "setStatusBar", - "enum": ["setStatusBar"], + "enum": [ + "setStatusBar" + ], "type": "string" }, "params": { @@ -2574,12 +2968,18 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "TipPresenceStatus": { "title": "TipPresenceStatus", "description": "Tip presence status reported by a pipette.", - "enum": ["present", "absent", "unknown"], + "enum": [ + "present", + "absent", + "unknown" + ], "type": "string" }, "VerifyTipPresenceParams": { @@ -2601,7 +3001,10 @@ ] } }, - "required": ["pipetteId", "expectedState"] + "required": [ + "pipetteId", + "expectedState" + ] }, "VerifyTipPresenceCreate": { "title": "VerifyTipPresenceCreate", @@ -2611,7 +3014,9 @@ "commandType": { "title": "Commandtype", "default": "verifyTipPresence", - "enum": ["verifyTipPresence"], + "enum": [ + "verifyTipPresence" + ], "type": "string" }, "params": { @@ -2631,7 +3036,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "GetTipPresenceParams": { "title": "GetTipPresenceParams", @@ -2644,7 +3051,9 @@ "type": "string" } }, - "required": ["pipetteId"] + "required": [ + "pipetteId" + ] }, "GetTipPresenceCreate": { "title": "GetTipPresenceCreate", @@ -2654,7 +3063,9 @@ "commandType": { "title": "Commandtype", "default": "getTipPresence", - "enum": ["getTipPresence"], + "enum": [ + "getTipPresence" + ], "type": "string" }, "params": { @@ -2674,7 +3085,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureParams": { "title": "WaitForTemperatureParams", @@ -2692,7 +3105,9 @@ "type": "number" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureCreate": { "title": "WaitForTemperatureCreate", @@ -2702,7 +3117,9 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/waitForTemperature", - "enum": ["heaterShaker/waitForTemperature"], + "enum": [ + "heaterShaker/waitForTemperature" + ], "type": "string" }, "params": { @@ -2722,7 +3139,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureParams": { "title": "SetTargetTemperatureParams", @@ -2740,7 +3159,10 @@ "type": "number" } }, - "required": ["moduleId", "celsius"] + "required": [ + "moduleId", + "celsius" + ] }, "opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureCreate": { "title": "SetTargetTemperatureCreate", @@ -2750,7 +3172,9 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/setTargetTemperature", - "enum": ["heaterShaker/setTargetTemperature"], + "enum": [ + "heaterShaker/setTargetTemperature" + ], "type": "string" }, "params": { @@ -2770,7 +3194,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DeactivateHeaterParams": { "title": "DeactivateHeaterParams", @@ -2783,7 +3209,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "DeactivateHeaterCreate": { "title": "DeactivateHeaterCreate", @@ -2793,7 +3221,9 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/deactivateHeater", - "enum": ["heaterShaker/deactivateHeater"], + "enum": [ + "heaterShaker/deactivateHeater" + ], "type": "string" }, "params": { @@ -2813,7 +3243,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "SetAndWaitForShakeSpeedParams": { "title": "SetAndWaitForShakeSpeedParams", @@ -2831,7 +3263,10 @@ "type": "number" } }, - "required": ["moduleId", "rpm"] + "required": [ + "moduleId", + "rpm" + ] }, "SetAndWaitForShakeSpeedCreate": { "title": "SetAndWaitForShakeSpeedCreate", @@ -2841,7 +3276,9 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/setAndWaitForShakeSpeed", - "enum": ["heaterShaker/setAndWaitForShakeSpeed"], + "enum": [ + "heaterShaker/setAndWaitForShakeSpeed" + ], "type": "string" }, "params": { @@ -2861,7 +3298,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DeactivateShakerParams": { "title": "DeactivateShakerParams", @@ -2874,7 +3313,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "DeactivateShakerCreate": { "title": "DeactivateShakerCreate", @@ -2884,7 +3325,9 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/deactivateShaker", - "enum": ["heaterShaker/deactivateShaker"], + "enum": [ + "heaterShaker/deactivateShaker" + ], "type": "string" }, "params": { @@ -2904,7 +3347,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "OpenLabwareLatchParams": { "title": "OpenLabwareLatchParams", @@ -2917,7 +3362,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "OpenLabwareLatchCreate": { "title": "OpenLabwareLatchCreate", @@ -2927,7 +3374,9 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/openLabwareLatch", - "enum": ["heaterShaker/openLabwareLatch"], + "enum": [ + "heaterShaker/openLabwareLatch" + ], "type": "string" }, "params": { @@ -2947,7 +3396,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "CloseLabwareLatchParams": { "title": "CloseLabwareLatchParams", @@ -2960,7 +3411,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "CloseLabwareLatchCreate": { "title": "CloseLabwareLatchCreate", @@ -2970,7 +3423,9 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/closeLabwareLatch", - "enum": ["heaterShaker/closeLabwareLatch"], + "enum": [ + "heaterShaker/closeLabwareLatch" + ], "type": "string" }, "params": { @@ -2990,7 +3445,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DisengageParams": { "title": "DisengageParams", @@ -3003,7 +3460,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "DisengageCreate": { "title": "DisengageCreate", @@ -3013,7 +3472,9 @@ "commandType": { "title": "Commandtype", "default": "magneticModule/disengage", - "enum": ["magneticModule/disengage"], + "enum": [ + "magneticModule/disengage" + ], "type": "string" }, "params": { @@ -3033,7 +3494,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "EngageParams": { "title": "EngageParams", @@ -3051,7 +3514,10 @@ "type": "number" } }, - "required": ["moduleId", "height"] + "required": [ + "moduleId", + "height" + ] }, "EngageCreate": { "title": "EngageCreate", @@ -3061,7 +3527,9 @@ "commandType": { "title": "Commandtype", "default": "magneticModule/engage", - "enum": ["magneticModule/engage"], + "enum": [ + "magneticModule/engage" + ], "type": "string" }, "params": { @@ -3081,7 +3549,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureParams": { "title": "SetTargetTemperatureParams", @@ -3099,7 +3569,10 @@ "type": "number" } }, - "required": ["moduleId", "celsius"] + "required": [ + "moduleId", + "celsius" + ] }, "opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureCreate": { "title": "SetTargetTemperatureCreate", @@ -3109,7 +3582,9 @@ "commandType": { "title": "Commandtype", "default": "temperatureModule/setTargetTemperature", - "enum": ["temperatureModule/setTargetTemperature"], + "enum": [ + "temperatureModule/setTargetTemperature" + ], "type": "string" }, "params": { @@ -3129,7 +3604,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureParams": { "title": "WaitForTemperatureParams", @@ -3147,7 +3624,9 @@ "type": "number" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureCreate": { "title": "WaitForTemperatureCreate", @@ -3157,7 +3636,9 @@ "commandType": { "title": "Commandtype", "default": "temperatureModule/waitForTemperature", - "enum": ["temperatureModule/waitForTemperature"], + "enum": [ + "temperatureModule/waitForTemperature" + ], "type": "string" }, "params": { @@ -3177,7 +3658,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DeactivateTemperatureParams": { "title": "DeactivateTemperatureParams", @@ -3190,7 +3673,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "DeactivateTemperatureCreate": { "title": "DeactivateTemperatureCreate", @@ -3200,7 +3685,9 @@ "commandType": { "title": "Commandtype", "default": "temperatureModule/deactivate", - "enum": ["temperatureModule/deactivate"], + "enum": [ + "temperatureModule/deactivate" + ], "type": "string" }, "params": { @@ -3220,7 +3707,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "SetTargetBlockTemperatureParams": { "title": "SetTargetBlockTemperatureParams", @@ -3248,7 +3737,10 @@ "type": "number" } }, - "required": ["moduleId", "celsius"] + "required": [ + "moduleId", + "celsius" + ] }, "SetTargetBlockTemperatureCreate": { "title": "SetTargetBlockTemperatureCreate", @@ -3258,7 +3750,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/setTargetBlockTemperature", - "enum": ["thermocycler/setTargetBlockTemperature"], + "enum": [ + "thermocycler/setTargetBlockTemperature" + ], "type": "string" }, "params": { @@ -3278,7 +3772,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "WaitForBlockTemperatureParams": { "title": "WaitForBlockTemperatureParams", @@ -3291,7 +3787,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "WaitForBlockTemperatureCreate": { "title": "WaitForBlockTemperatureCreate", @@ -3301,7 +3799,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/waitForBlockTemperature", - "enum": ["thermocycler/waitForBlockTemperature"], + "enum": [ + "thermocycler/waitForBlockTemperature" + ], "type": "string" }, "params": { @@ -3321,7 +3821,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "SetTargetLidTemperatureParams": { "title": "SetTargetLidTemperatureParams", @@ -3339,7 +3841,10 @@ "type": "number" } }, - "required": ["moduleId", "celsius"] + "required": [ + "moduleId", + "celsius" + ] }, "SetTargetLidTemperatureCreate": { "title": "SetTargetLidTemperatureCreate", @@ -3349,7 +3854,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/setTargetLidTemperature", - "enum": ["thermocycler/setTargetLidTemperature"], + "enum": [ + "thermocycler/setTargetLidTemperature" + ], "type": "string" }, "params": { @@ -3369,7 +3876,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "WaitForLidTemperatureParams": { "title": "WaitForLidTemperatureParams", @@ -3382,7 +3891,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "WaitForLidTemperatureCreate": { "title": "WaitForLidTemperatureCreate", @@ -3392,7 +3903,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/waitForLidTemperature", - "enum": ["thermocycler/waitForLidTemperature"], + "enum": [ + "thermocycler/waitForLidTemperature" + ], "type": "string" }, "params": { @@ -3412,7 +3925,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DeactivateBlockParams": { "title": "DeactivateBlockParams", @@ -3425,7 +3940,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "DeactivateBlockCreate": { "title": "DeactivateBlockCreate", @@ -3435,7 +3952,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/deactivateBlock", - "enum": ["thermocycler/deactivateBlock"], + "enum": [ + "thermocycler/deactivateBlock" + ], "type": "string" }, "params": { @@ -3455,7 +3974,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "DeactivateLidParams": { "title": "DeactivateLidParams", @@ -3468,7 +3989,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "DeactivateLidCreate": { "title": "DeactivateLidCreate", @@ -3478,7 +4001,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/deactivateLid", - "enum": ["thermocycler/deactivateLid"], + "enum": [ + "thermocycler/deactivateLid" + ], "type": "string" }, "params": { @@ -3498,7 +4023,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "OpenLidParams": { "title": "OpenLidParams", @@ -3511,7 +4038,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "OpenLidCreate": { "title": "OpenLidCreate", @@ -3521,7 +4050,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/openLid", - "enum": ["thermocycler/openLid"], + "enum": [ + "thermocycler/openLid" + ], "type": "string" }, "params": { @@ -3541,7 +4072,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "CloseLidParams": { "title": "CloseLidParams", @@ -3554,7 +4087,9 @@ "type": "string" } }, - "required": ["moduleId"] + "required": [ + "moduleId" + ] }, "CloseLidCreate": { "title": "CloseLidCreate", @@ -3564,7 +4099,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/closeLid", - "enum": ["thermocycler/closeLid"], + "enum": [ + "thermocycler/closeLid" + ], "type": "string" }, "params": { @@ -3584,7 +4121,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "RunProfileStepParams": { "title": "RunProfileStepParams", @@ -3602,7 +4141,10 @@ "type": "number" } }, - "required": ["celsius", "holdSeconds"] + "required": [ + "celsius", + "holdSeconds" + ] }, "RunProfileParams": { "title": "RunProfileParams", @@ -3628,7 +4170,10 @@ "type": "number" } }, - "required": ["moduleId", "profile"] + "required": [ + "moduleId", + "profile" + ] }, "RunProfileCreate": { "title": "RunProfileCreate", @@ -3638,7 +4183,9 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/runProfile", - "enum": ["thermocycler/runProfile"], + "enum": [ + "thermocycler/runProfile" + ], "type": "string" }, "params": { @@ -3658,12 +4205,17 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "CalibrateGripperParamsJaw": { "title": "CalibrateGripperParamsJaw", "description": "An enumeration.", - "enum": ["front", "rear"] + "enum": [ + "front", + "rear" + ] }, "Vec3f": { "title": "Vec3f", @@ -3683,7 +4235,11 @@ "type": "number" } }, - "required": ["x", "y", "z"] + "required": [ + "x", + "y", + "z" + ] }, "CalibrateGripperParams": { "title": "CalibrateGripperParams", @@ -3708,7 +4264,9 @@ ] } }, - "required": ["jaw"] + "required": [ + "jaw" + ] }, "CalibrateGripperCreate": { "title": "CalibrateGripperCreate", @@ -3718,7 +4276,9 @@ "commandType": { "title": "Commandtype", "default": "calibration/calibrateGripper", - "enum": ["calibration/calibrateGripper"], + "enum": [ + "calibration/calibrateGripper" + ], "type": "string" }, "params": { @@ -3738,7 +4298,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "CalibratePipetteParams": { "title": "CalibratePipetteParams", @@ -3754,7 +4316,9 @@ ] } }, - "required": ["mount"] + "required": [ + "mount" + ] }, "CalibratePipetteCreate": { "title": "CalibratePipetteCreate", @@ -3764,7 +4328,9 @@ "commandType": { "title": "Commandtype", "default": "calibration/calibratePipette", - "enum": ["calibration/calibratePipette"], + "enum": [ + "calibration/calibratePipette" + ], "type": "string" }, "params": { @@ -3784,7 +4350,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "CalibrateModuleParams": { "title": "CalibrateModuleParams", @@ -3810,7 +4378,11 @@ ] } }, - "required": ["moduleId", "labwareId", "mount"] + "required": [ + "moduleId", + "labwareId", + "mount" + ] }, "CalibrateModuleCreate": { "title": "CalibrateModuleCreate", @@ -3820,7 +4392,9 @@ "commandType": { "title": "Commandtype", "default": "calibration/calibrateModule", - "enum": ["calibration/calibrateModule"], + "enum": [ + "calibration/calibrateModule" + ], "type": "string" }, "params": { @@ -3840,12 +4414,17 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] }, "MaintenancePosition": { "title": "MaintenancePosition", "description": "Maintenance position options.", - "enum": ["attachPlate", "attachInstrument"] + "enum": [ + "attachPlate", + "attachInstrument" + ] }, "MoveToMaintenancePositionParams": { "title": "MoveToMaintenancePositionParams", @@ -3870,7 +4449,9 @@ ] } }, - "required": ["mount"] + "required": [ + "mount" + ] }, "MoveToMaintenancePositionCreate": { "title": "MoveToMaintenancePositionCreate", @@ -3880,7 +4461,9 @@ "commandType": { "title": "Commandtype", "default": "calibration/moveToMaintenancePosition", - "enum": ["calibration/moveToMaintenancePosition"], + "enum": [ + "calibration/moveToMaintenancePosition" + ], "type": "string" }, "params": { @@ -3900,7 +4483,9 @@ "type": "string" } }, - "required": ["params"] + "required": [ + "params" + ] } }, "$id": "opentronsCommandSchemaV8", From 3e78dd36efa1a1949d9bd1d5e36150e5b9378bdf Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Fri, 19 Apr 2024 13:47:25 -0400 Subject: [PATCH 02/10] implement tip state handling --- .../opentrons/protocol_engine/state/tips.py | 41 +++- .../protocol_engine/state/test_tip_state.py | 186 +++++++++++++++++- 2 files changed, 213 insertions(+), 14 deletions(-) diff --git a/api/src/opentrons/protocol_engine/state/tips.py b/api/src/opentrons/protocol_engine/state/tips.py index f5d68d61ee5..96e7bafe327 100644 --- a/api/src/opentrons/protocol_engine/state/tips.py +++ b/api/src/opentrons/protocol_engine/state/tips.py @@ -3,6 +3,10 @@ from enum import Enum from typing import Dict, Optional, List, Union +from opentrons_shared_data.labware.labware_definition import LabwareDefinition + +from opentrons.hardware_control.nozzle_manager import NozzleMap + from .abstract_store import HasState, HandlesActions from ..actions import ( Action, @@ -13,6 +17,7 @@ from ..commands import ( Command, LoadLabwareResult, + ReloadLabwareResult, PickUpTip, PickUpTipResult, DropTipResult, @@ -24,8 +29,6 @@ ) from ..error_recovery_policy import ErrorRecoveryType -from opentrons.hardware_control.nozzle_manager import NozzleMap - class TipRackWellState(Enum): """The state of a single tip in a tip rack's well.""" @@ -100,6 +103,16 @@ def handle_action(self, action: Action) -> None: well_name ] = TipRackWellState.CLEAN + def _add_new_tiprack(self, labware_id: str, definition: LabwareDefinition) -> None: + self._state.tips_by_labware_id[labware_id] = { + well_name: TipRackWellState.CLEAN + for column in definition.ordering + for well_name in column + } + self._state.column_by_labware_id[labware_id] = [ + column for column in definition.ordering + ] + def _handle_succeeded_command(self, command: Command) -> None: if ( isinstance(command.result, LoadLabwareResult) @@ -107,14 +120,7 @@ def _handle_succeeded_command(self, command: Command) -> None: ): labware_id = command.result.labwareId definition = command.result.definition - self._state.tips_by_labware_id[labware_id] = { - well_name: TipRackWellState.CLEAN - for column in definition.ordering - for well_name in column - } - self._state.column_by_labware_id[labware_id] = [ - column for column in definition.ordering - ] + self._add_new_tiprack(labware_id, definition) elif isinstance(command.result, PickUpTipResult): labware_id = command.params.labwareId @@ -130,6 +136,21 @@ def _handle_succeeded_command(self, command: Command) -> None: pipette_id = command.params.pipetteId self._state.length_by_pipette_id.pop(pipette_id, None) + elif isinstance(command.result, ReloadLabwareResult): + if ( + command.result.definition.parameters.isTiprack + and command.result.labwareId not in self._state.tips_by_labware_id + ): + self._add_new_tiprack( + command.result.labwareId, command.result.definition + ) + elif ( + not command.result.definition.parameters.isTiprack + and command.result.labwareId in self._state.tips_by_labware_id + ): + self._state.tips_by_labware_id.pop(command.result.labwareId) + self._state.column_by_labware_id.pop(command.result.labwareId) + def _handle_failed_command( self, action: FailCommandAction, diff --git a/api/tests/opentrons/protocol_engine/state/test_tip_state.py b/api/tests/opentrons/protocol_engine/state/test_tip_state.py index 25894554027..2af4a486319 100644 --- a/api/tests/opentrons/protocol_engine/state/test_tip_state.py +++ b/api/tests/opentrons/protocol_engine/state/test_tip_state.py @@ -36,9 +36,9 @@ def subject() -> TipStore: return TipStore() -@pytest.fixture -def labware_definition() -> LabwareDefinition: - """Get a labware definition value object.""" +def _default_labware_def( + parameters: Optional[LabwareParameters] = None, +) -> LabwareDefinition: return LabwareDefinition.construct( # type: ignore[call-arg] ordering=[ ["A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1"], @@ -54,10 +54,22 @@ def labware_definition() -> LabwareDefinition: ["A11", "B11", "C11", "D11", "E11", "F11", "G11", "H11"], ["A12", "B12", "C12", "D12", "E12", "F12", "G12", "H12"], ], - parameters=_tip_rack_parameters, + parameters=parameters or _tip_rack_parameters, ) +@pytest.fixture +def labware_definition() -> LabwareDefinition: + """Get a labware definition value object.""" + return _default_labware_def() + + +@pytest.fixture +def reload_labware_definition() -> LabwareDefinition: + """Get a labware definition for reloading.""" + return _default_labware_def() + + @pytest.fixture def load_labware_command(labware_definition: LabwareDefinition) -> commands.LoadLabware: """Get a load labware command value object.""" @@ -69,6 +81,18 @@ def load_labware_command(labware_definition: LabwareDefinition) -> commands.Load ) +@pytest.fixture +def reload_labware_command( + reload_labware_definition: LabwareDefinition, +) -> commands.ReloadLabware: + """Get a reload labware command.""" + return commands.ReloadLabware.construct( # type: ignore[call-arg] + result=commands.ReloadLabwareResult.construct( + labwareId="cool-labware", definition=reload_labware_definition + ) + ) + + @pytest.fixture def pick_up_tip_command() -> commands.PickUpTip: """Get a pick-up tip command value object.""" @@ -1135,3 +1159,157 @@ def _reconfigure_nozzle_layout(start: str, back_l: str, front_r: str) -> NozzleM _assert_and_pickup("B1", map) map = _reconfigure_nozzle_layout("A1", "A1", "A1") _assert_and_pickup("B2", map) + + +def test_reload_tiprack_does_not_alter_tip_state( + subject: TipStore, + load_labware_command: commands.LoadLabware, + pick_up_tip_command: commands.PickUpTip, + reload_labware_command: commands.ReloadLabware, + supported_tip_fixture: pipette_definition.SupportedTipsDefinition, +) -> None: + """Reloading a tiprack is not the same as resetting the tips.""" + subject.handle_action( + actions.SucceedCommandAction(private_result=None, command=load_labware_command) + ) + load_pipette_command = commands.LoadPipette.construct( # type: ignore[call-arg] + result=commands.LoadPipetteResult(pipetteId="pipette-id") + ) + load_pipette_private_result = commands.LoadPipettePrivateResult( + pipette_id="pipette-id", + serial_number="pipette-serial", + config=LoadedStaticPipetteData( + channels=1, + max_volume=15, + min_volume=3, + model="gen a", + display_name="display name", + flow_rates=FlowRates( + default_aspirate={}, + default_dispense={}, + default_blow_out={}, + ), + tip_configuration_lookup_table={15: supported_tip_fixture}, + nominal_tip_overlap={}, + nozzle_offset_z=1.23, + home_position=4.56, + nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE_GEN2), + back_left_corner_offset=Point(x=1, y=2, z=3), + front_right_corner_offset=Point(x=4, y=5, z=6), + ), + ) + + subject.handle_action( + actions.SucceedCommandAction( + private_result=load_pipette_private_result, command=load_pipette_command + ) + ) + + subject.handle_action( + actions.SucceedCommandAction(private_result=None, command=pick_up_tip_command) + ) + subject.handle_action( + actions.SucceedCommandAction( + private_result=None, command=reload_labware_command + ) + ) + result = TipView(subject.state).get_next_tip( + labware_id="cool-labware", + num_tips=1, + starting_tip_name=None, + nozzle_map=None, + ) + + assert result == "B1" + + +@pytest.mark.parametrize( + "labware_definition", + [ + _default_labware_def( + parameters=LabwareParameters.construct(isTiprack=False) # type: ignore[call-arg] + ) + ], +) +def test_reload_to_tiprack_loads( + subject: TipStore, + load_labware_command: commands.LoadLabware, + reload_labware_command: commands.ReloadLabware, +) -> None: + """If you have a loaded non-tiprack and reload with a tiprack, state should appear.""" + subject.handle_action( + actions.SucceedCommandAction(private_result=None, command=load_labware_command) + ) + assert load_labware_command.result + assert ( + TipView(subject.state).get_next_tip( + labware_id=load_labware_command.result.labwareId, + num_tips=1, + starting_tip_name=None, + nozzle_map=None, + ) + is None + ) + + subject.handle_action( + actions.SucceedCommandAction( + private_result=None, command=reload_labware_command + ) + ) + result = TipView(subject.state).get_next_tip( + labware_id="cool-labware", + num_tips=1, + starting_tip_name=None, + nozzle_map=None, + ) + + assert result == "A1" + + +@pytest.mark.parametrize( + "reload_labware_definition", + [ + _default_labware_def( + parameters=LabwareParameters.construct(isTiprack=False) # type: ignore[call-arg] + ) + ], +) +def test_reload_to_non_tiprack_unloads( + subject: TipStore, + load_labware_command: commands.LoadLabware, + reload_labware_command: commands.ReloadLabware, +) -> None: + """If you have a loaded tiprack and reload with a non-tiprack def, state should go away.""" + subject.handle_action( + actions.SucceedCommandAction(private_result=None, command=load_labware_command) + ) + result = TipView(subject.state).get_next_tip( + labware_id="cool-labware", + num_tips=1, + starting_tip_name=None, + nozzle_map=None, + ) + assert result == "A1" + + subject.handle_action( + actions.SucceedCommandAction( + private_result=None, command=reload_labware_command + ) + ) + result = TipView(subject.state).get_next_tip( + labware_id="cool-labware", + num_tips=1, + starting_tip_name=None, + nozzle_map=None, + ) + assert load_labware_command.result + + assert ( + TipView(subject.state).get_next_tip( + labware_id=load_labware_command.result.labwareId, + num_tips=1, + starting_tip_name=None, + nozzle_map=None, + ) + is None + ) From 83e8cb832cf2cd0d2002740180abfe8b8b1d156e Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Fri, 19 Apr 2024 14:06:57 -0400 Subject: [PATCH 03/10] implement labware handling --- .../protocol_engine/state/labware.py | 9 ++- .../protocol_engine/state/command_fixtures.py | 31 +++++++++ .../state/test_labware_store.py | 68 +++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/api/src/opentrons/protocol_engine/state/labware.py b/api/src/opentrons/protocol_engine/state/labware.py index a11f1a58e4a..743c582678b 100644 --- a/api/src/opentrons/protocol_engine/state/labware.py +++ b/api/src/opentrons/protocol_engine/state/labware.py @@ -31,6 +31,7 @@ Command, LoadLabwareResult, MoveLabwareResult, + ReloadLabwareResult, ) from ..types import ( DeckSlotLocation, @@ -175,7 +176,7 @@ def handle_action(self, action: Action) -> None: def _handle_command(self, command: Command) -> None: """Modify state in reaction to a command.""" - if isinstance(command.result, LoadLabwareResult): + if isinstance(command.result, (LoadLabwareResult, ReloadLabwareResult)): # If the labware load refers to an offset, that offset must actually exist. if command.result.offsetId is not None: assert command.result.offsetId in self._state.labware_offsets_by_id @@ -187,12 +188,16 @@ def _handle_command(self, command: Command) -> None: ) self._state.definitions_by_uri[definition_uri] = command.result.definition + if isinstance(command.result, LoadLabwareResult): + location = command.params.location + else: + location = self._state.labware_by_id[command.result.labwareId].location self._state.labware_by_id[ command.result.labwareId ] = LoadedLabware.construct( id=command.result.labwareId, - location=command.params.location, + location=location, loadName=command.result.definition.parameters.loadName, definitionUri=definition_uri, offsetId=command.result.offsetId, diff --git a/api/tests/opentrons/protocol_engine/state/command_fixtures.py b/api/tests/opentrons/protocol_engine/state/command_fixtures.py index 191dd49bd48..aeab8eb621b 100644 --- a/api/tests/opentrons/protocol_engine/state/command_fixtures.py +++ b/api/tests/opentrons/protocol_engine/state/command_fixtures.py @@ -577,3 +577,34 @@ def create_prepare_to_aspirate_command(pipette_id: str) -> cmd.PrepareToAspirate params=params, result=result, ) + + +def create_reload_labware_command( + labware_id: str, + definition: LabwareDefinition, + offset_id: Optional[str], + display_name: Optional[str], +) -> cmd.ReloadLabware: + """Create a completed ReloadLabware command.""" + params = cmd.ReloadLabwareParams( + loadName=definition.parameters.loadName, + namespace=definition.namespace, + version=definition.version, + labwareId=labware_id, + displayName=display_name, + ) + + result = cmd.ReloadLabwareResult( + labwareId=labware_id, + definition=definition, + offsetId=offset_id, + ) + + return cmd.ReloadLabware( + id="command-id", + key="command-key", + status=cmd.CommandStatus.SUCCEEDED, + createdAt=datetime.now(), + params=params, + result=result, + ) diff --git a/api/tests/opentrons/protocol_engine/state/test_labware_store.py b/api/tests/opentrons/protocol_engine/state/test_labware_store.py index 9d926583fb0..77de86b4a65 100644 --- a/api/tests/opentrons/protocol_engine/state/test_labware_store.py +++ b/api/tests/opentrons/protocol_engine/state/test_labware_store.py @@ -28,6 +28,7 @@ from .command_fixtures import ( create_load_labware_command, create_move_labware_command, + create_reload_labware_command, ) @@ -132,6 +133,73 @@ def test_handles_load_labware( assert subject.state.definitions_by_uri[expected_definition_uri] == well_plate_def +def test_handles_reload_labware( + subject: LabwareStore, + well_plate_def: LabwareDefinition, + flex_50uL_tiprack: LabwareDefinition, +) -> None: + """It should override labware data in the state.""" + load_labware = create_load_labware_command( + location=DeckSlotLocation(slotName=DeckSlotName.SLOT_A1), + labware_id="test-labware-id", + definition=well_plate_def, + display_name="display-name", + offset_id=None, + ) + + subject.handle_action( + SucceedCommandAction(private_result=None, command=load_labware) + ) + assert subject.state.labware_by_id[ + "test-labware-id" + ].definitionUri == uri_from_details( + load_name=well_plate_def.parameters.loadName, + namespace=well_plate_def.namespace, + version=well_plate_def.version, + ) + + offset_request = LabwareOffsetCreate( + definitionUri="offset-definition-uri", + location=LabwareOffsetLocation(slotName=DeckSlotName.SLOT_1), + vector=LabwareOffsetVector(x=1, y=2, z=3), + ) + subject.handle_action( + AddLabwareOffsetAction( + request=offset_request, + labware_offset_id="offset-id", + created_at=datetime(year=2021, month=1, day=2), + ) + ) + reload_labware = create_reload_labware_command( + labware_id="test-labware-id", + definition=flex_50uL_tiprack, + offset_id="offset-id", + display_name="display-name-2", + ) + subject.handle_action( + SucceedCommandAction(private_result=None, command=reload_labware) + ) + + expected_definition_uri = uri_from_details( + load_name=flex_50uL_tiprack.parameters.loadName, + namespace=flex_50uL_tiprack.namespace, + version=flex_50uL_tiprack.version, + ) + + expected_labware_data = LoadedLabware( + id="test-labware-id", + loadName=flex_50uL_tiprack.parameters.loadName, + definitionUri=expected_definition_uri, + location=DeckSlotLocation(slotName=DeckSlotName.SLOT_A1), + offsetId="offset-id", + displayName="display-name-2", + ) + assert subject.state.labware_by_id["test-labware-id"] == expected_labware_data + assert ( + subject.state.definitions_by_uri[expected_definition_uri] == flex_50uL_tiprack + ) + + def test_handles_add_labware_definition( subject: LabwareStore, well_plate_def: LabwareDefinition, From ee514d525cf8817658f644f51b2b4a5077ec422c Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Fri, 19 Apr 2024 14:21:37 -0400 Subject: [PATCH 04/10] add sync client implementation --- .../protocol_engine/clients/sync_client.py | 21 ++++++++++++ .../clients/test_sync_client.py | 33 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/api/src/opentrons/protocol_engine/clients/sync_client.py b/api/src/opentrons/protocol_engine/clients/sync_client.py index f95611c1b4c..c553b737ec0 100644 --- a/api/src/opentrons/protocol_engine/clients/sync_client.py +++ b/api/src/opentrons/protocol_engine/clients/sync_client.py @@ -127,6 +127,27 @@ def load_labware( return cast(commands.LoadLabwareResult, result) + def reload_labware( + self, + labware_id: str, + load_name: str, + namespace: str, + version: int, + display_name: Optional[str] = None, + ) -> commands.ReloadLabwareResult: + """Execute a ReloadLabware command and return the result.""" + request = commands.ReloadLabwareCreate( + params=commands.ReloadLabwareParams( + labwareId=labware_id, + loadName=load_name, + namespace=namespace, + version=version, + displayName=display_name, + ) + ) + result = self._transport.execute_command(request=request) + return cast(commands.ReloadLabwareResult, result) + # TODO (spp, 2022-12-14): https://opentrons.atlassian.net/browse/RLAB-237 def move_labware( self, diff --git a/api/tests/opentrons/protocol_engine/clients/test_sync_client.py b/api/tests/opentrons/protocol_engine/clients/test_sync_client.py index d5d1f930cca..c1e7be8f4bf 100644 --- a/api/tests/opentrons/protocol_engine/clients/test_sync_client.py +++ b/api/tests/opentrons/protocol_engine/clients/test_sync_client.py @@ -161,6 +161,39 @@ def test_load_labware( assert result == expected_result +def test_reload_labware( + decoy: Decoy, + transport: ChildThreadTransport, + tip_rack_def: LabwareDefinition, + subject: SyncClient, +) -> None: + """It should execute a reload labware command.""" + expected_request = commands.ReloadLabwareCreate( + params=commands.ReloadLabwareParams( + labwareId="some-labware-id", + loadName="some_labware", + namespace="opentrons", + version=1, + displayName="some_display_name", + ) + ) + + expected_result = commands.ReloadLabwareResult( + labwareId="some-labware-id", definition=tip_rack_def, offsetId=None + ) + decoy.when(transport.execute_command(request=expected_request)).then_return( + expected_result + ) + result = subject.reload_labware( + labware_id="some-labware-id", + namespace="opentrons", + load_name="some_labware", + version=1, + display_name="some_display_name", + ) + assert result == expected_result + + def test_load_module( decoy: Decoy, transport: ChildThreadTransport, From 895c84cc37265b33349d1add1a7ba2d985739d8c Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Fri, 19 Apr 2024 15:33:15 -0400 Subject: [PATCH 05/10] format schema --- shared-data/command/schemas/8.json | 940 +++++++---------------------- 1 file changed, 211 insertions(+), 729 deletions(-) diff --git a/shared-data/command/schemas/8.json b/shared-data/command/schemas/8.json index 1a7adb09f69..d481179157d 100644 --- a/shared-data/command/schemas/8.json +++ b/shared-data/command/schemas/8.json @@ -253,11 +253,7 @@ "WellOrigin": { "title": "WellOrigin", "description": "Origin of WellLocation offset.\n\nProps:\n TOP: the top-center of the well\n BOTTOM: the bottom-center of the well\n CENTER: the middle-center of the well", - "enum": [ - "top", - "bottom", - "center" - ], + "enum": ["top", "bottom", "center"], "type": "string" }, "WellOffset": { @@ -342,21 +338,12 @@ "type": "string" } }, - "required": [ - "labwareId", - "wellName", - "flowRate", - "volume", - "pipetteId" - ] + "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"] }, "CommandIntent": { "title": "CommandIntent", "description": "Run intent for a given command.\n\nProps:\n PROTOCOL: the command is part of the protocol run itself.\n SETUP: the command is part of the setup phase of a run.", - "enum": [ - "protocol", - "setup" - ], + "enum": ["protocol", "setup"], "type": "string" }, "AspirateCreate": { @@ -367,9 +354,7 @@ "commandType": { "title": "Commandtype", "default": "aspirate", - "enum": [ - "aspirate" - ], + "enum": ["aspirate"], "type": "string" }, "params": { @@ -389,9 +374,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "AspirateInPlaceParams": { "title": "AspirateInPlaceParams", @@ -416,11 +399,7 @@ "type": "string" } }, - "required": [ - "flowRate", - "volume", - "pipetteId" - ] + "required": ["flowRate", "volume", "pipetteId"] }, "AspirateInPlaceCreate": { "title": "AspirateInPlaceCreate", @@ -430,9 +409,7 @@ "commandType": { "title": "Commandtype", "default": "aspirateInPlace", - "enum": [ - "aspirateInPlace" - ], + "enum": ["aspirateInPlace"], "type": "string" }, "params": { @@ -452,9 +429,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "CommentParams": { "title": "CommentParams", @@ -467,9 +442,7 @@ "type": "string" } }, - "required": [ - "message" - ] + "required": ["message"] }, "CommentCreate": { "title": "CommentCreate", @@ -479,9 +452,7 @@ "commandType": { "title": "Commandtype", "default": "comment", - "enum": [ - "comment" - ], + "enum": ["comment"], "type": "string" }, "params": { @@ -501,9 +472,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "ConfigureForVolumeParams": { "title": "ConfigureForVolumeParams", @@ -522,10 +491,7 @@ "type": "number" } }, - "required": [ - "pipetteId", - "volume" - ] + "required": ["pipetteId", "volume"] }, "ConfigureForVolumeCreate": { "title": "ConfigureForVolumeCreate", @@ -535,9 +501,7 @@ "commandType": { "title": "Commandtype", "default": "configureForVolume", - "enum": [ - "configureForVolume" - ], + "enum": ["configureForVolume"], "type": "string" }, "params": { @@ -557,9 +521,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "AllNozzleLayoutConfiguration": { "title": "AllNozzleLayoutConfiguration", @@ -569,9 +531,7 @@ "style": { "title": "Style", "default": "ALL", - "enum": [ - "ALL" - ], + "enum": ["ALL"], "type": "string" } } @@ -584,26 +544,17 @@ "style": { "title": "Style", "default": "SINGLE", - "enum": [ - "SINGLE" - ], + "enum": ["SINGLE"], "type": "string" }, "primaryNozzle": { "title": "Primarynozzle", "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", - "enum": [ - "A1", - "H1", - "A12", - "H12" - ], + "enum": ["A1", "H1", "A12", "H12"], "type": "string" } }, - "required": [ - "primaryNozzle" - ] + "required": ["primaryNozzle"] }, "RowNozzleLayoutConfiguration": { "title": "RowNozzleLayoutConfiguration", @@ -613,26 +564,17 @@ "style": { "title": "Style", "default": "ROW", - "enum": [ - "ROW" - ], + "enum": ["ROW"], "type": "string" }, "primaryNozzle": { "title": "Primarynozzle", "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", - "enum": [ - "A1", - "H1", - "A12", - "H12" - ], + "enum": ["A1", "H1", "A12", "H12"], "type": "string" } }, - "required": [ - "primaryNozzle" - ] + "required": ["primaryNozzle"] }, "ColumnNozzleLayoutConfiguration": { "title": "ColumnNozzleLayoutConfiguration", @@ -642,26 +584,17 @@ "style": { "title": "Style", "default": "COLUMN", - "enum": [ - "COLUMN" - ], + "enum": ["COLUMN"], "type": "string" }, "primaryNozzle": { "title": "Primarynozzle", "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", - "enum": [ - "A1", - "H1", - "A12", - "H12" - ], + "enum": ["A1", "H1", "A12", "H12"], "type": "string" } }, - "required": [ - "primaryNozzle" - ] + "required": ["primaryNozzle"] }, "QuadrantNozzleLayoutConfiguration": { "title": "QuadrantNozzleLayoutConfiguration", @@ -671,20 +604,13 @@ "style": { "title": "Style", "default": "QUADRANT", - "enum": [ - "QUADRANT" - ], + "enum": ["QUADRANT"], "type": "string" }, "primaryNozzle": { "title": "Primarynozzle", "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", - "enum": [ - "A1", - "H1", - "A12", - "H12" - ], + "enum": ["A1", "H1", "A12", "H12"], "type": "string" }, "frontRightNozzle": { @@ -694,10 +620,7 @@ "type": "string" } }, - "required": [ - "primaryNozzle", - "frontRightNozzle" - ] + "required": ["primaryNozzle", "frontRightNozzle"] }, "ConfigureNozzleLayoutParams": { "title": "ConfigureNozzleLayoutParams", @@ -730,10 +653,7 @@ ] } }, - "required": [ - "pipetteId", - "configurationParams" - ] + "required": ["pipetteId", "configurationParams"] }, "ConfigureNozzleLayoutCreate": { "title": "ConfigureNozzleLayoutCreate", @@ -743,9 +663,7 @@ "commandType": { "title": "Commandtype", "default": "configureNozzleLayout", - "enum": [ - "configureNozzleLayout" - ], + "enum": ["configureNozzleLayout"], "type": "string" }, "params": { @@ -765,9 +683,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "CustomParams": { "title": "CustomParams", @@ -783,9 +699,7 @@ "commandType": { "title": "Commandtype", "default": "custom", - "enum": [ - "custom" - ], + "enum": ["custom"], "type": "string" }, "params": { @@ -805,9 +719,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DispenseParams": { "title": "DispenseParams", @@ -856,13 +768,7 @@ "type": "number" } }, - "required": [ - "labwareId", - "wellName", - "flowRate", - "volume", - "pipetteId" - ] + "required": ["labwareId", "wellName", "flowRate", "volume", "pipetteId"] }, "DispenseCreate": { "title": "DispenseCreate", @@ -872,9 +778,7 @@ "commandType": { "title": "Commandtype", "default": "dispense", - "enum": [ - "dispense" - ], + "enum": ["dispense"], "type": "string" }, "params": { @@ -894,9 +798,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DispenseInPlaceParams": { "title": "DispenseInPlaceParams", @@ -926,11 +828,7 @@ "type": "number" } }, - "required": [ - "flowRate", - "volume", - "pipetteId" - ] + "required": ["flowRate", "volume", "pipetteId"] }, "DispenseInPlaceCreate": { "title": "DispenseInPlaceCreate", @@ -940,9 +838,7 @@ "commandType": { "title": "Commandtype", "default": "dispenseInPlace", - "enum": [ - "dispenseInPlace" - ], + "enum": ["dispenseInPlace"], "type": "string" }, "params": { @@ -962,9 +858,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "BlowOutParams": { "title": "BlowOutParams", @@ -1002,12 +896,7 @@ "type": "string" } }, - "required": [ - "labwareId", - "wellName", - "flowRate", - "pipetteId" - ] + "required": ["labwareId", "wellName", "flowRate", "pipetteId"] }, "BlowOutCreate": { "title": "BlowOutCreate", @@ -1017,9 +906,7 @@ "commandType": { "title": "Commandtype", "default": "blowout", - "enum": [ - "blowout" - ], + "enum": ["blowout"], "type": "string" }, "params": { @@ -1039,9 +926,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "BlowOutInPlaceParams": { "title": "BlowOutInPlaceParams", @@ -1060,10 +945,7 @@ "type": "string" } }, - "required": [ - "flowRate", - "pipetteId" - ] + "required": ["flowRate", "pipetteId"] }, "BlowOutInPlaceCreate": { "title": "BlowOutInPlaceCreate", @@ -1073,9 +955,7 @@ "commandType": { "title": "Commandtype", "default": "blowOutInPlace", - "enum": [ - "blowOutInPlace" - ], + "enum": ["blowOutInPlace"], "type": "string" }, "params": { @@ -1095,19 +975,12 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DropTipWellOrigin": { "title": "DropTipWellOrigin", "description": "The origin of a DropTipWellLocation offset.\n\nProps:\n TOP: the top-center of the well\n BOTTOM: the bottom-center of the well\n CENTER: the middle-center of the well\n DEFAULT: the default drop-tip location of the well,\n based on pipette configuration and length of the tip.", - "enum": [ - "top", - "bottom", - "center", - "default" - ], + "enum": ["top", "bottom", "center", "default"], "type": "string" }, "DropTipWellLocation": { @@ -1169,11 +1042,7 @@ "type": "boolean" } }, - "required": [ - "pipetteId", - "labwareId", - "wellName" - ] + "required": ["pipetteId", "labwareId", "wellName"] }, "DropTipCreate": { "title": "DropTipCreate", @@ -1183,9 +1052,7 @@ "commandType": { "title": "Commandtype", "default": "dropTip", - "enum": [ - "dropTip" - ], + "enum": ["dropTip"], "type": "string" }, "params": { @@ -1205,9 +1072,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DropTipInPlaceParams": { "title": "DropTipInPlaceParams", @@ -1225,9 +1090,7 @@ "type": "boolean" } }, - "required": [ - "pipetteId" - ] + "required": ["pipetteId"] }, "DropTipInPlaceCreate": { "title": "DropTipInPlaceCreate", @@ -1237,9 +1100,7 @@ "commandType": { "title": "Commandtype", "default": "dropTipInPlace", - "enum": [ - "dropTipInPlace" - ], + "enum": ["dropTipInPlace"], "type": "string" }, "params": { @@ -1259,9 +1120,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "MotorAxis": { "title": "MotorAxis", @@ -1281,11 +1140,7 @@ "MountType": { "title": "MountType", "description": "An enumeration.", - "enum": [ - "left", - "right", - "extension" - ], + "enum": ["left", "right", "extension"], "type": "string" }, "HomeParams": { @@ -1318,9 +1173,7 @@ "commandType": { "title": "Commandtype", "default": "home", - "enum": [ - "home" - ], + "enum": ["home"], "type": "string" }, "params": { @@ -1340,9 +1193,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "RetractAxisParams": { "title": "RetractAxisParams", @@ -1358,9 +1209,7 @@ ] } }, - "required": [ - "axis" - ] + "required": ["axis"] }, "RetractAxisCreate": { "title": "RetractAxisCreate", @@ -1370,9 +1219,7 @@ "commandType": { "title": "Commandtype", "default": "retractAxis", - "enum": [ - "retractAxis" - ], + "enum": ["retractAxis"], "type": "string" }, "params": { @@ -1392,9 +1239,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DeckSlotName": { "title": "DeckSlotName", @@ -1440,9 +1285,7 @@ ] } }, - "required": [ - "slotName" - ] + "required": ["slotName"] }, "ModuleLocation": { "title": "ModuleLocation", @@ -1455,9 +1298,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "OnLabwareLocation": { "title": "OnLabwareLocation", @@ -1470,9 +1311,7 @@ "type": "string" } }, - "required": [ - "labwareId" - ] + "required": ["labwareId"] }, "AddressableAreaLocation": { "title": "AddressableAreaLocation", @@ -1485,9 +1324,7 @@ "type": "string" } }, - "required": [ - "addressableAreaName" - ] + "required": ["addressableAreaName"] }, "LoadLabwareParams": { "title": "LoadLabwareParams", @@ -1508,9 +1345,7 @@ "$ref": "#/definitions/OnLabwareLocation" }, { - "enum": [ - "offDeck" - ], + "enum": ["offDeck"], "type": "string" }, { @@ -1544,12 +1379,7 @@ "type": "string" } }, - "required": [ - "location", - "loadName", - "namespace", - "version" - ] + "required": ["location", "loadName", "namespace", "version"] }, "LoadLabwareCreate": { "title": "LoadLabwareCreate", @@ -1559,9 +1389,7 @@ "commandType": { "title": "Commandtype", "default": "loadLabware", - "enum": [ - "loadLabware" - ], + "enum": ["loadLabware"], "type": "string" }, "params": { @@ -1581,9 +1409,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "ReloadLabwareParams": { "title": "ReloadLabwareParams", @@ -1616,12 +1442,7 @@ "type": "string" } }, - "required": [ - "labwareId", - "loadName", - "namespace", - "version" - ] + "required": ["labwareId", "loadName", "namespace", "version"] }, "ReloadLabwareCreate": { "title": "ReloadLabwareCreate", @@ -1631,9 +1452,7 @@ "commandType": { "title": "Commandtype", "default": "reloadLabware", - "enum": [ - "reloadLabware" - ], + "enum": ["reloadLabware"], "type": "string" }, "params": { @@ -1653,9 +1472,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "LoadLiquidParams": { "title": "LoadLiquidParams", @@ -1681,11 +1498,7 @@ } } }, - "required": [ - "liquidId", - "labwareId", - "volumeByWell" - ] + "required": ["liquidId", "labwareId", "volumeByWell"] }, "LoadLiquidCreate": { "title": "LoadLiquidCreate", @@ -1695,9 +1508,7 @@ "commandType": { "title": "Commandtype", "default": "loadLiquid", - "enum": [ - "loadLiquid" - ], + "enum": ["loadLiquid"], "type": "string" }, "params": { @@ -1717,9 +1528,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "ModuleModel": { "title": "ModuleModel", @@ -1764,10 +1573,7 @@ "type": "string" } }, - "required": [ - "model", - "location" - ] + "required": ["model", "location"] }, "LoadModuleCreate": { "title": "LoadModuleCreate", @@ -1777,9 +1583,7 @@ "commandType": { "title": "Commandtype", "default": "loadModule", - "enum": [ - "loadModule" - ], + "enum": ["loadModule"], "type": "string" }, "params": { @@ -1799,9 +1603,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "PipetteNameType": { "title": "PipetteNameType", @@ -1854,10 +1656,7 @@ "type": "string" } }, - "required": [ - "pipetteName", - "mount" - ] + "required": ["pipetteName", "mount"] }, "LoadPipetteCreate": { "title": "LoadPipetteCreate", @@ -1867,9 +1666,7 @@ "commandType": { "title": "Commandtype", "default": "loadPipette", - "enum": [ - "loadPipette" - ], + "enum": ["loadPipette"], "type": "string" }, "params": { @@ -1889,18 +1686,12 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "LabwareMovementStrategy": { "title": "LabwareMovementStrategy", "description": "Strategy to use for labware movement.", - "enum": [ - "usingGripper", - "manualMoveWithPause", - "manualMoveWithoutPause" - ], + "enum": ["usingGripper", "manualMoveWithPause", "manualMoveWithoutPause"], "type": "string" }, "LabwareOffsetVector": { @@ -1921,11 +1712,7 @@ "type": "number" } }, - "required": [ - "x", - "y", - "z" - ] + "required": ["x", "y", "z"] }, "MoveLabwareParams": { "title": "MoveLabwareParams", @@ -1951,9 +1738,7 @@ "$ref": "#/definitions/OnLabwareLocation" }, { - "enum": [ - "offDeck" - ], + "enum": ["offDeck"], "type": "string" }, { @@ -1988,11 +1773,7 @@ ] } }, - "required": [ - "labwareId", - "newLocation", - "strategy" - ] + "required": ["labwareId", "newLocation", "strategy"] }, "MoveLabwareCreate": { "title": "MoveLabwareCreate", @@ -2002,9 +1783,7 @@ "commandType": { "title": "Commandtype", "default": "moveLabware", - "enum": [ - "moveLabware" - ], + "enum": ["moveLabware"], "type": "string" }, "params": { @@ -2024,18 +1803,12 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "MovementAxis": { "title": "MovementAxis", "description": "Axis on which to issue a relative movement.", - "enum": [ - "x", - "y", - "z" - ], + "enum": ["x", "y", "z"], "type": "string" }, "MoveRelativeParams": { @@ -2062,11 +1835,7 @@ "type": "number" } }, - "required": [ - "pipetteId", - "axis", - "distance" - ] + "required": ["pipetteId", "axis", "distance"] }, "MoveRelativeCreate": { "title": "MoveRelativeCreate", @@ -2076,9 +1845,7 @@ "commandType": { "title": "Commandtype", "default": "moveRelative", - "enum": [ - "moveRelative" - ], + "enum": ["moveRelative"], "type": "string" }, "params": { @@ -2098,9 +1865,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DeckPoint": { "title": "DeckPoint", @@ -2120,11 +1885,7 @@ "type": "number" } }, - "required": [ - "x", - "y", - "z" - ] + "required": ["x", "y", "z"] }, "MoveToCoordinatesParams": { "title": "MoveToCoordinatesParams", @@ -2162,10 +1923,7 @@ ] } }, - "required": [ - "pipetteId", - "coordinates" - ] + "required": ["pipetteId", "coordinates"] }, "MoveToCoordinatesCreate": { "title": "MoveToCoordinatesCreate", @@ -2175,9 +1933,7 @@ "commandType": { "title": "Commandtype", "default": "moveToCoordinates", - "enum": [ - "moveToCoordinates" - ], + "enum": ["moveToCoordinates"], "type": "string" }, "params": { @@ -2197,9 +1953,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "MoveToWellParams": { "title": "MoveToWellParams", @@ -2247,11 +2001,7 @@ "type": "string" } }, - "required": [ - "labwareId", - "wellName", - "pipetteId" - ] + "required": ["labwareId", "wellName", "pipetteId"] }, "MoveToWellCreate": { "title": "MoveToWellCreate", @@ -2261,9 +2011,7 @@ "commandType": { "title": "Commandtype", "default": "moveToWell", - "enum": [ - "moveToWell" - ], + "enum": ["moveToWell"], "type": "string" }, "params": { @@ -2283,9 +2031,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "AddressableOffsetVector": { "title": "AddressableOffsetVector", @@ -2305,11 +2051,7 @@ "type": "number" } }, - "required": [ - "x", - "y", - "z" - ] + "required": ["x", "y", "z"] }, "MoveToAddressableAreaParams": { "title": "MoveToAddressableAreaParams", @@ -2363,10 +2105,7 @@ "type": "boolean" } }, - "required": [ - "pipetteId", - "addressableAreaName" - ] + "required": ["pipetteId", "addressableAreaName"] }, "MoveToAddressableAreaCreate": { "title": "MoveToAddressableAreaCreate", @@ -2376,9 +2115,7 @@ "commandType": { "title": "Commandtype", "default": "moveToAddressableArea", - "enum": [ - "moveToAddressableArea" - ], + "enum": ["moveToAddressableArea"], "type": "string" }, "params": { @@ -2398,9 +2135,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "MoveToAddressableAreaForDropTipParams": { "title": "MoveToAddressableAreaForDropTipParams", @@ -2460,10 +2195,7 @@ "type": "boolean" } }, - "required": [ - "pipetteId", - "addressableAreaName" - ] + "required": ["pipetteId", "addressableAreaName"] }, "MoveToAddressableAreaForDropTipCreate": { "title": "MoveToAddressableAreaForDropTipCreate", @@ -2473,9 +2205,7 @@ "commandType": { "title": "Commandtype", "default": "moveToAddressableAreaForDropTip", - "enum": [ - "moveToAddressableAreaForDropTip" - ], + "enum": ["moveToAddressableAreaForDropTip"], "type": "string" }, "params": { @@ -2495,9 +2225,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "PrepareToAspirateParams": { "title": "PrepareToAspirateParams", @@ -2510,9 +2238,7 @@ "type": "string" } }, - "required": [ - "pipetteId" - ] + "required": ["pipetteId"] }, "PrepareToAspirateCreate": { "title": "PrepareToAspirateCreate", @@ -2522,9 +2248,7 @@ "commandType": { "title": "Commandtype", "default": "prepareToAspirate", - "enum": [ - "prepareToAspirate" - ], + "enum": ["prepareToAspirate"], "type": "string" }, "params": { @@ -2544,9 +2268,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "WaitForResumeParams": { "title": "WaitForResumeParams", @@ -2568,10 +2290,7 @@ "commandType": { "title": "Commandtype", "default": "waitForResume", - "enum": [ - "waitForResume", - "pause" - ], + "enum": ["waitForResume", "pause"], "type": "string" }, "params": { @@ -2591,9 +2310,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "WaitForDurationParams": { "title": "WaitForDurationParams", @@ -2611,9 +2328,7 @@ "type": "string" } }, - "required": [ - "seconds" - ] + "required": ["seconds"] }, "WaitForDurationCreate": { "title": "WaitForDurationCreate", @@ -2623,9 +2338,7 @@ "commandType": { "title": "Commandtype", "default": "waitForDuration", - "enum": [ - "waitForDuration" - ], + "enum": ["waitForDuration"], "type": "string" }, "params": { @@ -2645,9 +2358,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "PickUpTipParams": { "title": "PickUpTipParams", @@ -2679,11 +2390,7 @@ "type": "string" } }, - "required": [ - "labwareId", - "wellName", - "pipetteId" - ] + "required": ["labwareId", "wellName", "pipetteId"] }, "PickUpTipCreate": { "title": "PickUpTipCreate", @@ -2693,9 +2400,7 @@ "commandType": { "title": "Commandtype", "default": "pickUpTip", - "enum": [ - "pickUpTip" - ], + "enum": ["pickUpTip"], "type": "string" }, "params": { @@ -2715,9 +2420,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "SavePositionParams": { "title": "SavePositionParams", @@ -2741,9 +2444,7 @@ "type": "boolean" } }, - "required": [ - "pipetteId" - ] + "required": ["pipetteId"] }, "SavePositionCreate": { "title": "SavePositionCreate", @@ -2753,9 +2454,7 @@ "commandType": { "title": "Commandtype", "default": "savePosition", - "enum": [ - "savePosition" - ], + "enum": ["savePosition"], "type": "string" }, "params": { @@ -2775,9 +2474,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "SetRailLightsParams": { "title": "SetRailLightsParams", @@ -2790,9 +2487,7 @@ "type": "boolean" } }, - "required": [ - "on" - ] + "required": ["on"] }, "SetRailLightsCreate": { "title": "SetRailLightsCreate", @@ -2802,9 +2497,7 @@ "commandType": { "title": "Commandtype", "default": "setRailLights", - "enum": [ - "setRailLights" - ], + "enum": ["setRailLights"], "type": "string" }, "params": { @@ -2824,9 +2517,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "TouchTipParams": { "title": "TouchTipParams", @@ -2869,11 +2560,7 @@ "type": "number" } }, - "required": [ - "labwareId", - "wellName", - "pipetteId" - ] + "required": ["labwareId", "wellName", "pipetteId"] }, "TouchTipCreate": { "title": "TouchTipCreate", @@ -2883,9 +2570,7 @@ "commandType": { "title": "Commandtype", "default": "touchTip", - "enum": [ - "touchTip" - ], + "enum": ["touchTip"], "type": "string" }, "params": { @@ -2905,20 +2590,12 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "StatusBarAnimation": { "title": "StatusBarAnimation", "description": "Status Bar animation options.", - "enum": [ - "idle", - "confirm", - "updating", - "disco", - "off" - ] + "enum": ["idle", "confirm", "updating", "disco", "off"] }, "SetStatusBarParams": { "title": "SetStatusBarParams", @@ -2934,9 +2611,7 @@ ] } }, - "required": [ - "animation" - ] + "required": ["animation"] }, "SetStatusBarCreate": { "title": "SetStatusBarCreate", @@ -2946,9 +2621,7 @@ "commandType": { "title": "Commandtype", "default": "setStatusBar", - "enum": [ - "setStatusBar" - ], + "enum": ["setStatusBar"], "type": "string" }, "params": { @@ -2968,18 +2641,12 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "TipPresenceStatus": { "title": "TipPresenceStatus", "description": "Tip presence status reported by a pipette.", - "enum": [ - "present", - "absent", - "unknown" - ], + "enum": ["present", "absent", "unknown"], "type": "string" }, "VerifyTipPresenceParams": { @@ -3001,10 +2668,7 @@ ] } }, - "required": [ - "pipetteId", - "expectedState" - ] + "required": ["pipetteId", "expectedState"] }, "VerifyTipPresenceCreate": { "title": "VerifyTipPresenceCreate", @@ -3014,9 +2678,7 @@ "commandType": { "title": "Commandtype", "default": "verifyTipPresence", - "enum": [ - "verifyTipPresence" - ], + "enum": ["verifyTipPresence"], "type": "string" }, "params": { @@ -3036,9 +2698,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "GetTipPresenceParams": { "title": "GetTipPresenceParams", @@ -3051,9 +2711,7 @@ "type": "string" } }, - "required": [ - "pipetteId" - ] + "required": ["pipetteId"] }, "GetTipPresenceCreate": { "title": "GetTipPresenceCreate", @@ -3063,9 +2721,7 @@ "commandType": { "title": "Commandtype", "default": "getTipPresence", - "enum": [ - "getTipPresence" - ], + "enum": ["getTipPresence"], "type": "string" }, "params": { @@ -3085,9 +2741,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureParams": { "title": "WaitForTemperatureParams", @@ -3105,9 +2759,7 @@ "type": "number" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "opentrons__protocol_engine__commands__heater_shaker__wait_for_temperature__WaitForTemperatureCreate": { "title": "WaitForTemperatureCreate", @@ -3117,9 +2769,7 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/waitForTemperature", - "enum": [ - "heaterShaker/waitForTemperature" - ], + "enum": ["heaterShaker/waitForTemperature"], "type": "string" }, "params": { @@ -3139,9 +2789,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureParams": { "title": "SetTargetTemperatureParams", @@ -3159,10 +2807,7 @@ "type": "number" } }, - "required": [ - "moduleId", - "celsius" - ] + "required": ["moduleId", "celsius"] }, "opentrons__protocol_engine__commands__heater_shaker__set_target_temperature__SetTargetTemperatureCreate": { "title": "SetTargetTemperatureCreate", @@ -3172,9 +2817,7 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/setTargetTemperature", - "enum": [ - "heaterShaker/setTargetTemperature" - ], + "enum": ["heaterShaker/setTargetTemperature"], "type": "string" }, "params": { @@ -3194,9 +2837,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DeactivateHeaterParams": { "title": "DeactivateHeaterParams", @@ -3209,9 +2850,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "DeactivateHeaterCreate": { "title": "DeactivateHeaterCreate", @@ -3221,9 +2860,7 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/deactivateHeater", - "enum": [ - "heaterShaker/deactivateHeater" - ], + "enum": ["heaterShaker/deactivateHeater"], "type": "string" }, "params": { @@ -3243,9 +2880,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "SetAndWaitForShakeSpeedParams": { "title": "SetAndWaitForShakeSpeedParams", @@ -3263,10 +2898,7 @@ "type": "number" } }, - "required": [ - "moduleId", - "rpm" - ] + "required": ["moduleId", "rpm"] }, "SetAndWaitForShakeSpeedCreate": { "title": "SetAndWaitForShakeSpeedCreate", @@ -3276,9 +2908,7 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/setAndWaitForShakeSpeed", - "enum": [ - "heaterShaker/setAndWaitForShakeSpeed" - ], + "enum": ["heaterShaker/setAndWaitForShakeSpeed"], "type": "string" }, "params": { @@ -3298,9 +2928,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DeactivateShakerParams": { "title": "DeactivateShakerParams", @@ -3313,9 +2941,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "DeactivateShakerCreate": { "title": "DeactivateShakerCreate", @@ -3325,9 +2951,7 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/deactivateShaker", - "enum": [ - "heaterShaker/deactivateShaker" - ], + "enum": ["heaterShaker/deactivateShaker"], "type": "string" }, "params": { @@ -3347,9 +2971,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "OpenLabwareLatchParams": { "title": "OpenLabwareLatchParams", @@ -3362,9 +2984,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "OpenLabwareLatchCreate": { "title": "OpenLabwareLatchCreate", @@ -3374,9 +2994,7 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/openLabwareLatch", - "enum": [ - "heaterShaker/openLabwareLatch" - ], + "enum": ["heaterShaker/openLabwareLatch"], "type": "string" }, "params": { @@ -3396,9 +3014,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "CloseLabwareLatchParams": { "title": "CloseLabwareLatchParams", @@ -3411,9 +3027,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "CloseLabwareLatchCreate": { "title": "CloseLabwareLatchCreate", @@ -3423,9 +3037,7 @@ "commandType": { "title": "Commandtype", "default": "heaterShaker/closeLabwareLatch", - "enum": [ - "heaterShaker/closeLabwareLatch" - ], + "enum": ["heaterShaker/closeLabwareLatch"], "type": "string" }, "params": { @@ -3445,9 +3057,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DisengageParams": { "title": "DisengageParams", @@ -3460,9 +3070,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "DisengageCreate": { "title": "DisengageCreate", @@ -3472,9 +3080,7 @@ "commandType": { "title": "Commandtype", "default": "magneticModule/disengage", - "enum": [ - "magneticModule/disengage" - ], + "enum": ["magneticModule/disengage"], "type": "string" }, "params": { @@ -3494,9 +3100,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "EngageParams": { "title": "EngageParams", @@ -3514,10 +3118,7 @@ "type": "number" } }, - "required": [ - "moduleId", - "height" - ] + "required": ["moduleId", "height"] }, "EngageCreate": { "title": "EngageCreate", @@ -3527,9 +3128,7 @@ "commandType": { "title": "Commandtype", "default": "magneticModule/engage", - "enum": [ - "magneticModule/engage" - ], + "enum": ["magneticModule/engage"], "type": "string" }, "params": { @@ -3549,9 +3148,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureParams": { "title": "SetTargetTemperatureParams", @@ -3569,10 +3166,7 @@ "type": "number" } }, - "required": [ - "moduleId", - "celsius" - ] + "required": ["moduleId", "celsius"] }, "opentrons__protocol_engine__commands__temperature_module__set_target_temperature__SetTargetTemperatureCreate": { "title": "SetTargetTemperatureCreate", @@ -3582,9 +3176,7 @@ "commandType": { "title": "Commandtype", "default": "temperatureModule/setTargetTemperature", - "enum": [ - "temperatureModule/setTargetTemperature" - ], + "enum": ["temperatureModule/setTargetTemperature"], "type": "string" }, "params": { @@ -3604,9 +3196,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureParams": { "title": "WaitForTemperatureParams", @@ -3624,9 +3214,7 @@ "type": "number" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "opentrons__protocol_engine__commands__temperature_module__wait_for_temperature__WaitForTemperatureCreate": { "title": "WaitForTemperatureCreate", @@ -3636,9 +3224,7 @@ "commandType": { "title": "Commandtype", "default": "temperatureModule/waitForTemperature", - "enum": [ - "temperatureModule/waitForTemperature" - ], + "enum": ["temperatureModule/waitForTemperature"], "type": "string" }, "params": { @@ -3658,9 +3244,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DeactivateTemperatureParams": { "title": "DeactivateTemperatureParams", @@ -3673,9 +3257,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "DeactivateTemperatureCreate": { "title": "DeactivateTemperatureCreate", @@ -3685,9 +3267,7 @@ "commandType": { "title": "Commandtype", "default": "temperatureModule/deactivate", - "enum": [ - "temperatureModule/deactivate" - ], + "enum": ["temperatureModule/deactivate"], "type": "string" }, "params": { @@ -3707,9 +3287,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "SetTargetBlockTemperatureParams": { "title": "SetTargetBlockTemperatureParams", @@ -3737,10 +3315,7 @@ "type": "number" } }, - "required": [ - "moduleId", - "celsius" - ] + "required": ["moduleId", "celsius"] }, "SetTargetBlockTemperatureCreate": { "title": "SetTargetBlockTemperatureCreate", @@ -3750,9 +3325,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/setTargetBlockTemperature", - "enum": [ - "thermocycler/setTargetBlockTemperature" - ], + "enum": ["thermocycler/setTargetBlockTemperature"], "type": "string" }, "params": { @@ -3772,9 +3345,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "WaitForBlockTemperatureParams": { "title": "WaitForBlockTemperatureParams", @@ -3787,9 +3358,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "WaitForBlockTemperatureCreate": { "title": "WaitForBlockTemperatureCreate", @@ -3799,9 +3368,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/waitForBlockTemperature", - "enum": [ - "thermocycler/waitForBlockTemperature" - ], + "enum": ["thermocycler/waitForBlockTemperature"], "type": "string" }, "params": { @@ -3821,9 +3388,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "SetTargetLidTemperatureParams": { "title": "SetTargetLidTemperatureParams", @@ -3841,10 +3406,7 @@ "type": "number" } }, - "required": [ - "moduleId", - "celsius" - ] + "required": ["moduleId", "celsius"] }, "SetTargetLidTemperatureCreate": { "title": "SetTargetLidTemperatureCreate", @@ -3854,9 +3416,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/setTargetLidTemperature", - "enum": [ - "thermocycler/setTargetLidTemperature" - ], + "enum": ["thermocycler/setTargetLidTemperature"], "type": "string" }, "params": { @@ -3876,9 +3436,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "WaitForLidTemperatureParams": { "title": "WaitForLidTemperatureParams", @@ -3891,9 +3449,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "WaitForLidTemperatureCreate": { "title": "WaitForLidTemperatureCreate", @@ -3903,9 +3459,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/waitForLidTemperature", - "enum": [ - "thermocycler/waitForLidTemperature" - ], + "enum": ["thermocycler/waitForLidTemperature"], "type": "string" }, "params": { @@ -3925,9 +3479,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DeactivateBlockParams": { "title": "DeactivateBlockParams", @@ -3940,9 +3492,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "DeactivateBlockCreate": { "title": "DeactivateBlockCreate", @@ -3952,9 +3502,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/deactivateBlock", - "enum": [ - "thermocycler/deactivateBlock" - ], + "enum": ["thermocycler/deactivateBlock"], "type": "string" }, "params": { @@ -3974,9 +3522,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "DeactivateLidParams": { "title": "DeactivateLidParams", @@ -3989,9 +3535,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "DeactivateLidCreate": { "title": "DeactivateLidCreate", @@ -4001,9 +3545,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/deactivateLid", - "enum": [ - "thermocycler/deactivateLid" - ], + "enum": ["thermocycler/deactivateLid"], "type": "string" }, "params": { @@ -4023,9 +3565,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "OpenLidParams": { "title": "OpenLidParams", @@ -4038,9 +3578,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "OpenLidCreate": { "title": "OpenLidCreate", @@ -4050,9 +3588,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/openLid", - "enum": [ - "thermocycler/openLid" - ], + "enum": ["thermocycler/openLid"], "type": "string" }, "params": { @@ -4072,9 +3608,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "CloseLidParams": { "title": "CloseLidParams", @@ -4087,9 +3621,7 @@ "type": "string" } }, - "required": [ - "moduleId" - ] + "required": ["moduleId"] }, "CloseLidCreate": { "title": "CloseLidCreate", @@ -4099,9 +3631,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/closeLid", - "enum": [ - "thermocycler/closeLid" - ], + "enum": ["thermocycler/closeLid"], "type": "string" }, "params": { @@ -4121,9 +3651,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "RunProfileStepParams": { "title": "RunProfileStepParams", @@ -4141,10 +3669,7 @@ "type": "number" } }, - "required": [ - "celsius", - "holdSeconds" - ] + "required": ["celsius", "holdSeconds"] }, "RunProfileParams": { "title": "RunProfileParams", @@ -4170,10 +3695,7 @@ "type": "number" } }, - "required": [ - "moduleId", - "profile" - ] + "required": ["moduleId", "profile"] }, "RunProfileCreate": { "title": "RunProfileCreate", @@ -4183,9 +3705,7 @@ "commandType": { "title": "Commandtype", "default": "thermocycler/runProfile", - "enum": [ - "thermocycler/runProfile" - ], + "enum": ["thermocycler/runProfile"], "type": "string" }, "params": { @@ -4205,17 +3725,12 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "CalibrateGripperParamsJaw": { "title": "CalibrateGripperParamsJaw", "description": "An enumeration.", - "enum": [ - "front", - "rear" - ] + "enum": ["front", "rear"] }, "Vec3f": { "title": "Vec3f", @@ -4235,11 +3750,7 @@ "type": "number" } }, - "required": [ - "x", - "y", - "z" - ] + "required": ["x", "y", "z"] }, "CalibrateGripperParams": { "title": "CalibrateGripperParams", @@ -4264,9 +3775,7 @@ ] } }, - "required": [ - "jaw" - ] + "required": ["jaw"] }, "CalibrateGripperCreate": { "title": "CalibrateGripperCreate", @@ -4276,9 +3785,7 @@ "commandType": { "title": "Commandtype", "default": "calibration/calibrateGripper", - "enum": [ - "calibration/calibrateGripper" - ], + "enum": ["calibration/calibrateGripper"], "type": "string" }, "params": { @@ -4298,9 +3805,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "CalibratePipetteParams": { "title": "CalibratePipetteParams", @@ -4316,9 +3821,7 @@ ] } }, - "required": [ - "mount" - ] + "required": ["mount"] }, "CalibratePipetteCreate": { "title": "CalibratePipetteCreate", @@ -4328,9 +3831,7 @@ "commandType": { "title": "Commandtype", "default": "calibration/calibratePipette", - "enum": [ - "calibration/calibratePipette" - ], + "enum": ["calibration/calibratePipette"], "type": "string" }, "params": { @@ -4350,9 +3851,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "CalibrateModuleParams": { "title": "CalibrateModuleParams", @@ -4378,11 +3877,7 @@ ] } }, - "required": [ - "moduleId", - "labwareId", - "mount" - ] + "required": ["moduleId", "labwareId", "mount"] }, "CalibrateModuleCreate": { "title": "CalibrateModuleCreate", @@ -4392,9 +3887,7 @@ "commandType": { "title": "Commandtype", "default": "calibration/calibrateModule", - "enum": [ - "calibration/calibrateModule" - ], + "enum": ["calibration/calibrateModule"], "type": "string" }, "params": { @@ -4414,17 +3907,12 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] }, "MaintenancePosition": { "title": "MaintenancePosition", "description": "Maintenance position options.", - "enum": [ - "attachPlate", - "attachInstrument" - ] + "enum": ["attachPlate", "attachInstrument"] }, "MoveToMaintenancePositionParams": { "title": "MoveToMaintenancePositionParams", @@ -4449,9 +3937,7 @@ ] } }, - "required": [ - "mount" - ] + "required": ["mount"] }, "MoveToMaintenancePositionCreate": { "title": "MoveToMaintenancePositionCreate", @@ -4461,9 +3947,7 @@ "commandType": { "title": "Commandtype", "default": "calibration/moveToMaintenancePosition", - "enum": [ - "calibration/moveToMaintenancePosition" - ], + "enum": ["calibration/moveToMaintenancePosition"], "type": "string" }, "params": { @@ -4483,9 +3967,7 @@ "type": "string" } }, - "required": [ - "params" - ] + "required": ["params"] } }, "$id": "opentronsCommandSchemaV8", From 28a2d165212154a9111570a99f3857dcddc96282 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Wed, 24 Apr 2024 11:58:02 -0400 Subject: [PATCH 06/10] refactor: remove all args but id --- .../protocol_engine/clients/sync_client.py | 8 - .../commands/reload_labware.py | 44 ----- .../protocol_engine/execution/equipment.py | 31 +-- .../protocol_engine/state/labware.py | 7 +- .../opentrons/protocol_engine/state/tips.py | 41 +--- .../clients/test_sync_client.py | 11 +- .../commands/test_reload_labware.py | 57 +----- .../protocol_engine/state/command_fixtures.py | 7 - .../state/test_labware_store.py | 25 +-- .../protocol_engine/state/test_tip_state.py | 186 +----------------- shared-data/command/schemas/8.json | 22 +-- 11 files changed, 35 insertions(+), 404 deletions(-) diff --git a/api/src/opentrons/protocol_engine/clients/sync_client.py b/api/src/opentrons/protocol_engine/clients/sync_client.py index c553b737ec0..2277ce815a4 100644 --- a/api/src/opentrons/protocol_engine/clients/sync_client.py +++ b/api/src/opentrons/protocol_engine/clients/sync_client.py @@ -130,19 +130,11 @@ def load_labware( def reload_labware( self, labware_id: str, - load_name: str, - namespace: str, - version: int, - display_name: Optional[str] = None, ) -> commands.ReloadLabwareResult: """Execute a ReloadLabware command and return the result.""" request = commands.ReloadLabwareCreate( params=commands.ReloadLabwareParams( labwareId=labware_id, - loadName=load_name, - namespace=namespace, - version=version, - displayName=display_name, ) ) result = self._transport.execute_command(request=request) diff --git a/api/src/opentrons/protocol_engine/commands/reload_labware.py b/api/src/opentrons/protocol_engine/commands/reload_labware.py index 132ef9b3bef..5cabe9bb855 100644 --- a/api/src/opentrons/protocol_engine/commands/reload_labware.py +++ b/api/src/opentrons/protocol_engine/commands/reload_labware.py @@ -29,23 +29,6 @@ class ReloadLabwareParams(BaseModel): labwareId: str = Field( ..., description="The already-loaded labware instance to update." ) - loadName: str = Field( - ..., - description="Name used to reference a labware definition.", - ) - namespace: str = Field( - ..., - description="The namespace the labware definition belongs to.", - ) - version: int = Field( - ..., - description="The labware definition version.", - ) - displayName: Optional[str] = Field( - None, - description="An optional user-specified display name " - "or label for this labware.", - ) class ReloadLabwareResult(BaseModel): @@ -55,10 +38,6 @@ class ReloadLabwareResult(BaseModel): ..., description="An ID to reference this labware in subsequent commands. Same as the one in the parameters.", ) - definition: LabwareDefinition = Field( - ..., - description="The full definition data for this labware.", - ) offsetId: Optional[str] = Field( # Default `None` instead of `...` so this field shows up as non-required in # OpenAPI. The server is allowed to omit it or make it null. @@ -89,33 +68,10 @@ async def execute(self, params: ReloadLabwareParams) -> ReloadLabwareResult: """Reload the definition and calibration data for a specific labware.""" reloaded_labware = await self._equipment.reload_labware( labware_id=params.labwareId, - load_name=params.loadName, - namespace=params.namespace, - version=params.version, ) - # note: this check must be kept because somebody might specify the trash loadName - if ( - labware_validation.is_flex_trash(params.loadName) - and isinstance(reloaded_labware.location, DeckSlotLocation) - and self._state_view.geometry.get_slot_column( - reloaded_labware.location.slotName - ) - != 3 - ): - raise LabwareIsNotAllowedInLocationError( - f"{params.loadName} is not allowed in slot {reloaded_labware.location.slotName}" - ) - - if isinstance(reloaded_labware.location, OnLabwareLocation): - self._state_view.labware.raise_if_labware_cannot_be_stacked( - top_labware_definition=reloaded_labware.definition, - bottom_labware_id=reloaded_labware.location.labwareId, - ) - return ReloadLabwareResult( labwareId=params.labwareId, - definition=reloaded_labware.definition, offsetId=reloaded_labware.offsetId, ) diff --git a/api/src/opentrons/protocol_engine/execution/equipment.py b/api/src/opentrons/protocol_engine/execution/equipment.py index 12eb3df6787..711e95a3f59 100644 --- a/api/src/opentrons/protocol_engine/execution/equipment.py +++ b/api/src/opentrons/protocol_engine/execution/equipment.py @@ -60,7 +60,6 @@ class LoadedLabwareData: class ReloadedLabwareData: """The result of a reload labware procedure.""" - definition: LabwareDefinition location: LabwareLocation offsetId: Optional[str] @@ -180,47 +179,25 @@ async def load_labware( labware_id=labware_id, definition=definition, offsetId=offset_id ) - async def reload_labware( - self, labware_id: str, load_name: str, namespace: str, version: int - ) -> ReloadedLabwareData: + async def reload_labware(self, labware_id: str) -> ReloadedLabwareData: """Reload an already-loaded labware. This cannot change the labware location. Args: labware_id: The ID of the already-loaded labware. - load_name: The labware's load name. - namespace: The labware's namespace. - version: The labware's version. Raises: LabwareNotLoadedError: If `labware_id` does not reference a loaded labware. """ - definition_uri = uri_from_details( - load_name=load_name, - namespace=namespace, - version=version, - ) - location = self._state_store.labware.get_location(labware_id) - try: - # Try to use existing definition in state. - definition = self._state_store.labware.get_definition_by_uri(definition_uri) - except LabwareDefinitionDoesNotExistError: - definition = await self._labware_data_provider.get_labware_definition( - load_name=load_name, - namespace=namespace, - version=version, - ) - - # Allow propagation of ModuleNotLoadedError. + location = self._state_store.labware.get_location(labware_id) + definition_uri = self._state_store.labware.get_definition_uri(labware_id) offset_id = self.find_applicable_labware_offset_id( labware_definition_uri=definition_uri, labware_location=location, ) - return ReloadedLabwareData( - definition=definition, location=location, offsetId=offset_id - ) + return ReloadedLabwareData(location=location, offsetId=offset_id) async def load_pipette( self, diff --git a/api/src/opentrons/protocol_engine/state/labware.py b/api/src/opentrons/protocol_engine/state/labware.py index 743c582678b..e9750a652b4 100644 --- a/api/src/opentrons/protocol_engine/state/labware.py +++ b/api/src/opentrons/protocol_engine/state/labware.py @@ -176,7 +176,7 @@ def handle_action(self, action: Action) -> None: def _handle_command(self, command: Command) -> None: """Modify state in reaction to a command.""" - if isinstance(command.result, (LoadLabwareResult, ReloadLabwareResult)): + if isinstance(command.result, LoadLabwareResult): # If the labware load refers to an offset, that offset must actually exist. if command.result.offsetId is not None: assert command.result.offsetId in self._state.labware_offsets_by_id @@ -204,6 +204,11 @@ def _handle_command(self, command: Command) -> None: displayName=command.params.displayName, ) + elif isinstance(command.result, ReloadLabwareResult): + labware_id = command.params.labwareId + new_offset_id = command.result.offsetId + self._state.labware_by_id[labware_id].offsetId = new_offset_id + elif isinstance(command.result, MoveLabwareResult): labware_id = command.params.labwareId new_location = command.params.newLocation diff --git a/api/src/opentrons/protocol_engine/state/tips.py b/api/src/opentrons/protocol_engine/state/tips.py index 96e7bafe327..f5d68d61ee5 100644 --- a/api/src/opentrons/protocol_engine/state/tips.py +++ b/api/src/opentrons/protocol_engine/state/tips.py @@ -3,10 +3,6 @@ from enum import Enum from typing import Dict, Optional, List, Union -from opentrons_shared_data.labware.labware_definition import LabwareDefinition - -from opentrons.hardware_control.nozzle_manager import NozzleMap - from .abstract_store import HasState, HandlesActions from ..actions import ( Action, @@ -17,7 +13,6 @@ from ..commands import ( Command, LoadLabwareResult, - ReloadLabwareResult, PickUpTip, PickUpTipResult, DropTipResult, @@ -29,6 +24,8 @@ ) from ..error_recovery_policy import ErrorRecoveryType +from opentrons.hardware_control.nozzle_manager import NozzleMap + class TipRackWellState(Enum): """The state of a single tip in a tip rack's well.""" @@ -103,16 +100,6 @@ def handle_action(self, action: Action) -> None: well_name ] = TipRackWellState.CLEAN - def _add_new_tiprack(self, labware_id: str, definition: LabwareDefinition) -> None: - self._state.tips_by_labware_id[labware_id] = { - well_name: TipRackWellState.CLEAN - for column in definition.ordering - for well_name in column - } - self._state.column_by_labware_id[labware_id] = [ - column for column in definition.ordering - ] - def _handle_succeeded_command(self, command: Command) -> None: if ( isinstance(command.result, LoadLabwareResult) @@ -120,7 +107,14 @@ def _handle_succeeded_command(self, command: Command) -> None: ): labware_id = command.result.labwareId definition = command.result.definition - self._add_new_tiprack(labware_id, definition) + self._state.tips_by_labware_id[labware_id] = { + well_name: TipRackWellState.CLEAN + for column in definition.ordering + for well_name in column + } + self._state.column_by_labware_id[labware_id] = [ + column for column in definition.ordering + ] elif isinstance(command.result, PickUpTipResult): labware_id = command.params.labwareId @@ -136,21 +130,6 @@ def _handle_succeeded_command(self, command: Command) -> None: pipette_id = command.params.pipetteId self._state.length_by_pipette_id.pop(pipette_id, None) - elif isinstance(command.result, ReloadLabwareResult): - if ( - command.result.definition.parameters.isTiprack - and command.result.labwareId not in self._state.tips_by_labware_id - ): - self._add_new_tiprack( - command.result.labwareId, command.result.definition - ) - elif ( - not command.result.definition.parameters.isTiprack - and command.result.labwareId in self._state.tips_by_labware_id - ): - self._state.tips_by_labware_id.pop(command.result.labwareId) - self._state.column_by_labware_id.pop(command.result.labwareId) - def _handle_failed_command( self, action: FailCommandAction, diff --git a/api/tests/opentrons/protocol_engine/clients/test_sync_client.py b/api/tests/opentrons/protocol_engine/clients/test_sync_client.py index c1e7be8f4bf..e4f5d7602ca 100644 --- a/api/tests/opentrons/protocol_engine/clients/test_sync_client.py +++ b/api/tests/opentrons/protocol_engine/clients/test_sync_client.py @@ -164,32 +164,23 @@ def test_load_labware( def test_reload_labware( decoy: Decoy, transport: ChildThreadTransport, - tip_rack_def: LabwareDefinition, subject: SyncClient, ) -> None: """It should execute a reload labware command.""" expected_request = commands.ReloadLabwareCreate( params=commands.ReloadLabwareParams( labwareId="some-labware-id", - loadName="some_labware", - namespace="opentrons", - version=1, - displayName="some_display_name", ) ) expected_result = commands.ReloadLabwareResult( - labwareId="some-labware-id", definition=tip_rack_def, offsetId=None + labwareId="some-labware-id", offsetId=None ) decoy.when(transport.execute_command(request=expected_request)).then_return( expected_result ) result = subject.reload_labware( labware_id="some-labware-id", - namespace="opentrons", - load_name="some_labware", - version=1, - display_name="some_display_name", ) assert result == expected_result diff --git a/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py b/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py index 73d751a6609..29057d88ebb 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py +++ b/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py @@ -46,23 +46,11 @@ async def test_reload_labware_implementation( data = ReloadLabwareParams( labwareId="my-labware-id", - loadName="some-load-name", - namespace="opentrons-test", - version=1, - displayName="My custom display name", ) - decoy.when( - await equipment.reload_labware( - labware_id="my-labware-id", - load_name="some-load-name", - namespace="opentrons-test", - version=1, - ) - ).then_return( + decoy.when(await equipment.reload_labware(labware_id="my-labware-id",)).then_return( ReloadedLabwareData( location=DeckSlotLocation(slotName=DeckSlotName.SLOT_4), - definition=well_plate_def, offsetId="labware-offset-id", ) ) @@ -71,7 +59,6 @@ async def test_reload_labware_implementation( assert result == ReloadLabwareResult( labwareId="my-labware-id", - definition=well_plate_def, offsetId="labware-offset-id", ) @@ -87,55 +74,13 @@ async def test_reload_labware_raises_labware_does_not_exist( data = ReloadLabwareParams( labwareId="my-labware-id", - loadName="some-load-name", - namespace="opentrons-test", - version=1, - displayName="My custom display name", ) decoy.when( await equipment.reload_labware( labware_id="my-labware-id", - load_name="some-load-name", - namespace="opentrons-test", - version=1, ) ).then_raise(LabwareNotLoadedError("What labware is this!")) with pytest.raises(LabwareNotLoadedError): await subject.execute(data) - - -async def test_load_labware_raises_location_not_allowed( - decoy: Decoy, - equipment: EquipmentHandler, - state_view: StateView, - well_plate_def: LabwareDefinition, -) -> None: - """A ReloadLabware command should raise if the flex trash definition is not in a valid slot.""" - subject = ReloadLabwareImplementation(equipment=equipment, state_view=state_view) - decoy.when(labware_validation.is_flex_trash("some-load-name")).then_return(True) - decoy.when( - await equipment.reload_labware( - labware_id="my-labware-id", - load_name="some-load-name", - namespace="opentrons-test", - version=1, - ) - ).then_return( - ReloadedLabwareData( - location=DeckSlotLocation(slotName=DeckSlotName.SLOT_A3), - definition=well_plate_def, - offsetId="labware-offset-id", - ) - ) - data = ReloadLabwareParams( - labwareId="my-labware-id", - loadName="some-load-name", - namespace="opentrons-test", - version=1, - displayName="My custom display name", - ) - - with pytest.raises(LabwareIsNotAllowedInLocationError): - await subject.execute(data) diff --git a/api/tests/opentrons/protocol_engine/state/command_fixtures.py b/api/tests/opentrons/protocol_engine/state/command_fixtures.py index aeab8eb621b..82d5c801611 100644 --- a/api/tests/opentrons/protocol_engine/state/command_fixtures.py +++ b/api/tests/opentrons/protocol_engine/state/command_fixtures.py @@ -581,22 +581,15 @@ def create_prepare_to_aspirate_command(pipette_id: str) -> cmd.PrepareToAspirate def create_reload_labware_command( labware_id: str, - definition: LabwareDefinition, offset_id: Optional[str], - display_name: Optional[str], ) -> cmd.ReloadLabware: """Create a completed ReloadLabware command.""" params = cmd.ReloadLabwareParams( - loadName=definition.parameters.loadName, - namespace=definition.namespace, - version=definition.version, labwareId=labware_id, - displayName=display_name, ) result = cmd.ReloadLabwareResult( labwareId=labware_id, - definition=definition, offsetId=offset_id, ) diff --git a/api/tests/opentrons/protocol_engine/state/test_labware_store.py b/api/tests/opentrons/protocol_engine/state/test_labware_store.py index 77de86b4a65..960ce423194 100644 --- a/api/tests/opentrons/protocol_engine/state/test_labware_store.py +++ b/api/tests/opentrons/protocol_engine/state/test_labware_store.py @@ -136,7 +136,6 @@ def test_handles_load_labware( def test_handles_reload_labware( subject: LabwareStore, well_plate_def: LabwareDefinition, - flex_50uL_tiprack: LabwareDefinition, ) -> None: """It should override labware data in the state.""" load_labware = create_load_labware_command( @@ -150,13 +149,15 @@ def test_handles_reload_labware( subject.handle_action( SucceedCommandAction(private_result=None, command=load_labware) ) - assert subject.state.labware_by_id[ - "test-labware-id" - ].definitionUri == uri_from_details( + expected_definition_uri = uri_from_details( load_name=well_plate_def.parameters.loadName, namespace=well_plate_def.namespace, version=well_plate_def.version, ) + assert ( + subject.state.labware_by_id["test-labware-id"].definitionUri + == expected_definition_uri + ) offset_request = LabwareOffsetCreate( definitionUri="offset-definition-uri", @@ -172,32 +173,22 @@ def test_handles_reload_labware( ) reload_labware = create_reload_labware_command( labware_id="test-labware-id", - definition=flex_50uL_tiprack, offset_id="offset-id", - display_name="display-name-2", ) subject.handle_action( SucceedCommandAction(private_result=None, command=reload_labware) ) - expected_definition_uri = uri_from_details( - load_name=flex_50uL_tiprack.parameters.loadName, - namespace=flex_50uL_tiprack.namespace, - version=flex_50uL_tiprack.version, - ) - expected_labware_data = LoadedLabware( id="test-labware-id", - loadName=flex_50uL_tiprack.parameters.loadName, + loadName=well_plate_def.parameters.loadName, definitionUri=expected_definition_uri, location=DeckSlotLocation(slotName=DeckSlotName.SLOT_A1), offsetId="offset-id", - displayName="display-name-2", + displayName="display-name", ) assert subject.state.labware_by_id["test-labware-id"] == expected_labware_data - assert ( - subject.state.definitions_by_uri[expected_definition_uri] == flex_50uL_tiprack - ) + assert subject.state.definitions_by_uri[expected_definition_uri] == well_plate_def def test_handles_add_labware_definition( diff --git a/api/tests/opentrons/protocol_engine/state/test_tip_state.py b/api/tests/opentrons/protocol_engine/state/test_tip_state.py index 2af4a486319..25894554027 100644 --- a/api/tests/opentrons/protocol_engine/state/test_tip_state.py +++ b/api/tests/opentrons/protocol_engine/state/test_tip_state.py @@ -36,9 +36,9 @@ def subject() -> TipStore: return TipStore() -def _default_labware_def( - parameters: Optional[LabwareParameters] = None, -) -> LabwareDefinition: +@pytest.fixture +def labware_definition() -> LabwareDefinition: + """Get a labware definition value object.""" return LabwareDefinition.construct( # type: ignore[call-arg] ordering=[ ["A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1"], @@ -54,22 +54,10 @@ def _default_labware_def( ["A11", "B11", "C11", "D11", "E11", "F11", "G11", "H11"], ["A12", "B12", "C12", "D12", "E12", "F12", "G12", "H12"], ], - parameters=parameters or _tip_rack_parameters, + parameters=_tip_rack_parameters, ) -@pytest.fixture -def labware_definition() -> LabwareDefinition: - """Get a labware definition value object.""" - return _default_labware_def() - - -@pytest.fixture -def reload_labware_definition() -> LabwareDefinition: - """Get a labware definition for reloading.""" - return _default_labware_def() - - @pytest.fixture def load_labware_command(labware_definition: LabwareDefinition) -> commands.LoadLabware: """Get a load labware command value object.""" @@ -81,18 +69,6 @@ def load_labware_command(labware_definition: LabwareDefinition) -> commands.Load ) -@pytest.fixture -def reload_labware_command( - reload_labware_definition: LabwareDefinition, -) -> commands.ReloadLabware: - """Get a reload labware command.""" - return commands.ReloadLabware.construct( # type: ignore[call-arg] - result=commands.ReloadLabwareResult.construct( - labwareId="cool-labware", definition=reload_labware_definition - ) - ) - - @pytest.fixture def pick_up_tip_command() -> commands.PickUpTip: """Get a pick-up tip command value object.""" @@ -1159,157 +1135,3 @@ def _reconfigure_nozzle_layout(start: str, back_l: str, front_r: str) -> NozzleM _assert_and_pickup("B1", map) map = _reconfigure_nozzle_layout("A1", "A1", "A1") _assert_and_pickup("B2", map) - - -def test_reload_tiprack_does_not_alter_tip_state( - subject: TipStore, - load_labware_command: commands.LoadLabware, - pick_up_tip_command: commands.PickUpTip, - reload_labware_command: commands.ReloadLabware, - supported_tip_fixture: pipette_definition.SupportedTipsDefinition, -) -> None: - """Reloading a tiprack is not the same as resetting the tips.""" - subject.handle_action( - actions.SucceedCommandAction(private_result=None, command=load_labware_command) - ) - load_pipette_command = commands.LoadPipette.construct( # type: ignore[call-arg] - result=commands.LoadPipetteResult(pipetteId="pipette-id") - ) - load_pipette_private_result = commands.LoadPipettePrivateResult( - pipette_id="pipette-id", - serial_number="pipette-serial", - config=LoadedStaticPipetteData( - channels=1, - max_volume=15, - min_volume=3, - model="gen a", - display_name="display name", - flow_rates=FlowRates( - default_aspirate={}, - default_dispense={}, - default_blow_out={}, - ), - tip_configuration_lookup_table={15: supported_tip_fixture}, - nominal_tip_overlap={}, - nozzle_offset_z=1.23, - home_position=4.56, - nozzle_map=get_default_nozzle_map(PipetteNameType.P300_SINGLE_GEN2), - back_left_corner_offset=Point(x=1, y=2, z=3), - front_right_corner_offset=Point(x=4, y=5, z=6), - ), - ) - - subject.handle_action( - actions.SucceedCommandAction( - private_result=load_pipette_private_result, command=load_pipette_command - ) - ) - - subject.handle_action( - actions.SucceedCommandAction(private_result=None, command=pick_up_tip_command) - ) - subject.handle_action( - actions.SucceedCommandAction( - private_result=None, command=reload_labware_command - ) - ) - result = TipView(subject.state).get_next_tip( - labware_id="cool-labware", - num_tips=1, - starting_tip_name=None, - nozzle_map=None, - ) - - assert result == "B1" - - -@pytest.mark.parametrize( - "labware_definition", - [ - _default_labware_def( - parameters=LabwareParameters.construct(isTiprack=False) # type: ignore[call-arg] - ) - ], -) -def test_reload_to_tiprack_loads( - subject: TipStore, - load_labware_command: commands.LoadLabware, - reload_labware_command: commands.ReloadLabware, -) -> None: - """If you have a loaded non-tiprack and reload with a tiprack, state should appear.""" - subject.handle_action( - actions.SucceedCommandAction(private_result=None, command=load_labware_command) - ) - assert load_labware_command.result - assert ( - TipView(subject.state).get_next_tip( - labware_id=load_labware_command.result.labwareId, - num_tips=1, - starting_tip_name=None, - nozzle_map=None, - ) - is None - ) - - subject.handle_action( - actions.SucceedCommandAction( - private_result=None, command=reload_labware_command - ) - ) - result = TipView(subject.state).get_next_tip( - labware_id="cool-labware", - num_tips=1, - starting_tip_name=None, - nozzle_map=None, - ) - - assert result == "A1" - - -@pytest.mark.parametrize( - "reload_labware_definition", - [ - _default_labware_def( - parameters=LabwareParameters.construct(isTiprack=False) # type: ignore[call-arg] - ) - ], -) -def test_reload_to_non_tiprack_unloads( - subject: TipStore, - load_labware_command: commands.LoadLabware, - reload_labware_command: commands.ReloadLabware, -) -> None: - """If you have a loaded tiprack and reload with a non-tiprack def, state should go away.""" - subject.handle_action( - actions.SucceedCommandAction(private_result=None, command=load_labware_command) - ) - result = TipView(subject.state).get_next_tip( - labware_id="cool-labware", - num_tips=1, - starting_tip_name=None, - nozzle_map=None, - ) - assert result == "A1" - - subject.handle_action( - actions.SucceedCommandAction( - private_result=None, command=reload_labware_command - ) - ) - result = TipView(subject.state).get_next_tip( - labware_id="cool-labware", - num_tips=1, - starting_tip_name=None, - nozzle_map=None, - ) - assert load_labware_command.result - - assert ( - TipView(subject.state).get_next_tip( - labware_id=load_labware_command.result.labwareId, - num_tips=1, - starting_tip_name=None, - nozzle_map=None, - ) - is None - ) diff --git a/shared-data/command/schemas/8.json b/shared-data/command/schemas/8.json index d481179157d..8699cc998f9 100644 --- a/shared-data/command/schemas/8.json +++ b/shared-data/command/schemas/8.json @@ -1420,29 +1420,9 @@ "title": "Labwareid", "description": "The already-loaded labware instance to update.", "type": "string" - }, - "loadName": { - "title": "Loadname", - "description": "Name used to reference a labware definition.", - "type": "string" - }, - "namespace": { - "title": "Namespace", - "description": "The namespace the labware definition belongs to.", - "type": "string" - }, - "version": { - "title": "Version", - "description": "The labware definition version.", - "type": "integer" - }, - "displayName": { - "title": "Displayname", - "description": "An optional user-specified display name or label for this labware.", - "type": "string" } }, - "required": ["labwareId", "loadName", "namespace", "version"] + "required": ["labwareId"] }, "ReloadLabwareCreate": { "title": "ReloadLabwareCreate", From b5b1738e32047024abe3aed5a71b1e9f907a7512 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Wed, 24 Apr 2024 16:19:42 -0400 Subject: [PATCH 07/10] feel just like james hetfield --- .../opentrons/protocol_engine/commands/reload_labware.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/opentrons/protocol_engine/commands/reload_labware.py b/api/src/opentrons/protocol_engine/commands/reload_labware.py index 5cabe9bb855..dafd4640c71 100644 --- a/api/src/opentrons/protocol_engine/commands/reload_labware.py +++ b/api/src/opentrons/protocol_engine/commands/reload_labware.py @@ -56,7 +56,7 @@ class ReloadLabwareResult(BaseModel): class ReloadLabwareImplementation( AbstractCommandImpl[ReloadLabwareParams, ReloadLabwareResult] ): - """Load labware command implementation.""" + """Reload labware command implementation.""" def __init__( self, equipment: EquipmentHandler, state_view: StateView, **kwargs: object @@ -77,7 +77,7 @@ async def execute(self, params: ReloadLabwareParams) -> ReloadLabwareResult: class ReloadLabware(BaseCommand[ReloadLabwareParams, ReloadLabwareResult]): - """Load labware command resource model.""" + """Reload labware command resource model.""" commandType: ReloadLabwareCommandType = "reloadLabware" params: ReloadLabwareParams @@ -87,7 +87,7 @@ class ReloadLabware(BaseCommand[ReloadLabwareParams, ReloadLabwareResult]): class ReloadLabwareCreate(BaseCommandCreate[ReloadLabwareParams]): - """Load labware command creation request.""" + """Reload labware command creation request.""" commandType: ReloadLabwareCommandType = "reloadLabware" params: ReloadLabwareParams From b960b2ba7cf9b71067147ba1abfb2830ee6437dc Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Wed, 24 Apr 2024 16:21:01 -0400 Subject: [PATCH 08/10] lint --- .../opentrons/protocol_engine/commands/reload_labware.py | 9 --------- api/src/opentrons/protocol_engine/execution/equipment.py | 1 - 2 files changed, 10 deletions(-) diff --git a/api/src/opentrons/protocol_engine/commands/reload_labware.py b/api/src/opentrons/protocol_engine/commands/reload_labware.py index dafd4640c71..247f717feb9 100644 --- a/api/src/opentrons/protocol_engine/commands/reload_labware.py +++ b/api/src/opentrons/protocol_engine/commands/reload_labware.py @@ -4,15 +4,6 @@ from typing import TYPE_CHECKING, Optional, Type from typing_extensions import Literal -from opentrons_shared_data.labware.labware_definition import LabwareDefinition -from ..resources import labware_validation - -from ..errors import LabwareIsNotAllowedInLocationError -from ..types import ( - OnLabwareLocation, - DeckSlotLocation, -) - from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate if TYPE_CHECKING: diff --git a/api/src/opentrons/protocol_engine/execution/equipment.py b/api/src/opentrons/protocol_engine/execution/equipment.py index 711e95a3f59..7dc2f3bcfaa 100644 --- a/api/src/opentrons/protocol_engine/execution/equipment.py +++ b/api/src/opentrons/protocol_engine/execution/equipment.py @@ -189,7 +189,6 @@ async def reload_labware(self, labware_id: str) -> ReloadedLabwareData: LabwareNotLoadedError: If `labware_id` does not reference a loaded labware. """ - location = self._state_store.labware.get_location(labware_id) definition_uri = self._state_store.labware.get_definition_uri(labware_id) offset_id = self.find_applicable_labware_offset_id( From b6a13c21bae35fa0bc760d0f6fd1d6ed416e510c Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Wed, 24 Apr 2024 16:26:42 -0400 Subject: [PATCH 09/10] this one too --- .../opentrons/protocol_engine/commands/test_reload_labware.py | 1 - 1 file changed, 1 deletion(-) diff --git a/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py b/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py index 29057d88ebb..556d4975786 100644 --- a/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py +++ b/api/tests/opentrons/protocol_engine/commands/test_reload_labware.py @@ -8,7 +8,6 @@ from opentrons.protocols.models import LabwareDefinition from opentrons.protocol_engine.errors import ( - LabwareIsNotAllowedInLocationError, LabwareNotLoadedError, ) From 17c0f94719e4eaf4830848f36221812568a7fb61 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Wed, 24 Apr 2024 16:53:03 -0400 Subject: [PATCH 10/10] comment captured in schema --- shared-data/command/schemas/8.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-data/command/schemas/8.json b/shared-data/command/schemas/8.json index 8699cc998f9..3d25fab2e03 100644 --- a/shared-data/command/schemas/8.json +++ b/shared-data/command/schemas/8.json @@ -1426,7 +1426,7 @@ }, "ReloadLabwareCreate": { "title": "ReloadLabwareCreate", - "description": "Load labware command creation request.", + "description": "Reload labware command creation request.", "type": "object", "properties": { "commandType": {