opentrons 8.2.0a4__py2.py3-none-any.whl → 8.3.0a1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opentrons/calibration_storage/deck_configuration.py +3 -3
- opentrons/calibration_storage/file_operators.py +3 -3
- opentrons/calibration_storage/helpers.py +3 -1
- opentrons/calibration_storage/ot2/models/v1.py +16 -29
- opentrons/calibration_storage/ot2/tip_length.py +7 -4
- opentrons/calibration_storage/ot3/models/v1.py +14 -23
- opentrons/cli/analyze.py +18 -6
- opentrons/config/defaults_ot3.py +1 -0
- opentrons/drivers/asyncio/communication/__init__.py +2 -0
- opentrons/drivers/asyncio/communication/errors.py +16 -3
- opentrons/drivers/asyncio/communication/serial_connection.py +24 -9
- opentrons/drivers/command_builder.py +2 -2
- opentrons/drivers/flex_stacker/__init__.py +9 -0
- opentrons/drivers/flex_stacker/abstract.py +89 -0
- opentrons/drivers/flex_stacker/driver.py +260 -0
- opentrons/drivers/flex_stacker/simulator.py +109 -0
- opentrons/drivers/flex_stacker/types.py +138 -0
- opentrons/drivers/heater_shaker/driver.py +18 -3
- opentrons/drivers/temp_deck/driver.py +13 -3
- opentrons/drivers/thermocycler/driver.py +17 -3
- opentrons/execute.py +3 -1
- opentrons/hardware_control/__init__.py +1 -2
- opentrons/hardware_control/api.py +28 -20
- opentrons/hardware_control/backends/flex_protocol.py +17 -7
- opentrons/hardware_control/backends/ot3controller.py +213 -63
- opentrons/hardware_control/backends/ot3simulator.py +18 -9
- opentrons/hardware_control/backends/ot3utils.py +43 -15
- opentrons/hardware_control/dev_types.py +4 -0
- opentrons/hardware_control/emulation/heater_shaker.py +4 -0
- opentrons/hardware_control/emulation/module_server/client.py +1 -1
- opentrons/hardware_control/emulation/module_server/server.py +5 -3
- opentrons/hardware_control/emulation/settings.py +3 -4
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +2 -1
- opentrons/hardware_control/instruments/ot2/pipette.py +15 -22
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +8 -1
- opentrons/hardware_control/instruments/ot3/gripper.py +2 -2
- opentrons/hardware_control/instruments/ot3/pipette.py +23 -22
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -1
- opentrons/hardware_control/modules/mod_abc.py +2 -2
- opentrons/hardware_control/motion_utilities.py +68 -0
- opentrons/hardware_control/nozzle_manager.py +39 -41
- opentrons/hardware_control/ot3_calibration.py +1 -1
- opentrons/hardware_control/ot3api.py +60 -23
- opentrons/hardware_control/protocols/gripper_controller.py +3 -0
- opentrons/hardware_control/protocols/hardware_manager.py +5 -1
- opentrons/hardware_control/protocols/liquid_handler.py +18 -0
- opentrons/hardware_control/protocols/motion_controller.py +6 -0
- opentrons/hardware_control/robot_calibration.py +1 -1
- opentrons/hardware_control/types.py +61 -0
- opentrons/protocol_api/__init__.py +20 -1
- opentrons/protocol_api/_liquid.py +24 -49
- opentrons/protocol_api/_liquid_properties.py +754 -0
- opentrons/protocol_api/_types.py +24 -0
- opentrons/protocol_api/core/common.py +2 -0
- opentrons/protocol_api/core/engine/instrument.py +82 -10
- opentrons/protocol_api/core/engine/labware.py +29 -7
- opentrons/protocol_api/core/engine/protocol.py +130 -5
- opentrons/protocol_api/core/engine/robot.py +139 -0
- opentrons/protocol_api/core/engine/well.py +4 -1
- opentrons/protocol_api/core/instrument.py +46 -4
- opentrons/protocol_api/core/labware.py +13 -4
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +37 -3
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +13 -4
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +32 -1
- opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +37 -3
- opentrons/protocol_api/core/protocol.py +34 -1
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/instrument_context.py +158 -44
- opentrons/protocol_api/labware.py +231 -7
- opentrons/protocol_api/module_contexts.py +21 -17
- opentrons/protocol_api/protocol_context.py +125 -4
- opentrons/protocol_api/robot_context.py +204 -32
- opentrons/protocol_api/validation.py +262 -3
- opentrons/protocol_engine/__init__.py +4 -0
- opentrons/protocol_engine/actions/actions.py +2 -3
- opentrons/protocol_engine/clients/sync_client.py +18 -0
- opentrons/protocol_engine/commands/__init__.py +81 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +0 -2
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +19 -5
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +0 -1
- opentrons/protocol_engine/commands/absorbance_reader/read.py +32 -9
- opentrons/protocol_engine/commands/air_gap_in_place.py +160 -0
- opentrons/protocol_engine/commands/aspirate.py +103 -53
- opentrons/protocol_engine/commands/aspirate_in_place.py +55 -51
- opentrons/protocol_engine/commands/blow_out.py +44 -39
- opentrons/protocol_engine/commands/blow_out_in_place.py +21 -32
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +13 -6
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +1 -1
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +3 -3
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +1 -1
- opentrons/protocol_engine/commands/command.py +73 -66
- opentrons/protocol_engine/commands/command_unions.py +101 -1
- opentrons/protocol_engine/commands/comment.py +1 -1
- opentrons/protocol_engine/commands/configure_for_volume.py +10 -3
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +6 -4
- opentrons/protocol_engine/commands/custom.py +6 -12
- opentrons/protocol_engine/commands/dispense.py +82 -48
- opentrons/protocol_engine/commands/dispense_in_place.py +71 -51
- opentrons/protocol_engine/commands/drop_tip.py +52 -31
- opentrons/protocol_engine/commands/drop_tip_in_place.py +13 -3
- opentrons/protocol_engine/commands/generate_command_schema.py +4 -11
- opentrons/protocol_engine/commands/get_next_tip.py +134 -0
- opentrons/protocol_engine/commands/get_tip_presence.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +10 -4
- opentrons/protocol_engine/commands/home.py +13 -4
- opentrons/protocol_engine/commands/liquid_probe.py +67 -24
- opentrons/protocol_engine/commands/load_labware.py +29 -7
- opentrons/protocol_engine/commands/load_lid.py +146 -0
- opentrons/protocol_engine/commands/load_lid_stack.py +189 -0
- opentrons/protocol_engine/commands/load_liquid.py +12 -4
- opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
- opentrons/protocol_engine/commands/load_module.py +31 -10
- opentrons/protocol_engine/commands/load_pipette.py +19 -8
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +1 -1
- opentrons/protocol_engine/commands/magnetic_module/engage.py +1 -1
- opentrons/protocol_engine/commands/move_labware.py +19 -6
- opentrons/protocol_engine/commands/move_relative.py +35 -25
- opentrons/protocol_engine/commands/move_to_addressable_area.py +40 -27
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +53 -32
- opentrons/protocol_engine/commands/move_to_coordinates.py +36 -22
- opentrons/protocol_engine/commands/move_to_well.py +40 -24
- opentrons/protocol_engine/commands/movement_common.py +338 -0
- opentrons/protocol_engine/commands/pick_up_tip.py +49 -27
- opentrons/protocol_engine/commands/pipetting_common.py +169 -87
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +24 -33
- opentrons/protocol_engine/commands/reload_labware.py +1 -1
- opentrons/protocol_engine/commands/retract_axis.py +1 -1
- opentrons/protocol_engine/commands/robot/__init__.py +69 -0
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +86 -0
- opentrons/protocol_engine/commands/robot/common.py +18 -0
- opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
- opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
- opentrons/protocol_engine/commands/robot/move_to.py +94 -0
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +77 -0
- opentrons/protocol_engine/commands/save_position.py +14 -5
- opentrons/protocol_engine/commands/set_rail_lights.py +1 -1
- opentrons/protocol_engine/commands/set_status_bar.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +10 -4
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +8 -2
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +9 -3
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +11 -4
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +1 -1
- opentrons/protocol_engine/commands/touch_tip.py +65 -16
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +4 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -3
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +1 -4
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +1 -4
- opentrons/protocol_engine/commands/verify_tip_presence.py +11 -4
- opentrons/protocol_engine/commands/wait_for_duration.py +10 -3
- opentrons/protocol_engine/commands/wait_for_resume.py +10 -3
- opentrons/protocol_engine/errors/__init__.py +8 -0
- opentrons/protocol_engine/errors/error_occurrence.py +19 -20
- opentrons/protocol_engine/errors/exceptions.py +50 -0
- opentrons/protocol_engine/execution/command_executor.py +1 -1
- opentrons/protocol_engine/execution/equipment.py +73 -5
- opentrons/protocol_engine/execution/gantry_mover.py +364 -8
- opentrons/protocol_engine/execution/movement.py +27 -0
- opentrons/protocol_engine/execution/pipetting.py +5 -1
- opentrons/protocol_engine/execution/tip_handler.py +4 -6
- opentrons/protocol_engine/notes/notes.py +1 -1
- opentrons/protocol_engine/protocol_engine.py +7 -6
- opentrons/protocol_engine/resources/labware_data_provider.py +1 -1
- opentrons/protocol_engine/resources/labware_validation.py +5 -0
- opentrons/protocol_engine/resources/module_data_provider.py +1 -1
- opentrons/protocol_engine/resources/pipette_data_provider.py +26 -0
- opentrons/protocol_engine/slot_standardization.py +9 -9
- opentrons/protocol_engine/state/_move_types.py +9 -5
- opentrons/protocol_engine/state/_well_math.py +193 -0
- opentrons/protocol_engine/state/addressable_areas.py +25 -61
- opentrons/protocol_engine/state/command_history.py +12 -0
- opentrons/protocol_engine/state/commands.py +17 -13
- opentrons/protocol_engine/state/files.py +10 -12
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/frustum_helpers.py +57 -32
- opentrons/protocol_engine/state/geometry.py +47 -1
- opentrons/protocol_engine/state/labware.py +79 -25
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +16 -4
- opentrons/protocol_engine/state/modules.py +52 -70
- opentrons/protocol_engine/state/motion.py +6 -1
- opentrons/protocol_engine/state/pipettes.py +144 -58
- opentrons/protocol_engine/state/state.py +21 -2
- opentrons/protocol_engine/state/state_summary.py +4 -2
- opentrons/protocol_engine/state/tips.py +11 -44
- opentrons/protocol_engine/state/update_types.py +343 -48
- opentrons/protocol_engine/state/wells.py +19 -11
- opentrons/protocol_engine/types.py +176 -28
- opentrons/protocol_reader/extract_labware_definitions.py +5 -2
- opentrons/protocol_reader/file_format_validator.py +5 -5
- opentrons/protocol_runner/json_file_reader.py +9 -3
- opentrons/protocol_runner/json_translator.py +51 -25
- opentrons/protocol_runner/legacy_command_mapper.py +66 -64
- opentrons/protocol_runner/protocol_runner.py +35 -4
- opentrons/protocol_runner/python_protocol_wrappers.py +1 -1
- opentrons/protocol_runner/run_orchestrator.py +13 -3
- opentrons/protocols/advanced_control/common.py +38 -0
- opentrons/protocols/advanced_control/mix.py +1 -1
- opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
- opentrons/protocols/advanced_control/transfers/common.py +56 -0
- opentrons/protocols/advanced_control/{transfers.py → transfers/transfer.py} +10 -85
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/instrument.py +1 -1
- opentrons/protocols/api_support/util.py +10 -0
- opentrons/protocols/labware.py +39 -6
- opentrons/protocols/models/json_protocol.py +5 -9
- opentrons/simulate.py +3 -1
- opentrons/types.py +162 -2
- opentrons/util/logging_config.py +1 -1
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/METADATA +16 -15
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/RECORD +229 -202
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/WHEEL +1 -1
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/LICENSE +0 -0
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/entry_points.txt +0 -0
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/top_level.txt +0 -0
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
"""Generate a JSON schema against which all create commands statically validate."""
|
|
2
|
+
|
|
2
3
|
import json
|
|
3
|
-
import pydantic
|
|
4
4
|
import argparse
|
|
5
5
|
import sys
|
|
6
|
-
from opentrons.protocol_engine.commands.command_unions import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class CreateCommandUnion(pydantic.BaseModel):
|
|
10
|
-
"""Model that validates a union of all CommandCreate models."""
|
|
11
|
-
|
|
12
|
-
__root__: CommandCreate
|
|
6
|
+
from opentrons.protocol_engine.commands.command_unions import CommandCreateAdapter
|
|
13
7
|
|
|
14
8
|
|
|
15
9
|
def generate_command_schema(version: str) -> str:
|
|
16
10
|
"""Generate a JSON Schema that all valid create commands can validate against."""
|
|
17
|
-
|
|
18
|
-
schema_as_dict = json.loads(raw_json_schema)
|
|
11
|
+
schema_as_dict = CommandCreateAdapter.json_schema(mode="validation")
|
|
19
12
|
schema_as_dict["$id"] = f"opentronsCommandSchemaV{version}"
|
|
20
13
|
schema_as_dict["$schema"] = "http://json-schema.org/draft-07/schema#"
|
|
21
|
-
return json.dumps(schema_as_dict, indent=2)
|
|
14
|
+
return json.dumps(schema_as_dict, indent=2, sort_keys=True)
|
|
22
15
|
|
|
23
16
|
|
|
24
17
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Get next tip command request, result, and implementation models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Optional, Type, List, Literal, Union
|
|
6
|
+
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
|
+
|
|
9
|
+
from opentrons.types import NozzleConfigurationType
|
|
10
|
+
|
|
11
|
+
from ..errors import ErrorOccurrence
|
|
12
|
+
from ..types import NextTipInfo, NoTipAvailable, NoTipReason
|
|
13
|
+
from .pipetting_common import PipetteIdMixin
|
|
14
|
+
|
|
15
|
+
from .command import (
|
|
16
|
+
AbstractCommandImpl,
|
|
17
|
+
BaseCommand,
|
|
18
|
+
BaseCommandCreate,
|
|
19
|
+
SuccessData,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from ..state.state import StateView
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
27
|
+
s.pop("default", None)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
GetNextTipCommandType = Literal["getNextTip"]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class GetNextTipParams(PipetteIdMixin):
|
|
34
|
+
"""Payload needed to resolve the next available tip."""
|
|
35
|
+
|
|
36
|
+
labwareIds: List[str] = Field(
|
|
37
|
+
...,
|
|
38
|
+
description="Labware ID(s) of tip racks to resolve next available tip(s) from"
|
|
39
|
+
" Labware IDs will be resolved sequentially",
|
|
40
|
+
)
|
|
41
|
+
startingTipWell: str | SkipJsonSchema[None] = Field(
|
|
42
|
+
None,
|
|
43
|
+
description="Name of starting tip rack 'well'."
|
|
44
|
+
" This only applies to the first tip rack in the list provided in labwareIDs",
|
|
45
|
+
json_schema_extra=_remove_default,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class GetNextTipResult(BaseModel):
|
|
50
|
+
"""Result data from the execution of a GetNextTip."""
|
|
51
|
+
|
|
52
|
+
nextTipInfo: Union[NextTipInfo, NoTipAvailable] = Field(
|
|
53
|
+
...,
|
|
54
|
+
description="Labware ID and well name of next available tip for a pipette,"
|
|
55
|
+
" or information why no tip could be resolved.",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class GetNextTipImplementation(
|
|
60
|
+
AbstractCommandImpl[GetNextTipParams, SuccessData[GetNextTipResult]]
|
|
61
|
+
):
|
|
62
|
+
"""Get next tip command implementation."""
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
state_view: StateView,
|
|
67
|
+
**kwargs: object,
|
|
68
|
+
) -> None:
|
|
69
|
+
self._state_view = state_view
|
|
70
|
+
|
|
71
|
+
async def execute(self, params: GetNextTipParams) -> SuccessData[GetNextTipResult]:
|
|
72
|
+
"""Get the next available tip for the requested pipette."""
|
|
73
|
+
pipette_id = params.pipetteId
|
|
74
|
+
starting_tip_name = params.startingTipWell
|
|
75
|
+
|
|
76
|
+
num_tips = self._state_view.tips.get_pipette_active_channels(pipette_id)
|
|
77
|
+
nozzle_map = self._state_view.tips.get_pipette_nozzle_map(pipette_id)
|
|
78
|
+
|
|
79
|
+
if (
|
|
80
|
+
starting_tip_name is not None
|
|
81
|
+
and nozzle_map.configuration != NozzleConfigurationType.FULL
|
|
82
|
+
):
|
|
83
|
+
# This is to match the behavior found in PAPI, but also because we don't have logic to automatically find
|
|
84
|
+
# the next tip with partial configuration and a starting tip. This will never work for a 96-channel due to
|
|
85
|
+
# x-axis overlap, but could eventually work with 8-channel if we better define starting tip USED or CLEAN
|
|
86
|
+
# state when starting a protocol to prevent accidental tip pick-up with starting non-full tip racks.
|
|
87
|
+
return SuccessData(
|
|
88
|
+
public=GetNextTipResult(
|
|
89
|
+
nextTipInfo=NoTipAvailable(
|
|
90
|
+
noTipReason=NoTipReason.STARTING_TIP_WITH_PARTIAL,
|
|
91
|
+
message="Cannot automatically resolve next tip with starting tip and partial tip configuration.",
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
next_tip: Union[NextTipInfo, NoTipAvailable]
|
|
97
|
+
for labware_id in params.labwareIds:
|
|
98
|
+
well_name = self._state_view.tips.get_next_tip(
|
|
99
|
+
labware_id=labware_id,
|
|
100
|
+
num_tips=num_tips,
|
|
101
|
+
starting_tip_name=starting_tip_name,
|
|
102
|
+
nozzle_map=nozzle_map,
|
|
103
|
+
)
|
|
104
|
+
if well_name is not None:
|
|
105
|
+
next_tip = NextTipInfo(labwareId=labware_id, tipStartingWell=well_name)
|
|
106
|
+
break
|
|
107
|
+
# After the first tip rack is exhausted, starting tip no longer applies
|
|
108
|
+
starting_tip_name = None
|
|
109
|
+
else:
|
|
110
|
+
next_tip = NoTipAvailable(
|
|
111
|
+
noTipReason=NoTipReason.NO_AVAILABLE_TIPS,
|
|
112
|
+
message="No available tips for given pipette, nozzle configuration and provided tip racks.",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
return SuccessData(public=GetNextTipResult(nextTipInfo=next_tip))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class GetNextTip(BaseCommand[GetNextTipParams, GetNextTipResult, ErrorOccurrence]):
|
|
119
|
+
"""Get next tip command model."""
|
|
120
|
+
|
|
121
|
+
commandType: GetNextTipCommandType = "getNextTip"
|
|
122
|
+
params: GetNextTipParams
|
|
123
|
+
result: Optional[GetNextTipResult]
|
|
124
|
+
|
|
125
|
+
_ImplementationCls: Type[GetNextTipImplementation] = GetNextTipImplementation
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class GetNextTipCreate(BaseCommandCreate[GetNextTipParams]):
|
|
129
|
+
"""Get next tip command creation request model."""
|
|
130
|
+
|
|
131
|
+
commandType: GetNextTipCommandType = "getNextTip"
|
|
132
|
+
params: GetNextTipParams
|
|
133
|
+
|
|
134
|
+
_CommandCls: Type[GetNextTip] = GetNextTip
|
|
@@ -71,7 +71,7 @@ class GetTipPresence(
|
|
|
71
71
|
|
|
72
72
|
commandType: GetTipPresenceCommandType = "getTipPresence"
|
|
73
73
|
params: GetTipPresenceParams
|
|
74
|
-
result: Optional[GetTipPresenceResult]
|
|
74
|
+
result: Optional[GetTipPresenceResult] = None
|
|
75
75
|
|
|
76
76
|
_ImplementationCls: Type[
|
|
77
77
|
GetTipPresenceImplementation
|
|
@@ -69,7 +69,7 @@ class CloseLabwareLatch(
|
|
|
69
69
|
|
|
70
70
|
commandType: CloseLabwareLatchCommandType = "heaterShaker/closeLabwareLatch"
|
|
71
71
|
params: CloseLabwareLatchParams
|
|
72
|
-
result: Optional[CloseLabwareLatchResult]
|
|
72
|
+
result: Optional[CloseLabwareLatchResult] = None
|
|
73
73
|
|
|
74
74
|
_ImplementationCls: Type[CloseLabwareLatchImpl] = CloseLabwareLatchImpl
|
|
75
75
|
|
|
@@ -68,7 +68,7 @@ class DeactivateHeater(
|
|
|
68
68
|
|
|
69
69
|
commandType: DeactivateHeaterCommandType = "heaterShaker/deactivateHeater"
|
|
70
70
|
params: DeactivateHeaterParams
|
|
71
|
-
result: Optional[DeactivateHeaterResult]
|
|
71
|
+
result: Optional[DeactivateHeaterResult] = None
|
|
72
72
|
|
|
73
73
|
_ImplementationCls: Type[DeactivateHeaterImpl] = DeactivateHeaterImpl
|
|
74
74
|
|
|
@@ -70,7 +70,7 @@ class DeactivateShaker(
|
|
|
70
70
|
|
|
71
71
|
commandType: DeactivateShakerCommandType = "heaterShaker/deactivateShaker"
|
|
72
72
|
params: DeactivateShakerParams
|
|
73
|
-
result: Optional[DeactivateShakerResult]
|
|
73
|
+
result: Optional[DeactivateShakerResult] = None
|
|
74
74
|
|
|
75
75
|
_ImplementationCls: Type[DeactivateShakerImpl] = DeactivateShakerImpl
|
|
76
76
|
|
|
@@ -96,7 +96,7 @@ class OpenLabwareLatch(
|
|
|
96
96
|
|
|
97
97
|
commandType: OpenLabwareLatchCommandType = "heaterShaker/openLabwareLatch"
|
|
98
98
|
params: OpenLabwareLatchParams
|
|
99
|
-
result: Optional[OpenLabwareLatchResult]
|
|
99
|
+
result: Optional[OpenLabwareLatchResult] = None
|
|
100
100
|
|
|
101
101
|
_ImplementationCls: Type[OpenLabwareLatchImpl] = OpenLabwareLatchImpl
|
|
102
102
|
|
|
@@ -109,7 +109,7 @@ class SetAndWaitForShakeSpeed(
|
|
|
109
109
|
"heaterShaker/setAndWaitForShakeSpeed"
|
|
110
110
|
)
|
|
111
111
|
params: SetAndWaitForShakeSpeedParams
|
|
112
|
-
result: Optional[SetAndWaitForShakeSpeedResult]
|
|
112
|
+
result: Optional[SetAndWaitForShakeSpeedResult] = None
|
|
113
113
|
|
|
114
114
|
_ImplementationCls: Type[SetAndWaitForShakeSpeedImpl] = SetAndWaitForShakeSpeedImpl
|
|
115
115
|
|
|
@@ -76,7 +76,7 @@ class SetTargetTemperature(
|
|
|
76
76
|
|
|
77
77
|
commandType: SetTargetTemperatureCommandType = "heaterShaker/setTargetTemperature"
|
|
78
78
|
params: SetTargetTemperatureParams
|
|
79
|
-
result: Optional[SetTargetTemperatureResult]
|
|
79
|
+
result: Optional[SetTargetTemperatureResult] = None
|
|
80
80
|
|
|
81
81
|
_ImplementationCls: Type[SetTargetTemperatureImpl] = SetTargetTemperatureImpl
|
|
82
82
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Command models to wait for a Heater-Shaker Module's target temperature."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
-
from typing import Optional, TYPE_CHECKING
|
|
4
|
-
from typing_extensions import Literal, Type
|
|
3
|
+
from typing import Optional, TYPE_CHECKING, Any
|
|
5
4
|
|
|
5
|
+
from typing_extensions import Literal, Type
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
7
8
|
|
|
8
9
|
from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
9
10
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
@@ -16,11 +17,15 @@ if TYPE_CHECKING:
|
|
|
16
17
|
WaitForTemperatureCommandType = Literal["heaterShaker/waitForTemperature"]
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
21
|
+
s.pop("default", None)
|
|
22
|
+
|
|
23
|
+
|
|
19
24
|
class WaitForTemperatureParams(BaseModel):
|
|
20
25
|
"""Input parameters to wait for a Heater-Shaker's target temperature."""
|
|
21
26
|
|
|
22
27
|
moduleId: str = Field(..., description="Unique ID of the Heater-Shaker Module.")
|
|
23
|
-
celsius:
|
|
28
|
+
celsius: float | SkipJsonSchema[None] = Field(
|
|
24
29
|
None,
|
|
25
30
|
description="Target temperature in °C. If not specified, will "
|
|
26
31
|
"default to the module's target temperature. "
|
|
@@ -28,6 +33,7 @@ class WaitForTemperatureParams(BaseModel):
|
|
|
28
33
|
"could lead to unpredictable behavior and hence is not "
|
|
29
34
|
"recommended for use. This parameter can be removed in a "
|
|
30
35
|
"future version without prior notice.",
|
|
36
|
+
json_schema_extra=_remove_default,
|
|
31
37
|
)
|
|
32
38
|
|
|
33
39
|
|
|
@@ -82,7 +88,7 @@ class WaitForTemperature(
|
|
|
82
88
|
|
|
83
89
|
commandType: WaitForTemperatureCommandType = "heaterShaker/waitForTemperature"
|
|
84
90
|
params: WaitForTemperatureParams
|
|
85
|
-
result: Optional[WaitForTemperatureResult]
|
|
91
|
+
result: Optional[WaitForTemperatureResult] = None
|
|
86
92
|
|
|
87
93
|
_ImplementationCls: Type[WaitForTemperatureImpl] = WaitForTemperatureImpl
|
|
88
94
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"""Home command payload, result, and implementation models."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, List, Type, Any
|
|
4
|
+
|
|
3
5
|
from pydantic import BaseModel, Field
|
|
4
|
-
from
|
|
6
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
7
|
+
|
|
5
8
|
from typing_extensions import Literal
|
|
6
9
|
|
|
7
10
|
from opentrons.types import MountType
|
|
@@ -17,24 +20,30 @@ if TYPE_CHECKING:
|
|
|
17
20
|
HomeCommandType = Literal["home"]
|
|
18
21
|
|
|
19
22
|
|
|
23
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
24
|
+
s.pop("default", None)
|
|
25
|
+
|
|
26
|
+
|
|
20
27
|
class HomeParams(BaseModel):
|
|
21
28
|
"""Payload required for a Home command."""
|
|
22
29
|
|
|
23
|
-
axes:
|
|
30
|
+
axes: List[MotorAxis] | SkipJsonSchema[None] = Field(
|
|
24
31
|
None,
|
|
25
32
|
description=(
|
|
26
33
|
"Axes to return to their home positions. If omitted,"
|
|
27
34
|
" will home all motors. Extra axes may be implicitly homed"
|
|
28
35
|
" to ensure accurate homing of the explicitly specified axes."
|
|
29
36
|
),
|
|
37
|
+
json_schema_extra=_remove_default,
|
|
30
38
|
)
|
|
31
|
-
skipIfMountPositionOk:
|
|
39
|
+
skipIfMountPositionOk: MountType | SkipJsonSchema[None] = Field(
|
|
32
40
|
None,
|
|
33
41
|
description=(
|
|
34
42
|
"If this parameter is provided, the gantry will only be homed if the"
|
|
35
43
|
" specified mount has an invalid position. If omitted, the homing action"
|
|
36
44
|
" will be executed unconditionally."
|
|
37
45
|
),
|
|
46
|
+
json_schema_extra=_remove_default,
|
|
38
47
|
)
|
|
39
48
|
|
|
40
49
|
|
|
@@ -77,7 +86,7 @@ class Home(BaseCommand[HomeParams, HomeResult, ErrorOccurrence]):
|
|
|
77
86
|
|
|
78
87
|
commandType: HomeCommandType = "home"
|
|
79
88
|
params: HomeParams
|
|
80
|
-
result: Optional[HomeResult]
|
|
89
|
+
result: Optional[HomeResult] = None
|
|
81
90
|
|
|
82
91
|
_ImplementationCls: Type[HomeImplementation] = HomeImplementation
|
|
83
92
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"""The liquidProbe and tryLiquidProbe commands."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from typing import TYPE_CHECKING, NamedTuple, Optional, Type, Union
|
|
5
|
-
from typing_extensions import Literal
|
|
4
|
+
from typing import TYPE_CHECKING, NamedTuple, Optional, Type, Union, Any
|
|
6
5
|
|
|
6
|
+
from typing_extensions import Literal
|
|
7
7
|
from pydantic import Field
|
|
8
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
9
|
|
|
9
10
|
from opentrons.protocol_engine.state import update_types
|
|
10
11
|
from opentrons.protocol_engine.errors.exceptions import (
|
|
@@ -12,18 +13,24 @@ from opentrons.protocol_engine.errors.exceptions import (
|
|
|
12
13
|
PipetteNotReadyToAspirateError,
|
|
13
14
|
TipNotEmptyError,
|
|
14
15
|
IncompleteLabwareDefinitionError,
|
|
16
|
+
TipNotAttachedError,
|
|
15
17
|
)
|
|
16
18
|
from opentrons.types import MountType
|
|
17
19
|
from opentrons_shared_data.errors.exceptions import (
|
|
18
20
|
PipetteLiquidNotFoundError,
|
|
21
|
+
UnsupportedHardwareCommand,
|
|
19
22
|
)
|
|
20
23
|
|
|
21
24
|
from ..types import DeckPoint
|
|
22
25
|
from .pipetting_common import (
|
|
23
26
|
LiquidNotFoundError,
|
|
24
27
|
PipetteIdMixin,
|
|
28
|
+
)
|
|
29
|
+
from .movement_common import (
|
|
25
30
|
WellLocationMixin,
|
|
26
31
|
DestinationPositionResult,
|
|
32
|
+
StallOrCollisionError,
|
|
33
|
+
move_to_well,
|
|
27
34
|
)
|
|
28
35
|
from .command import (
|
|
29
36
|
AbstractCommandImpl,
|
|
@@ -41,6 +48,10 @@ if TYPE_CHECKING:
|
|
|
41
48
|
from ..state.state import StateView
|
|
42
49
|
|
|
43
50
|
|
|
51
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
52
|
+
s.pop("default", None)
|
|
53
|
+
|
|
54
|
+
|
|
44
55
|
LiquidProbeCommandType = Literal["liquidProbe"]
|
|
45
56
|
TryLiquidProbeCommandType = Literal["tryLiquidProbe"]
|
|
46
57
|
|
|
@@ -76,20 +87,23 @@ class LiquidProbeResult(DestinationPositionResult):
|
|
|
76
87
|
class TryLiquidProbeResult(DestinationPositionResult):
|
|
77
88
|
"""Result data from the execution of a `tryLiquidProbe` command."""
|
|
78
89
|
|
|
79
|
-
z_position:
|
|
90
|
+
z_position: float | SkipJsonSchema[None] = Field(
|
|
80
91
|
...,
|
|
81
92
|
description=(
|
|
82
93
|
"The Z coordinate, in mm, of the found liquid in deck space."
|
|
83
94
|
" If no liquid was found, `null` or omitted."
|
|
84
95
|
),
|
|
96
|
+
json_schema_extra=_remove_default,
|
|
85
97
|
)
|
|
86
98
|
|
|
87
99
|
|
|
88
100
|
_LiquidProbeExecuteReturn = Union[
|
|
89
101
|
SuccessData[LiquidProbeResult],
|
|
90
|
-
DefinedErrorData[LiquidNotFoundError],
|
|
102
|
+
DefinedErrorData[LiquidNotFoundError] | DefinedErrorData[StallOrCollisionError],
|
|
91
103
|
]
|
|
92
|
-
_TryLiquidProbeExecuteReturn =
|
|
104
|
+
_TryLiquidProbeExecuteReturn = (
|
|
105
|
+
SuccessData[TryLiquidProbeResult] | DefinedErrorData[StallOrCollisionError]
|
|
106
|
+
)
|
|
93
107
|
|
|
94
108
|
|
|
95
109
|
class _ExecuteCommonResult(NamedTuple):
|
|
@@ -106,13 +120,24 @@ async def _execute_common(
|
|
|
106
120
|
state_view: StateView,
|
|
107
121
|
movement: MovementHandler,
|
|
108
122
|
pipetting: PipettingHandler,
|
|
123
|
+
model_utils: ModelUtils,
|
|
109
124
|
params: _CommonParams,
|
|
110
|
-
) -> _ExecuteCommonResult:
|
|
125
|
+
) -> _ExecuteCommonResult | DefinedErrorData[StallOrCollisionError]:
|
|
111
126
|
pipette_id = params.pipetteId
|
|
112
127
|
labware_id = params.labwareId
|
|
113
128
|
well_name = params.wellName
|
|
129
|
+
if (
|
|
130
|
+
"pressure"
|
|
131
|
+
not in state_view.pipettes.get_config(pipette_id).available_sensors.sensors
|
|
132
|
+
):
|
|
133
|
+
raise UnsupportedHardwareCommand(
|
|
134
|
+
"Pressure sensor not available for this pipette"
|
|
135
|
+
)
|
|
114
136
|
|
|
115
|
-
|
|
137
|
+
if not state_view.pipettes.get_nozzle_configuration_supports_lld(pipette_id):
|
|
138
|
+
raise TipNotAttachedError(
|
|
139
|
+
"Either the front right or back left nozzle must have a tip attached to probe liquid height."
|
|
140
|
+
)
|
|
116
141
|
|
|
117
142
|
# May raise TipNotAttachedError.
|
|
118
143
|
aspirated_volume = state_view.pipettes.get_aspirated_volume(pipette_id)
|
|
@@ -137,20 +162,16 @@ async def _execute_common(
|
|
|
137
162
|
)
|
|
138
163
|
|
|
139
164
|
# liquid_probe process start position
|
|
140
|
-
|
|
165
|
+
move_result = await move_to_well(
|
|
166
|
+
movement=movement,
|
|
167
|
+
model_utils=model_utils,
|
|
141
168
|
pipette_id=pipette_id,
|
|
142
169
|
labware_id=labware_id,
|
|
143
170
|
well_name=well_name,
|
|
144
171
|
well_location=params.wellLocation,
|
|
145
172
|
)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
pipette_id=pipette_id,
|
|
149
|
-
new_labware_id=labware_id,
|
|
150
|
-
new_well_name=well_name,
|
|
151
|
-
new_deck_point=deck_point,
|
|
152
|
-
)
|
|
153
|
-
|
|
173
|
+
if isinstance(move_result, DefinedErrorData):
|
|
174
|
+
return move_result
|
|
154
175
|
try:
|
|
155
176
|
z_pos = await pipetting.liquid_probe_in_place(
|
|
156
177
|
pipette_id=pipette_id,
|
|
@@ -160,11 +181,15 @@ async def _execute_common(
|
|
|
160
181
|
)
|
|
161
182
|
except PipetteLiquidNotFoundError as exception:
|
|
162
183
|
return _ExecuteCommonResult(
|
|
163
|
-
z_pos_or_error=exception,
|
|
184
|
+
z_pos_or_error=exception,
|
|
185
|
+
state_update=move_result.state_update,
|
|
186
|
+
deck_point=move_result.public.position,
|
|
164
187
|
)
|
|
165
188
|
else:
|
|
166
189
|
return _ExecuteCommonResult(
|
|
167
|
-
z_pos_or_error=z_pos,
|
|
190
|
+
z_pos_or_error=z_pos,
|
|
191
|
+
state_update=move_result.state_update,
|
|
192
|
+
deck_point=move_result.public.position,
|
|
168
193
|
)
|
|
169
194
|
|
|
170
195
|
|
|
@@ -202,9 +227,16 @@ class LiquidProbeImplementation(
|
|
|
202
227
|
MustHomeError: as an undefined error, if the plunger is not in a valid
|
|
203
228
|
position.
|
|
204
229
|
"""
|
|
205
|
-
|
|
206
|
-
self._state_view,
|
|
230
|
+
result = await _execute_common(
|
|
231
|
+
state_view=self._state_view,
|
|
232
|
+
movement=self._movement,
|
|
233
|
+
pipetting=self._pipetting,
|
|
234
|
+
model_utils=self._model_utils,
|
|
235
|
+
params=params,
|
|
207
236
|
)
|
|
237
|
+
if isinstance(result, DefinedErrorData):
|
|
238
|
+
return result
|
|
239
|
+
z_pos_or_error, state_update, deck_point = result
|
|
208
240
|
if isinstance(z_pos_or_error, PipetteLiquidNotFoundError):
|
|
209
241
|
state_update.set_liquid_probed(
|
|
210
242
|
labware_id=params.labwareId,
|
|
@@ -278,9 +310,16 @@ class TryLiquidProbeImplementation(
|
|
|
278
310
|
found, `tryLiquidProbe` returns a success result with `z_position=null` instead
|
|
279
311
|
of a defined error.
|
|
280
312
|
"""
|
|
281
|
-
|
|
282
|
-
self._state_view,
|
|
313
|
+
result = await _execute_common(
|
|
314
|
+
state_view=self._state_view,
|
|
315
|
+
movement=self._movement,
|
|
316
|
+
pipetting=self._pipetting,
|
|
317
|
+
model_utils=self._model_utils,
|
|
318
|
+
params=params,
|
|
283
319
|
)
|
|
320
|
+
if isinstance(result, DefinedErrorData):
|
|
321
|
+
return result
|
|
322
|
+
z_pos_or_error, state_update, deck_point = result
|
|
284
323
|
|
|
285
324
|
if isinstance(z_pos_or_error, PipetteLiquidNotFoundError):
|
|
286
325
|
z_pos = None
|
|
@@ -312,7 +351,11 @@ class TryLiquidProbeImplementation(
|
|
|
312
351
|
|
|
313
352
|
|
|
314
353
|
class LiquidProbe(
|
|
315
|
-
BaseCommand[
|
|
354
|
+
BaseCommand[
|
|
355
|
+
LiquidProbeParams,
|
|
356
|
+
LiquidProbeResult,
|
|
357
|
+
LiquidNotFoundError | StallOrCollisionError,
|
|
358
|
+
]
|
|
316
359
|
):
|
|
317
360
|
"""The model for a full `liquidProbe` command."""
|
|
318
361
|
|
|
@@ -324,7 +367,7 @@ class LiquidProbe(
|
|
|
324
367
|
|
|
325
368
|
|
|
326
369
|
class TryLiquidProbe(
|
|
327
|
-
BaseCommand[TryLiquidProbeParams, TryLiquidProbeResult,
|
|
370
|
+
BaseCommand[TryLiquidProbeParams, TryLiquidProbeResult, StallOrCollisionError]
|
|
328
371
|
):
|
|
329
372
|
"""The model for a full `tryLiquidProbe` command."""
|
|
330
373
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Load labware command request, result, and implementation models."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, Type, Any
|
|
4
|
+
|
|
3
5
|
from pydantic import BaseModel, Field
|
|
4
|
-
from
|
|
6
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
5
7
|
from typing_extensions import Literal
|
|
6
8
|
|
|
7
9
|
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
@@ -29,6 +31,10 @@ if TYPE_CHECKING:
|
|
|
29
31
|
LoadLabwareCommandType = Literal["loadLabware"]
|
|
30
32
|
|
|
31
33
|
|
|
34
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
35
|
+
s.pop("default", None)
|
|
36
|
+
|
|
37
|
+
|
|
32
38
|
class LoadLabwareParams(BaseModel):
|
|
33
39
|
"""Payload required to load a labware into a slot."""
|
|
34
40
|
|
|
@@ -48,18 +54,20 @@ class LoadLabwareParams(BaseModel):
|
|
|
48
54
|
...,
|
|
49
55
|
description="The labware definition version.",
|
|
50
56
|
)
|
|
51
|
-
labwareId:
|
|
57
|
+
labwareId: str | SkipJsonSchema[None] = Field(
|
|
52
58
|
None,
|
|
53
59
|
description="An optional ID to assign to this labware. If None, an ID "
|
|
54
60
|
"will be generated.",
|
|
61
|
+
json_schema_extra=_remove_default,
|
|
55
62
|
)
|
|
56
|
-
displayName:
|
|
63
|
+
displayName: str | SkipJsonSchema[None] = Field(
|
|
57
64
|
None,
|
|
58
65
|
description="An optional user-specified display name "
|
|
59
66
|
"or label for this labware.",
|
|
60
67
|
# NOTE: v4/5 JSON protocols will always have a displayName which will be the
|
|
61
68
|
# user-specified label OR the displayName property of the labware's definition.
|
|
62
69
|
# TODO: Make sure v6 JSON protocols don't do that.
|
|
70
|
+
json_schema_extra=_remove_default,
|
|
63
71
|
)
|
|
64
72
|
|
|
65
73
|
|
|
@@ -104,6 +112,8 @@ class LoadLabwareImplementation(
|
|
|
104
112
|
self, params: LoadLabwareParams
|
|
105
113
|
) -> SuccessData[LoadLabwareResult]:
|
|
106
114
|
"""Load definition and calibration data necessary for a labware."""
|
|
115
|
+
state_update = StateUpdate()
|
|
116
|
+
|
|
107
117
|
# TODO (tz, 8-15-2023): extend column validation to column 1 when working
|
|
108
118
|
# on https://opentrons.atlassian.net/browse/RSS-258 and completing
|
|
109
119
|
# https://opentrons.atlassian.net/browse/RSS-255
|
|
@@ -128,10 +138,12 @@ class LoadLabwareImplementation(
|
|
|
128
138
|
self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
|
|
129
139
|
area_name
|
|
130
140
|
)
|
|
141
|
+
state_update.set_addressable_area_used(area_name)
|
|
131
142
|
elif isinstance(params.location, DeckSlotLocation):
|
|
132
143
|
self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
|
|
133
144
|
params.location.slotName.id
|
|
134
145
|
)
|
|
146
|
+
state_update.set_addressable_area_used(params.location.slotName.id)
|
|
135
147
|
|
|
136
148
|
verified_location = self._state_view.geometry.ensure_location_not_occupied(
|
|
137
149
|
params.location
|
|
@@ -144,8 +156,6 @@ class LoadLabwareImplementation(
|
|
|
144
156
|
labware_id=params.labwareId,
|
|
145
157
|
)
|
|
146
158
|
|
|
147
|
-
state_update = StateUpdate()
|
|
148
|
-
|
|
149
159
|
state_update.set_loaded_labware(
|
|
150
160
|
labware_id=loaded_labware.labware_id,
|
|
151
161
|
offset_id=loaded_labware.offsetId,
|
|
@@ -162,6 +172,19 @@ class LoadLabwareImplementation(
|
|
|
162
172
|
top_labware_definition=loaded_labware.definition,
|
|
163
173
|
bottom_labware_id=verified_location.labwareId,
|
|
164
174
|
)
|
|
175
|
+
# Validate load location is valid for lids
|
|
176
|
+
if (
|
|
177
|
+
labware_validation.validate_definition_is_lid(
|
|
178
|
+
definition=loaded_labware.definition
|
|
179
|
+
)
|
|
180
|
+
and loaded_labware.definition.compatibleParentLabware is not None
|
|
181
|
+
and self._state_view.labware.get_load_name(verified_location.labwareId)
|
|
182
|
+
not in loaded_labware.definition.compatibleParentLabware
|
|
183
|
+
):
|
|
184
|
+
raise ValueError(
|
|
185
|
+
f"Labware Lid {params.loadName} may not be loaded on parent labware {self._state_view.labware.get_display_name(verified_location.labwareId)}."
|
|
186
|
+
)
|
|
187
|
+
|
|
165
188
|
# Validate labware for the absorbance reader
|
|
166
189
|
elif isinstance(params.location, ModuleLocation):
|
|
167
190
|
module = self._state_view.modules.get(params.location.moduleId)
|
|
@@ -169,7 +192,6 @@ class LoadLabwareImplementation(
|
|
|
169
192
|
self._state_view.labware.raise_if_labware_incompatible_with_plate_reader(
|
|
170
193
|
loaded_labware.definition
|
|
171
194
|
)
|
|
172
|
-
|
|
173
195
|
return SuccessData(
|
|
174
196
|
public=LoadLabwareResult(
|
|
175
197
|
labwareId=loaded_labware.labware_id,
|
|
@@ -185,7 +207,7 @@ class LoadLabware(BaseCommand[LoadLabwareParams, LoadLabwareResult, ErrorOccurre
|
|
|
185
207
|
|
|
186
208
|
commandType: LoadLabwareCommandType = "loadLabware"
|
|
187
209
|
params: LoadLabwareParams
|
|
188
|
-
result: Optional[LoadLabwareResult]
|
|
210
|
+
result: Optional[LoadLabwareResult] = None
|
|
189
211
|
|
|
190
212
|
_ImplementationCls: Type[LoadLabwareImplementation] = LoadLabwareImplementation
|
|
191
213
|
|