opentrons 8.2.0a4__py2.py3-none-any.whl → 8.3.0__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.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- 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 +33 -21
- 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 +78 -31
- 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 +22 -1
- opentrons/hardware_control/protocols/motion_controller.py +7 -0
- opentrons/hardware_control/robot_calibration.py +1 -1
- opentrons/hardware_control/types.py +61 -0
- opentrons/legacy_commands/commands.py +37 -0
- opentrons/legacy_commands/types.py +39 -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 +191 -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 +73 -4
- opentrons/protocol_api/core/labware.py +13 -4
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +87 -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 +61 -3
- opentrons/protocol_api/core/protocol.py +34 -1
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/instrument_context.py +299 -44
- opentrons/protocol_api/labware.py +248 -9
- 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 +121 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +1 -3
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +20 -6
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +1 -2
- opentrons/protocol_engine/commands/absorbance_reader/read.py +36 -10
- 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 +140 -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 +79 -8
- opentrons/protocol_engine/commands/evotip_dispense.py +156 -0
- opentrons/protocol_engine/commands/evotip_seal_pipette.py +331 -0
- opentrons/protocol_engine/commands/evotip_unseal_pipette.py +160 -0
- 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 +125 -31
- opentrons/protocol_engine/commands/load_labware.py +33 -6
- 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 +28 -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 +9 -3
- 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 +5 -2
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +13 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +2 -5
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +1 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +1 -1
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +2 -5
- 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 +12 -0
- opentrons/protocol_engine/errors/error_occurrence.py +19 -20
- opentrons/protocol_engine/errors/exceptions.py +76 -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 +369 -8
- opentrons/protocol_engine/execution/hardware_stopper.py +7 -7
- opentrons/protocol_engine/execution/movement.py +27 -0
- opentrons/protocol_engine/execution/pipetting.py +5 -1
- opentrons/protocol_engine/execution/tip_handler.py +34 -15
- 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 +18 -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 +22 -14
- opentrons/protocol_engine/state/files.py +10 -12
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/frustum_helpers.py +63 -69
- opentrons/protocol_engine/state/geometry.py +47 -1
- opentrons/protocol_engine/state/labware.py +92 -26
- 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 +149 -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 +70 -8
- opentrons/protocols/models/json_protocol.py +5 -9
- opentrons/simulate.py +3 -1
- opentrons/types.py +162 -2
- opentrons/util/entrypoint_util.py +2 -5
- opentrons/util/logging_config.py +1 -1
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/METADATA +16 -15
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/RECORD +238 -208
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/WHEEL +1 -1
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/LICENSE +0 -0
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/top_level.txt +0 -0
opentrons/protocol_api/_types.py
CHANGED
|
@@ -17,3 +17,27 @@ A special location value, indicating that a labware is not currently on the robo
|
|
|
17
17
|
|
|
18
18
|
See :ref:`off-deck-location` for details on using ``OFF_DECK`` with :py:obj:`ProtocolContext.move_labware()`.
|
|
19
19
|
"""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PlungerPositionTypes(enum.Enum):
|
|
23
|
+
PLUNGER_TOP = "top"
|
|
24
|
+
PLUNGER_BOTTOM = "bottom"
|
|
25
|
+
PLUNGER_BLOWOUT = "blow_out"
|
|
26
|
+
PLUNGER_DROPTIP = "drop_tip"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
PLUNGER_TOP: Final = PlungerPositionTypes.PLUNGER_TOP
|
|
30
|
+
PLUNGER_BOTTOM: Final = PlungerPositionTypes.PLUNGER_BOTTOM
|
|
31
|
+
PLUNGER_BLOWOUT: Final = PlungerPositionTypes.PLUNGER_BLOWOUT
|
|
32
|
+
PLUNGER_DROPTIP: Final = PlungerPositionTypes.PLUNGER_DROPTIP
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class PipetteActionTypes(enum.Enum):
|
|
36
|
+
ASPIRATE_ACTION = "aspirate"
|
|
37
|
+
DISPENSE_ACTION = "dispense"
|
|
38
|
+
BLOWOUT_ACTION = "blowout"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
ASPIRATE_ACTION: Final = PipetteActionTypes.ASPIRATE_ACTION
|
|
42
|
+
DISPENSE_ACTION: Final = PipetteActionTypes.DISPENSE_ACTION
|
|
43
|
+
BLOWOUT_ACTION: Final = PipetteActionTypes.BLOWOUT_ACTION
|
|
@@ -14,6 +14,7 @@ from .module import (
|
|
|
14
14
|
)
|
|
15
15
|
from .protocol import AbstractProtocol
|
|
16
16
|
from .well import AbstractWellCore
|
|
17
|
+
from .robot import AbstractRobot
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
WellCore = AbstractWellCore
|
|
@@ -26,4 +27,5 @@ ThermocyclerCore = AbstractThermocyclerCore
|
|
|
26
27
|
HeaterShakerCore = AbstractHeaterShakerCore
|
|
27
28
|
MagneticBlockCore = AbstractMagneticBlockCore
|
|
28
29
|
AbsorbanceReaderCore = AbstractAbsorbanceReaderCore
|
|
30
|
+
RobotCore = AbstractRobot
|
|
29
31
|
ProtocolCore = AbstractProtocol[InstrumentCore, LabwareCore, ModuleCore]
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"""ProtocolEngine-based InstrumentContext core implementation."""
|
|
2
|
-
from __future__ import annotations
|
|
3
2
|
|
|
4
|
-
from
|
|
5
|
-
from opentrons.protocols.api_support.types import APIVersion
|
|
3
|
+
from __future__ import annotations
|
|
6
4
|
|
|
7
|
-
from
|
|
5
|
+
from typing import Optional, TYPE_CHECKING, cast, Union, List
|
|
6
|
+
from opentrons.types import Location, Mount, NozzleConfigurationType, NozzleMapInterface
|
|
8
7
|
from opentrons.hardware_control import SyncHardwareAPI
|
|
9
8
|
from opentrons.hardware_control.dev_types import PipetteDict
|
|
10
9
|
from opentrons.protocols.api_support.util import FlowRates, find_value_for_api_version
|
|
10
|
+
from opentrons.protocols.api_support.types import APIVersion
|
|
11
|
+
from opentrons.protocols.advanced_control.transfers.common import TransferTipPolicyV2
|
|
11
12
|
from opentrons.protocol_engine import commands as cmd
|
|
12
13
|
from opentrons.protocol_engine import (
|
|
13
14
|
DeckPoint,
|
|
@@ -26,26 +27,29 @@ from opentrons.protocol_engine.types import (
|
|
|
26
27
|
PRIMARY_NOZZLE_LITERAL,
|
|
27
28
|
NozzleLayoutConfigurationType,
|
|
28
29
|
AddressableOffsetVector,
|
|
30
|
+
LiquidClassRecord,
|
|
29
31
|
)
|
|
30
32
|
from opentrons.protocol_engine.errors.exceptions import TipNotAttachedError
|
|
31
33
|
from opentrons.protocol_engine.clients import SyncClient as EngineClient
|
|
32
34
|
from opentrons.protocols.api_support.definitions import MAX_SUPPORTED_VERSION
|
|
33
35
|
from opentrons_shared_data.pipette.types import PipetteNameType
|
|
36
|
+
from opentrons_shared_data.errors.exceptions import (
|
|
37
|
+
UnsupportedHardwareCommand,
|
|
38
|
+
)
|
|
34
39
|
from opentrons.protocol_api._nozzle_layout import NozzleLayout
|
|
35
|
-
from opentrons.hardware_control.nozzle_manager import NozzleConfigurationType
|
|
36
|
-
from opentrons.hardware_control.nozzle_manager import NozzleMap
|
|
37
40
|
from . import overlap_versions, pipette_movement_conflict
|
|
38
41
|
|
|
39
|
-
from ..instrument import AbstractInstrument
|
|
40
42
|
from .well import WellCore
|
|
41
|
-
|
|
43
|
+
from ..instrument import AbstractInstrument
|
|
42
44
|
from ...disposal_locations import TrashBin, WasteChute
|
|
43
45
|
|
|
44
46
|
if TYPE_CHECKING:
|
|
45
47
|
from .protocol import ProtocolCore
|
|
46
|
-
|
|
48
|
+
from opentrons.protocol_api._liquid import LiquidClass
|
|
47
49
|
|
|
48
50
|
_DISPENSE_VOLUME_VALIDATION_ADDED_IN = APIVersion(2, 17)
|
|
51
|
+
_RESIN_TIP_DEFAULT_VOLUME = 400
|
|
52
|
+
_RESIN_TIP_DEFAULT_FLOW_RATE = 10.0
|
|
49
53
|
|
|
50
54
|
|
|
51
55
|
class InstrumentCore(AbstractInstrument[WellCore]):
|
|
@@ -86,6 +90,13 @@ class InstrumentCore(AbstractInstrument[WellCore]):
|
|
|
86
90
|
self._liquid_presence_detection = bool(
|
|
87
91
|
self._engine_client.state.pipettes.get_liquid_presence_detection(pipette_id)
|
|
88
92
|
)
|
|
93
|
+
if (
|
|
94
|
+
self._liquid_presence_detection
|
|
95
|
+
and not self._pressure_supported_by_pipette()
|
|
96
|
+
):
|
|
97
|
+
raise UnsupportedHardwareCommand(
|
|
98
|
+
"Pressure sensor not available for this pipette"
|
|
99
|
+
)
|
|
89
100
|
|
|
90
101
|
@property
|
|
91
102
|
def pipette_id(self) -> str:
|
|
@@ -104,6 +115,19 @@ class InstrumentCore(AbstractInstrument[WellCore]):
|
|
|
104
115
|
pipette_id=self._pipette_id, speed=speed
|
|
105
116
|
)
|
|
106
117
|
|
|
118
|
+
def air_gap_in_place(self, volume: float, flow_rate: float) -> None:
|
|
119
|
+
"""Aspirate a given volume of air from the current location of the pipette.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
volume: The volume of air to aspirate, in microliters.
|
|
123
|
+
folw_rate: The flow rate of air into the pipette, in microliters/s
|
|
124
|
+
"""
|
|
125
|
+
self._engine_client.execute_command(
|
|
126
|
+
cmd.AirGapInPlaceParams(
|
|
127
|
+
pipetteId=self._pipette_id, volume=volume, flowRate=flow_rate
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
|
|
107
131
|
def aspirate(
|
|
108
132
|
self,
|
|
109
133
|
location: Location,
|
|
@@ -656,6 +680,113 @@ class InstrumentCore(AbstractInstrument[WellCore]):
|
|
|
656
680
|
location=location, mount=self.get_mount()
|
|
657
681
|
)
|
|
658
682
|
|
|
683
|
+
def resin_tip_seal(
|
|
684
|
+
self, location: Location, well_core: WellCore, in_place: Optional[bool] = False
|
|
685
|
+
) -> None:
|
|
686
|
+
labware_id = well_core.labware_id
|
|
687
|
+
well_name = well_core.get_name()
|
|
688
|
+
well_location = (
|
|
689
|
+
self._engine_client.state.geometry.get_relative_pick_up_tip_well_location(
|
|
690
|
+
labware_id=labware_id,
|
|
691
|
+
well_name=well_name,
|
|
692
|
+
absolute_point=location.point,
|
|
693
|
+
)
|
|
694
|
+
)
|
|
695
|
+
|
|
696
|
+
self._engine_client.execute_command(
|
|
697
|
+
cmd.EvotipSealPipetteParams(
|
|
698
|
+
pipetteId=self._pipette_id,
|
|
699
|
+
labwareId=labware_id,
|
|
700
|
+
wellName=well_name,
|
|
701
|
+
wellLocation=well_location,
|
|
702
|
+
)
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
def resin_tip_unseal(self, location: Location, well_core: WellCore) -> None:
|
|
706
|
+
well_name = well_core.get_name()
|
|
707
|
+
labware_id = well_core.labware_id
|
|
708
|
+
|
|
709
|
+
if location is not None:
|
|
710
|
+
relative_well_location = (
|
|
711
|
+
self._engine_client.state.geometry.get_relative_well_location(
|
|
712
|
+
labware_id=labware_id,
|
|
713
|
+
well_name=well_name,
|
|
714
|
+
absolute_point=location.point,
|
|
715
|
+
)
|
|
716
|
+
)
|
|
717
|
+
|
|
718
|
+
well_location = DropTipWellLocation(
|
|
719
|
+
origin=DropTipWellOrigin(relative_well_location.origin.value),
|
|
720
|
+
offset=relative_well_location.offset,
|
|
721
|
+
)
|
|
722
|
+
else:
|
|
723
|
+
well_location = DropTipWellLocation()
|
|
724
|
+
|
|
725
|
+
pipette_movement_conflict.check_safe_for_pipette_movement(
|
|
726
|
+
engine_state=self._engine_client.state,
|
|
727
|
+
pipette_id=self._pipette_id,
|
|
728
|
+
labware_id=labware_id,
|
|
729
|
+
well_name=well_name,
|
|
730
|
+
well_location=well_location,
|
|
731
|
+
)
|
|
732
|
+
self._engine_client.execute_command(
|
|
733
|
+
cmd.EvotipUnsealPipetteParams(
|
|
734
|
+
pipetteId=self._pipette_id,
|
|
735
|
+
labwareId=labware_id,
|
|
736
|
+
wellName=well_name,
|
|
737
|
+
wellLocation=well_location,
|
|
738
|
+
)
|
|
739
|
+
)
|
|
740
|
+
|
|
741
|
+
self._protocol_core.set_last_location(location=location, mount=self.get_mount())
|
|
742
|
+
|
|
743
|
+
def resin_tip_dispense(
|
|
744
|
+
self,
|
|
745
|
+
location: Location,
|
|
746
|
+
well_core: WellCore,
|
|
747
|
+
volume: Optional[float] = None,
|
|
748
|
+
flow_rate: Optional[float] = None,
|
|
749
|
+
) -> None:
|
|
750
|
+
"""
|
|
751
|
+
Args:
|
|
752
|
+
volume: The volume of liquid to dispense, in microliters. Defaults to 400uL.
|
|
753
|
+
location: The exact location to dispense to.
|
|
754
|
+
well_core: The well to dispense to, if applicable.
|
|
755
|
+
flow_rate: The flow rate in µL/s to dispense at. Defaults to 10.0uL/S.
|
|
756
|
+
"""
|
|
757
|
+
if isinstance(location, (TrashBin, WasteChute)):
|
|
758
|
+
raise ValueError("Trash Bin and Waste Chute have no Wells.")
|
|
759
|
+
well_name = well_core.get_name()
|
|
760
|
+
labware_id = well_core.labware_id
|
|
761
|
+
if volume is None:
|
|
762
|
+
volume = _RESIN_TIP_DEFAULT_VOLUME
|
|
763
|
+
if flow_rate is None:
|
|
764
|
+
flow_rate = _RESIN_TIP_DEFAULT_FLOW_RATE
|
|
765
|
+
|
|
766
|
+
well_location = self._engine_client.state.geometry.get_relative_liquid_handling_well_location(
|
|
767
|
+
labware_id=labware_id,
|
|
768
|
+
well_name=well_name,
|
|
769
|
+
absolute_point=location.point,
|
|
770
|
+
is_meniscus=None,
|
|
771
|
+
)
|
|
772
|
+
pipette_movement_conflict.check_safe_for_pipette_movement(
|
|
773
|
+
engine_state=self._engine_client.state,
|
|
774
|
+
pipette_id=self._pipette_id,
|
|
775
|
+
labware_id=labware_id,
|
|
776
|
+
well_name=well_name,
|
|
777
|
+
well_location=well_location,
|
|
778
|
+
)
|
|
779
|
+
self._engine_client.execute_command(
|
|
780
|
+
cmd.EvotipDispenseParams(
|
|
781
|
+
pipetteId=self._pipette_id,
|
|
782
|
+
labwareId=labware_id,
|
|
783
|
+
wellName=well_name,
|
|
784
|
+
wellLocation=well_location,
|
|
785
|
+
volume=volume,
|
|
786
|
+
flowRate=flow_rate,
|
|
787
|
+
)
|
|
788
|
+
)
|
|
789
|
+
|
|
659
790
|
def get_mount(self) -> Mount:
|
|
660
791
|
"""Get the mount the pipette is attached to."""
|
|
661
792
|
return self._engine_client.state.pipettes.get(
|
|
@@ -724,7 +855,7 @@ class InstrumentCore(AbstractInstrument[WellCore]):
|
|
|
724
855
|
self._pipette_id
|
|
725
856
|
)
|
|
726
857
|
|
|
727
|
-
def get_nozzle_map(self) ->
|
|
858
|
+
def get_nozzle_map(self) -> NozzleMapInterface:
|
|
728
859
|
return self._engine_client.state.tips.get_pipette_nozzle_map(self._pipette_id)
|
|
729
860
|
|
|
730
861
|
def has_tip(self) -> bool:
|
|
@@ -842,11 +973,55 @@ class InstrumentCore(AbstractInstrument[WellCore]):
|
|
|
842
973
|
)
|
|
843
974
|
)
|
|
844
975
|
|
|
976
|
+
def load_liquid_class(
|
|
977
|
+
self,
|
|
978
|
+
liquid_class: LiquidClass,
|
|
979
|
+
pipette_load_name: str,
|
|
980
|
+
tiprack_uri: str,
|
|
981
|
+
) -> str:
|
|
982
|
+
"""Load a liquid class into the engine and return its ID."""
|
|
983
|
+
transfer_props = liquid_class.get_for(
|
|
984
|
+
pipette=pipette_load_name, tiprack=tiprack_uri
|
|
985
|
+
)
|
|
986
|
+
|
|
987
|
+
liquid_class_record = LiquidClassRecord(
|
|
988
|
+
liquidClassName=liquid_class.name,
|
|
989
|
+
pipetteModel=self.get_model(), # TODO: verify this is the correct 'model' to use
|
|
990
|
+
tiprack=tiprack_uri,
|
|
991
|
+
aspirate=transfer_props.aspirate.as_shared_data_model(),
|
|
992
|
+
singleDispense=transfer_props.dispense.as_shared_data_model(),
|
|
993
|
+
multiDispense=transfer_props.multi_dispense.as_shared_data_model()
|
|
994
|
+
if transfer_props.multi_dispense
|
|
995
|
+
else None,
|
|
996
|
+
)
|
|
997
|
+
result = self._engine_client.execute_command_without_recovery(
|
|
998
|
+
cmd.LoadLiquidClassParams(
|
|
999
|
+
liquidClassRecord=liquid_class_record,
|
|
1000
|
+
)
|
|
1001
|
+
)
|
|
1002
|
+
return result.liquidClassId
|
|
1003
|
+
|
|
1004
|
+
def transfer_liquid(
|
|
1005
|
+
self,
|
|
1006
|
+
liquid_class_id: str,
|
|
1007
|
+
volume: float,
|
|
1008
|
+
source: List[WellCore],
|
|
1009
|
+
dest: List[WellCore],
|
|
1010
|
+
new_tip: TransferTipPolicyV2,
|
|
1011
|
+
trash_location: Union[WellCore, Location, TrashBin, WasteChute],
|
|
1012
|
+
) -> None:
|
|
1013
|
+
"""Execute transfer using liquid class properties."""
|
|
1014
|
+
|
|
845
1015
|
def retract(self) -> None:
|
|
846
1016
|
"""Retract this instrument to the top of the gantry."""
|
|
847
1017
|
z_axis = self._engine_client.state.pipettes.get_z_axis(self._pipette_id)
|
|
848
1018
|
self._engine_client.execute_command(cmd.HomeParams(axes=[z_axis]))
|
|
849
1019
|
|
|
1020
|
+
def _pressure_supported_by_pipette(self) -> bool:
|
|
1021
|
+
return self._engine_client.state.pipettes.get_pipette_supports_pressure(
|
|
1022
|
+
self.pipette_id
|
|
1023
|
+
)
|
|
1024
|
+
|
|
850
1025
|
def detect_liquid_presence(self, well_core: WellCore, loc: Location) -> bool:
|
|
851
1026
|
labware_id = well_core.labware_id
|
|
852
1027
|
well_name = well_core.get_name()
|
|
@@ -922,3 +1097,9 @@ class InstrumentCore(AbstractInstrument[WellCore]):
|
|
|
922
1097
|
self._protocol_core.set_last_location(location=loc, mount=self.get_mount())
|
|
923
1098
|
|
|
924
1099
|
return result.z_position
|
|
1100
|
+
|
|
1101
|
+
def nozzle_configuration_valid_for_lld(self) -> bool:
|
|
1102
|
+
"""Check if the nozzle configuration currently supports LLD."""
|
|
1103
|
+
return self._engine_client.state.pipettes.get_nozzle_configuration_supports_lld(
|
|
1104
|
+
self.pipette_id
|
|
1105
|
+
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""ProtocolEngine-based Labware core implementations."""
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional, cast, Dict
|
|
3
4
|
|
|
4
5
|
from opentrons_shared_data.labware.types import (
|
|
5
6
|
LabwareParameters as LabwareParametersDict,
|
|
@@ -19,11 +20,12 @@ from opentrons.protocol_engine.types import (
|
|
|
19
20
|
LabwareOffsetCreate,
|
|
20
21
|
LabwareOffsetVector,
|
|
21
22
|
)
|
|
22
|
-
from opentrons.types import DeckSlotName, Point, StagingSlotName
|
|
23
|
-
from opentrons.hardware_control.nozzle_manager import NozzleMap
|
|
23
|
+
from opentrons.types import DeckSlotName, NozzleMapInterface, Point, StagingSlotName
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
from ..._liquid import Liquid
|
|
26
27
|
from ..labware import AbstractLabware, LabwareLoadParams
|
|
28
|
+
|
|
27
29
|
from .well import WellCore
|
|
28
30
|
|
|
29
31
|
|
|
@@ -90,12 +92,14 @@ class LabwareCore(AbstractLabware[WellCore]):
|
|
|
90
92
|
|
|
91
93
|
def get_definition(self) -> LabwareDefinitionDict:
|
|
92
94
|
"""Get the labware's definition as a plain dictionary."""
|
|
93
|
-
return cast(
|
|
95
|
+
return cast(
|
|
96
|
+
LabwareDefinitionDict, self._definition.model_dump(exclude_none=True)
|
|
97
|
+
)
|
|
94
98
|
|
|
95
99
|
def get_parameters(self) -> LabwareParametersDict:
|
|
96
100
|
return cast(
|
|
97
101
|
LabwareParametersDict,
|
|
98
|
-
self._definition.parameters.
|
|
102
|
+
self._definition.parameters.model_dump(exclude_none=True),
|
|
99
103
|
)
|
|
100
104
|
|
|
101
105
|
def get_quirks(self) -> List[str]:
|
|
@@ -116,7 +120,7 @@ class LabwareCore(AbstractLabware[WellCore]):
|
|
|
116
120
|
details={"kind": "labware-not-in-slot"},
|
|
117
121
|
)
|
|
118
122
|
|
|
119
|
-
request = LabwareOffsetCreate.
|
|
123
|
+
request = LabwareOffsetCreate.model_construct(
|
|
120
124
|
definitionUri=self.get_uri(),
|
|
121
125
|
location=offset_location,
|
|
122
126
|
vector=LabwareOffsetVector(x=delta.x, y=delta.y, z=delta.z),
|
|
@@ -162,7 +166,7 @@ class LabwareCore(AbstractLabware[WellCore]):
|
|
|
162
166
|
self,
|
|
163
167
|
num_tips: int,
|
|
164
168
|
starting_tip: Optional[WellCore],
|
|
165
|
-
nozzle_map: Optional[
|
|
169
|
+
nozzle_map: Optional[NozzleMapInterface],
|
|
166
170
|
) -> Optional[str]:
|
|
167
171
|
return self._engine_client.state.tips.get_next_tip(
|
|
168
172
|
labware_id=self._labware_id,
|
|
@@ -203,3 +207,21 @@ class LabwareCore(AbstractLabware[WellCore]):
|
|
|
203
207
|
LocationIsStagingSlotError,
|
|
204
208
|
):
|
|
205
209
|
return None
|
|
210
|
+
|
|
211
|
+
def load_liquid(self, volumes: Dict[str, float], liquid: Liquid) -> None:
|
|
212
|
+
"""Load liquid into wells of the labware."""
|
|
213
|
+
self._engine_client.execute_command(
|
|
214
|
+
cmd.LoadLiquidParams(
|
|
215
|
+
labwareId=self._labware_id, liquidId=liquid._id, volumeByWell=volumes
|
|
216
|
+
)
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
def load_empty(self, wells: List[str]) -> None:
|
|
220
|
+
"""Mark wells of the labware as empty."""
|
|
221
|
+
self._engine_client.execute_command(
|
|
222
|
+
cmd.LoadLiquidParams(
|
|
223
|
+
labwareId=self._labware_id,
|
|
224
|
+
liquidId="EMPTY",
|
|
225
|
+
volumeByWell={well: 0.0 for well in wells},
|
|
226
|
+
)
|
|
227
|
+
)
|
|
@@ -6,6 +6,7 @@ from opentrons_shared_data.liquid_classes import LiquidClassDefinitionDoesNotExi
|
|
|
6
6
|
|
|
7
7
|
from opentrons.protocol_engine import commands as cmd
|
|
8
8
|
from opentrons.protocol_engine.commands import LoadModuleResult
|
|
9
|
+
|
|
9
10
|
from opentrons_shared_data.deck.types import DeckDefinitionV5, SlotDefV3
|
|
10
11
|
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
11
12
|
from opentrons_shared_data.labware.types import LabwareDefinition as LabwareDefDict
|
|
@@ -63,6 +64,7 @@ from ..protocol import AbstractProtocol
|
|
|
63
64
|
from ..labware import LabwareLoadParams
|
|
64
65
|
from .labware import LabwareCore
|
|
65
66
|
from .instrument import InstrumentCore
|
|
67
|
+
from .robot import RobotCore
|
|
66
68
|
from .module_core import (
|
|
67
69
|
ModuleCore,
|
|
68
70
|
TemperatureModuleCore,
|
|
@@ -82,7 +84,9 @@ if TYPE_CHECKING:
|
|
|
82
84
|
|
|
83
85
|
class ProtocolCore(
|
|
84
86
|
AbstractProtocol[
|
|
85
|
-
InstrumentCore,
|
|
87
|
+
InstrumentCore,
|
|
88
|
+
LabwareCore,
|
|
89
|
+
Union[ModuleCore, NonConnectedModuleCore],
|
|
86
90
|
]
|
|
87
91
|
):
|
|
88
92
|
"""Protocol API core using a ProtocolEngine.
|
|
@@ -189,7 +193,7 @@ class ProtocolCore(
|
|
|
189
193
|
) -> LabwareLoadParams:
|
|
190
194
|
"""Add a labware definition to the set of loadable definitions."""
|
|
191
195
|
uri = self._engine_client.add_labware_definition(
|
|
192
|
-
LabwareDefinition.
|
|
196
|
+
LabwareDefinition.model_validate(definition)
|
|
193
197
|
)
|
|
194
198
|
return LabwareLoadParams.from_uri(uri)
|
|
195
199
|
|
|
@@ -229,6 +233,9 @@ class ProtocolCore(
|
|
|
229
233
|
)
|
|
230
234
|
# FIXME(jbl, 2023-08-14) validating after loading the object issue
|
|
231
235
|
validation.ensure_definition_is_labware(load_result.definition)
|
|
236
|
+
validation.ensure_definition_is_not_lid_after_api_version(
|
|
237
|
+
self.api_version, load_result.definition
|
|
238
|
+
)
|
|
232
239
|
|
|
233
240
|
# FIXME(mm, 2023-02-21):
|
|
234
241
|
#
|
|
@@ -318,6 +325,52 @@ class ProtocolCore(
|
|
|
318
325
|
|
|
319
326
|
return labware_core
|
|
320
327
|
|
|
328
|
+
def load_lid(
|
|
329
|
+
self,
|
|
330
|
+
load_name: str,
|
|
331
|
+
location: LabwareCore,
|
|
332
|
+
namespace: Optional[str],
|
|
333
|
+
version: Optional[int],
|
|
334
|
+
) -> LabwareCore:
|
|
335
|
+
"""Load an individual lid using its identifying parameters. Must be loaded on an existing Labware."""
|
|
336
|
+
load_location = self._convert_labware_location(location=location)
|
|
337
|
+
custom_labware_params = (
|
|
338
|
+
self._engine_client.state.labware.find_custom_labware_load_params()
|
|
339
|
+
)
|
|
340
|
+
namespace, version = load_labware_params.resolve(
|
|
341
|
+
load_name, namespace, version, custom_labware_params
|
|
342
|
+
)
|
|
343
|
+
load_result = self._engine_client.execute_command_without_recovery(
|
|
344
|
+
cmd.LoadLidParams(
|
|
345
|
+
loadName=load_name,
|
|
346
|
+
location=load_location,
|
|
347
|
+
namespace=namespace,
|
|
348
|
+
version=version,
|
|
349
|
+
)
|
|
350
|
+
)
|
|
351
|
+
# FIXME(chb, 2024-12-06) validating after loading the object issue
|
|
352
|
+
validation.ensure_definition_is_lid(load_result.definition)
|
|
353
|
+
|
|
354
|
+
deck_conflict.check(
|
|
355
|
+
engine_state=self._engine_client.state,
|
|
356
|
+
new_labware_id=load_result.labwareId,
|
|
357
|
+
existing_disposal_locations=self._disposal_locations,
|
|
358
|
+
# TODO: We can now fetch these IDs from engine too.
|
|
359
|
+
# See comment in self.load_labware().
|
|
360
|
+
#
|
|
361
|
+
# Wrapping .keys() in list() is just to make Decoy verification easier.
|
|
362
|
+
existing_labware_ids=list(self._labware_cores_by_id.keys()),
|
|
363
|
+
existing_module_ids=list(self._module_cores_by_id.keys()),
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
labware_core = LabwareCore(
|
|
367
|
+
labware_id=load_result.labwareId,
|
|
368
|
+
engine_client=self._engine_client,
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
self._labware_cores_by_id[labware_core.labware_id] = labware_core
|
|
372
|
+
return labware_core
|
|
373
|
+
|
|
321
374
|
def move_labware(
|
|
322
375
|
self,
|
|
323
376
|
labware_core: LabwareCore,
|
|
@@ -422,6 +475,8 @@ class ProtocolCore(
|
|
|
422
475
|
raise InvalidModuleLocationError(deck_slot, model.name)
|
|
423
476
|
|
|
424
477
|
robot_type = self._engine_client.state.config.robot_type
|
|
478
|
+
# todo(mm, 2024-12-03): This might be possible to remove:
|
|
479
|
+
# Protocol Engine will normalize the deck slot itself.
|
|
425
480
|
normalized_deck_slot = deck_slot.to_equivalent_for_robot_type(robot_type)
|
|
426
481
|
|
|
427
482
|
result = self._engine_client.execute_command_without_recovery(
|
|
@@ -502,6 +557,12 @@ class ProtocolCore(
|
|
|
502
557
|
load_module_result=load_module_result, model=model
|
|
503
558
|
)
|
|
504
559
|
|
|
560
|
+
def load_robot(self) -> RobotCore:
|
|
561
|
+
"""Load a robot core into the RobotContext."""
|
|
562
|
+
return RobotCore(
|
|
563
|
+
engine_client=self._engine_client, sync_hardware_api=self._sync_hardware
|
|
564
|
+
)
|
|
565
|
+
|
|
505
566
|
def load_instrument(
|
|
506
567
|
self,
|
|
507
568
|
instrument_name: PipetteNameType,
|
|
@@ -632,6 +693,72 @@ class ProtocolCore(
|
|
|
632
693
|
self._last_location = location
|
|
633
694
|
self._last_mount = mount
|
|
634
695
|
|
|
696
|
+
def load_lid_stack(
|
|
697
|
+
self,
|
|
698
|
+
load_name: str,
|
|
699
|
+
location: Union[DeckSlotName, StagingSlotName, LabwareCore],
|
|
700
|
+
quantity: int,
|
|
701
|
+
namespace: Optional[str],
|
|
702
|
+
version: Optional[int],
|
|
703
|
+
) -> LabwareCore:
|
|
704
|
+
"""Load a Stack of Lids to a given location, creating a Lid Stack."""
|
|
705
|
+
if quantity < 1:
|
|
706
|
+
raise ValueError(
|
|
707
|
+
"When loading a lid stack quantity cannot be less than one."
|
|
708
|
+
)
|
|
709
|
+
if isinstance(location, DeckSlotName) or isinstance(location, StagingSlotName):
|
|
710
|
+
load_location = self._convert_labware_location(location=location)
|
|
711
|
+
else:
|
|
712
|
+
if isinstance(location, LabwareCore):
|
|
713
|
+
load_location = self._convert_labware_location(location=location)
|
|
714
|
+
else:
|
|
715
|
+
raise ValueError(
|
|
716
|
+
"Expected type of Labware Location for lid stack must be Labware, not Legacy Labware or Well."
|
|
717
|
+
)
|
|
718
|
+
|
|
719
|
+
custom_labware_params = (
|
|
720
|
+
self._engine_client.state.labware.find_custom_labware_load_params()
|
|
721
|
+
)
|
|
722
|
+
namespace, version = load_labware_params.resolve(
|
|
723
|
+
load_name, namespace, version, custom_labware_params
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
load_result = self._engine_client.execute_command_without_recovery(
|
|
727
|
+
cmd.LoadLidStackParams(
|
|
728
|
+
loadName=load_name,
|
|
729
|
+
location=load_location,
|
|
730
|
+
namespace=namespace,
|
|
731
|
+
version=version,
|
|
732
|
+
quantity=quantity,
|
|
733
|
+
)
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
# FIXME(CHB, 2024-12-04) just like load labware and load adapter we have a validating after loading the object issue
|
|
737
|
+
validation.ensure_definition_is_lid(load_result.definition)
|
|
738
|
+
|
|
739
|
+
deck_conflict.check(
|
|
740
|
+
engine_state=self._engine_client.state,
|
|
741
|
+
new_labware_id=load_result.stackLabwareId,
|
|
742
|
+
existing_disposal_locations=self._disposal_locations,
|
|
743
|
+
# TODO (spp, 2023-11-27): We've been using IDs from _labware_cores_by_id
|
|
744
|
+
# and _module_cores_by_id instead of getting the lists directly from engine
|
|
745
|
+
# because of the chance of engine carrying labware IDs from LPC too.
|
|
746
|
+
# But with https://github.com/Opentrons/opentrons/pull/13943,
|
|
747
|
+
# & LPC in maintenance runs, we can now rely on engine state for these IDs too.
|
|
748
|
+
# Wrapping .keys() in list() is just to make Decoy verification easier.
|
|
749
|
+
existing_labware_ids=list(self._labware_cores_by_id.keys()),
|
|
750
|
+
existing_module_ids=list(self._module_cores_by_id.keys()),
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
labware_core = LabwareCore(
|
|
754
|
+
labware_id=load_result.stackLabwareId,
|
|
755
|
+
engine_client=self._engine_client,
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
self._labware_cores_by_id[labware_core.labware_id] = labware_core
|
|
759
|
+
|
|
760
|
+
return labware_core
|
|
761
|
+
|
|
635
762
|
def get_deck_definition(self) -> DeckDefinitionV5:
|
|
636
763
|
"""Get the geometry definition of the robot's deck."""
|
|
637
764
|
return self._engine_client.state.labware.get_deck_definition()
|
|
@@ -725,9 +852,7 @@ class ProtocolCore(
|
|
|
725
852
|
_id=liquid.id,
|
|
726
853
|
name=liquid.displayName,
|
|
727
854
|
description=liquid.description,
|
|
728
|
-
display_color=(
|
|
729
|
-
liquid.displayColor.__root__ if liquid.displayColor else None
|
|
730
|
-
),
|
|
855
|
+
display_color=(liquid.displayColor.root if liquid.displayColor else None),
|
|
731
856
|
)
|
|
732
857
|
|
|
733
858
|
def define_liquid_class(self, name: str) -> LiquidClass:
|