opentrons 8.2.0a3__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 +40 -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 +4 -2
- 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 +56 -71
- 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.0a3.dist-info → opentrons-8.3.0.dist-info}/METADATA +16 -15
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/RECORD +238 -208
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/WHEEL +1 -1
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/LICENSE +0 -0
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
"""Utilities for calculating motion correctly."""
|
|
2
|
+
from logging import getLogger
|
|
3
|
+
|
|
2
4
|
from functools import lru_cache
|
|
3
5
|
from typing import Callable, Dict, Union, Optional, cast
|
|
4
6
|
from collections import OrderedDict
|
|
@@ -11,6 +13,7 @@ from opentrons.util import linal
|
|
|
11
13
|
|
|
12
14
|
from .types import Axis, OT3Mount
|
|
13
15
|
|
|
16
|
+
log = getLogger(__name__)
|
|
14
17
|
|
|
15
18
|
# TODO: The offset_for_mount function should be defined with an overload
|
|
16
19
|
# set, as with other functions in this module. Unfortunately, mypy < 0.920
|
|
@@ -36,6 +39,19 @@ from .types import Axis, OT3Mount
|
|
|
36
39
|
# ) -> Point:
|
|
37
40
|
# ...
|
|
38
41
|
|
|
42
|
+
EMPTY_ORDERED_DICT = OrderedDict(
|
|
43
|
+
(
|
|
44
|
+
(Axis.X, 0.0),
|
|
45
|
+
(Axis.Y, 0.0),
|
|
46
|
+
(Axis.Z_L, 0.0),
|
|
47
|
+
(Axis.Z_R, 0.0),
|
|
48
|
+
(Axis.Z_G, 0.0),
|
|
49
|
+
(Axis.P_L, 0.0),
|
|
50
|
+
(Axis.P_R, 0.0),
|
|
51
|
+
(Axis.Q, 0.0),
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
|
|
39
55
|
|
|
40
56
|
@lru_cache(4)
|
|
41
57
|
def offset_for_mount(
|
|
@@ -68,6 +84,7 @@ def target_position_from_absolute(
|
|
|
68
84
|
)
|
|
69
85
|
primary_cp = get_critical_point(mount)
|
|
70
86
|
primary_z = Axis.by_mount(mount)
|
|
87
|
+
|
|
71
88
|
target_position = OrderedDict(
|
|
72
89
|
(
|
|
73
90
|
(Axis.X, abs_position.x - offset.x - primary_cp.x),
|
|
@@ -97,6 +114,57 @@ def target_position_from_relative(
|
|
|
97
114
|
return target_position
|
|
98
115
|
|
|
99
116
|
|
|
117
|
+
def target_axis_map_from_absolute(
|
|
118
|
+
primary_mount: Union[OT3Mount, Mount],
|
|
119
|
+
axis_map: Dict[Axis, float],
|
|
120
|
+
get_critical_point: Callable[[Union[Mount, OT3Mount]], Point],
|
|
121
|
+
left_mount_offset: Point,
|
|
122
|
+
right_mount_offset: Point,
|
|
123
|
+
gripper_mount_offset: Optional[Point] = None,
|
|
124
|
+
) -> "OrderedDict[Axis, float]":
|
|
125
|
+
"""Create an absolute target position for all specified machine axes."""
|
|
126
|
+
keys_for_target_position = list(axis_map.keys())
|
|
127
|
+
|
|
128
|
+
offset = offset_for_mount(
|
|
129
|
+
primary_mount, left_mount_offset, right_mount_offset, gripper_mount_offset
|
|
130
|
+
)
|
|
131
|
+
primary_cp = get_critical_point(primary_mount)
|
|
132
|
+
primary_z = Axis.by_mount(primary_mount)
|
|
133
|
+
target_position = OrderedDict()
|
|
134
|
+
|
|
135
|
+
if Axis.X in keys_for_target_position:
|
|
136
|
+
target_position[Axis.X] = axis_map[Axis.X] - offset.x - primary_cp.x
|
|
137
|
+
if Axis.Y in keys_for_target_position:
|
|
138
|
+
target_position[Axis.Y] = axis_map[Axis.Y] - offset.y - primary_cp.y
|
|
139
|
+
if primary_z in keys_for_target_position:
|
|
140
|
+
# Since this function is intended to be used in conjunction with `API.move_axes`
|
|
141
|
+
# we must leave out the carriage offset subtraction from the target position as
|
|
142
|
+
# `move_axes` already does this calculation.
|
|
143
|
+
target_position[primary_z] = axis_map[primary_z] - primary_cp.z
|
|
144
|
+
|
|
145
|
+
target_position.update(
|
|
146
|
+
{ax: val for ax, val in axis_map.items() if ax not in Axis.gantry_axes()}
|
|
147
|
+
)
|
|
148
|
+
return target_position
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def target_axis_map_from_relative(
|
|
152
|
+
axis_map: Dict[Axis, float],
|
|
153
|
+
current_position: Dict[Axis, float],
|
|
154
|
+
) -> "OrderedDict[Axis, float]":
|
|
155
|
+
"""Create a target position for all specified machine axes."""
|
|
156
|
+
target_position = OrderedDict(
|
|
157
|
+
(
|
|
158
|
+
(ax, current_position[ax] + axis_map[ax])
|
|
159
|
+
for ax in EMPTY_ORDERED_DICT.keys()
|
|
160
|
+
if ax in axis_map.keys()
|
|
161
|
+
)
|
|
162
|
+
)
|
|
163
|
+
log.info(f"Current position {current_position} and axis map delta {axis_map}")
|
|
164
|
+
log.info(f"Relative move target {target_position}")
|
|
165
|
+
return target_position
|
|
166
|
+
|
|
167
|
+
|
|
100
168
|
def target_position_from_plunger(
|
|
101
169
|
mount: Union[Mount, OT3Mount],
|
|
102
170
|
delta: float,
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from typing import Dict, List, Optional, Any, Sequence, Iterator, Tuple, cast
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from collections import OrderedDict
|
|
4
|
-
from enum import Enum
|
|
5
4
|
from itertools import chain
|
|
6
5
|
|
|
7
6
|
from opentrons.hardware_control.types import CriticalPoint
|
|
8
|
-
from opentrons.types import
|
|
7
|
+
from opentrons.types import (
|
|
8
|
+
Point,
|
|
9
|
+
NozzleConfigurationType,
|
|
10
|
+
)
|
|
9
11
|
from opentrons_shared_data.pipette.pipette_definition import (
|
|
10
12
|
PipetteGeometryDefinition,
|
|
11
13
|
PipetteRowDefinition,
|
|
@@ -41,43 +43,6 @@ def _row_col_indices_for_nozzle(
|
|
|
41
43
|
)
|
|
42
44
|
|
|
43
45
|
|
|
44
|
-
class NozzleConfigurationType(Enum):
|
|
45
|
-
"""
|
|
46
|
-
Nozzle Configuration Type.
|
|
47
|
-
|
|
48
|
-
Represents the current nozzle
|
|
49
|
-
configuration stored in NozzleMap
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
COLUMN = "COLUMN"
|
|
53
|
-
ROW = "ROW"
|
|
54
|
-
SINGLE = "SINGLE"
|
|
55
|
-
FULL = "FULL"
|
|
56
|
-
SUBRECT = "SUBRECT"
|
|
57
|
-
|
|
58
|
-
@classmethod
|
|
59
|
-
def determine_nozzle_configuration(
|
|
60
|
-
cls,
|
|
61
|
-
physical_rows: "OrderedDict[str, List[str]]",
|
|
62
|
-
current_rows: "OrderedDict[str, List[str]]",
|
|
63
|
-
physical_cols: "OrderedDict[str, List[str]]",
|
|
64
|
-
current_cols: "OrderedDict[str, List[str]]",
|
|
65
|
-
) -> "NozzleConfigurationType":
|
|
66
|
-
"""
|
|
67
|
-
Determine the nozzle configuration based on the starting and
|
|
68
|
-
ending nozzle.
|
|
69
|
-
"""
|
|
70
|
-
if physical_rows == current_rows and physical_cols == current_cols:
|
|
71
|
-
return NozzleConfigurationType.FULL
|
|
72
|
-
if len(current_rows) == 1 and len(current_cols) == 1:
|
|
73
|
-
return NozzleConfigurationType.SINGLE
|
|
74
|
-
if len(current_rows) == 1:
|
|
75
|
-
return NozzleConfigurationType.ROW
|
|
76
|
-
if len(current_cols) == 1:
|
|
77
|
-
return NozzleConfigurationType.COLUMN
|
|
78
|
-
return NozzleConfigurationType.SUBRECT
|
|
79
|
-
|
|
80
|
-
|
|
81
46
|
@dataclass
|
|
82
47
|
class NozzleMap:
|
|
83
48
|
"""
|
|
@@ -113,6 +78,28 @@ class NozzleMap:
|
|
|
113
78
|
full_instrument_rows: Dict[str, List[str]]
|
|
114
79
|
#: A map of all the rows of an instrument
|
|
115
80
|
|
|
81
|
+
@classmethod
|
|
82
|
+
def determine_nozzle_configuration(
|
|
83
|
+
cls,
|
|
84
|
+
physical_rows: "OrderedDict[str, List[str]]",
|
|
85
|
+
current_rows: "OrderedDict[str, List[str]]",
|
|
86
|
+
physical_cols: "OrderedDict[str, List[str]]",
|
|
87
|
+
current_cols: "OrderedDict[str, List[str]]",
|
|
88
|
+
) -> "NozzleConfigurationType":
|
|
89
|
+
"""
|
|
90
|
+
Determine the nozzle configuration based on the starting and
|
|
91
|
+
ending nozzle.
|
|
92
|
+
"""
|
|
93
|
+
if physical_rows == current_rows and physical_cols == current_cols:
|
|
94
|
+
return NozzleConfigurationType.FULL
|
|
95
|
+
if len(current_rows) == 1 and len(current_cols) == 1:
|
|
96
|
+
return NozzleConfigurationType.SINGLE
|
|
97
|
+
if len(current_rows) == 1:
|
|
98
|
+
return NozzleConfigurationType.ROW
|
|
99
|
+
if len(current_cols) == 1:
|
|
100
|
+
return NozzleConfigurationType.COLUMN
|
|
101
|
+
return NozzleConfigurationType.SUBRECT
|
|
102
|
+
|
|
116
103
|
def __str__(self) -> str:
|
|
117
104
|
return f"back_left_nozzle: {self.back_left} front_right_nozzle: {self.front_right} configuration: {self.configuration}"
|
|
118
105
|
|
|
@@ -216,6 +203,16 @@ class NozzleMap:
|
|
|
216
203
|
"""The total number of active nozzles in the configuration, and thus the number of tips that will be picked up."""
|
|
217
204
|
return len(self.map_store)
|
|
218
205
|
|
|
206
|
+
@property
|
|
207
|
+
def physical_nozzle_count(self) -> int:
|
|
208
|
+
"""The number of physical nozzles, regardless of configuration."""
|
|
209
|
+
return len(self.full_instrument_map_store)
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def active_nozzles(self) -> list[str]:
|
|
213
|
+
"""An unstructured list of all nozzles active in the configuration."""
|
|
214
|
+
return list(self.map_store.keys())
|
|
215
|
+
|
|
219
216
|
@classmethod
|
|
220
217
|
def build( # noqa: C901
|
|
221
218
|
cls,
|
|
@@ -274,7 +271,7 @@ class NozzleMap:
|
|
|
274
271
|
)
|
|
275
272
|
|
|
276
273
|
if (
|
|
277
|
-
|
|
274
|
+
cls.determine_nozzle_configuration(
|
|
278
275
|
physical_rows, rows, physical_columns, columns
|
|
279
276
|
)
|
|
280
277
|
!= NozzleConfigurationType.FULL
|
|
@@ -289,6 +286,7 @@ class NozzleMap:
|
|
|
289
286
|
if valid_nozzle_maps.maps[map_key] == list(map_store.keys()):
|
|
290
287
|
validated_map_key = map_key
|
|
291
288
|
break
|
|
289
|
+
|
|
292
290
|
if validated_map_key is None:
|
|
293
291
|
raise IncompatibleNozzleConfiguration(
|
|
294
292
|
"Attempted Nozzle Configuration does not match any approved map layout for the current pipette."
|
|
@@ -302,7 +300,7 @@ class NozzleMap:
|
|
|
302
300
|
full_instrument_map_store=physical_nozzles,
|
|
303
301
|
full_instrument_rows=physical_rows,
|
|
304
302
|
columns=columns,
|
|
305
|
-
configuration=
|
|
303
|
+
configuration=cls.determine_nozzle_configuration(
|
|
306
304
|
physical_rows, rows, physical_columns, columns
|
|
307
305
|
),
|
|
308
306
|
)
|
|
@@ -968,7 +968,7 @@ def load_attitude_matrix(to_default: bool = True) -> DeckCalibration:
|
|
|
968
968
|
return DeckCalibration(
|
|
969
969
|
attitude=apply_machine_transform(calibration_data.attitude),
|
|
970
970
|
source=calibration_data.source,
|
|
971
|
-
status=types.CalibrationStatus(**calibration_data.status.
|
|
971
|
+
status=types.CalibrationStatus(**calibration_data.status.model_dump()),
|
|
972
972
|
belt_attitude=calibration_data.attitude,
|
|
973
973
|
last_modified=calibration_data.lastModified,
|
|
974
974
|
pipette_calibrated_with=calibration_data.pipetteCalibratedWith,
|
|
@@ -32,6 +32,7 @@ from opentrons_shared_data.pipette.types import (
|
|
|
32
32
|
)
|
|
33
33
|
from opentrons_shared_data.pipette import (
|
|
34
34
|
pipette_load_name_conversions as pipette_load_name,
|
|
35
|
+
pipette_definition,
|
|
35
36
|
)
|
|
36
37
|
from opentrons_shared_data.robot.types import RobotType
|
|
37
38
|
|
|
@@ -45,7 +46,6 @@ from opentrons.config.types import (
|
|
|
45
46
|
LiquidProbeSettings,
|
|
46
47
|
)
|
|
47
48
|
from opentrons.drivers.rpi_drivers.types import USBPort, PortGroup
|
|
48
|
-
from opentrons.hardware_control.nozzle_manager import NozzleConfigurationType
|
|
49
49
|
from opentrons_shared_data.errors.exceptions import (
|
|
50
50
|
EnumeratedError,
|
|
51
51
|
PythonException,
|
|
@@ -98,6 +98,7 @@ from .types import (
|
|
|
98
98
|
EstopState,
|
|
99
99
|
HardwareFeatureFlags,
|
|
100
100
|
FailedTipStateCheck,
|
|
101
|
+
PipetteSensorResponseQueue,
|
|
101
102
|
)
|
|
102
103
|
from .errors import (
|
|
103
104
|
UpdateOngoingError,
|
|
@@ -143,8 +144,6 @@ from .backends.types import HWStopCondition
|
|
|
143
144
|
from .backends.flex_protocol import FlexBackend
|
|
144
145
|
from .backends.ot3simulator import OT3Simulator
|
|
145
146
|
from .backends.errors import SubsystemUpdating
|
|
146
|
-
from opentrons_hardware.firmware_bindings.constants import SensorId
|
|
147
|
-
from opentrons_hardware.sensors.types import SensorDataType
|
|
148
147
|
|
|
149
148
|
mod_log = logging.getLogger(__name__)
|
|
150
149
|
|
|
@@ -299,8 +298,11 @@ class OT3API(
|
|
|
299
298
|
async def set_system_constraints_for_plunger_acceleration(
|
|
300
299
|
self, mount: OT3Mount, acceleration: float
|
|
301
300
|
) -> None:
|
|
301
|
+
high_speed_pipette = self._pipette_handler.get_pipette(
|
|
302
|
+
mount
|
|
303
|
+
).is_high_speed_pipette()
|
|
302
304
|
self._backend.update_constraints_for_plunger_acceleration(
|
|
303
|
-
mount, acceleration, self._gantry_load
|
|
305
|
+
mount, acceleration, self._gantry_load, high_speed_pipette
|
|
304
306
|
)
|
|
305
307
|
|
|
306
308
|
@contextlib.asynccontextmanager
|
|
@@ -353,7 +355,9 @@ class OT3API(
|
|
|
353
355
|
def _reset_last_mount(self) -> None:
|
|
354
356
|
self._last_moved_mount = None
|
|
355
357
|
|
|
356
|
-
def
|
|
358
|
+
def get_deck_from_machine(
|
|
359
|
+
self, machine_pos: Dict[Axis, float]
|
|
360
|
+
) -> Dict[Axis, float]:
|
|
357
361
|
return deck_from_machine(
|
|
358
362
|
machine_pos=machine_pos,
|
|
359
363
|
attitude=self._robot_calibration.deck_calibration.attitude,
|
|
@@ -633,10 +637,31 @@ class OT3API(
|
|
|
633
637
|
self._feature_flags.use_old_aspiration_functions,
|
|
634
638
|
)
|
|
635
639
|
self._pipette_handler.hardware_instruments[mount] = p
|
|
640
|
+
|
|
641
|
+
if config is not None:
|
|
642
|
+
self._set_pressure_sensor_available(mount, instrument_config=config)
|
|
643
|
+
|
|
636
644
|
# TODO (lc 12-5-2022) Properly support backwards compatibility
|
|
637
645
|
# when applicable
|
|
638
646
|
return skipped
|
|
639
647
|
|
|
648
|
+
def get_pressure_sensor_available(self, mount: OT3Mount) -> bool:
|
|
649
|
+
pip_axis = Axis.of_main_tool_actuator(mount)
|
|
650
|
+
return self._backend.get_pressure_sensor_available(pip_axis)
|
|
651
|
+
|
|
652
|
+
def _set_pressure_sensor_available(
|
|
653
|
+
self,
|
|
654
|
+
mount: OT3Mount,
|
|
655
|
+
instrument_config: pipette_definition.PipetteConfigurations,
|
|
656
|
+
) -> None:
|
|
657
|
+
pressure_sensor_available = (
|
|
658
|
+
"pressure" in instrument_config.available_sensors.sensors
|
|
659
|
+
)
|
|
660
|
+
pip_axis = Axis.of_main_tool_actuator(mount)
|
|
661
|
+
self._backend.set_pressure_sensor_available(
|
|
662
|
+
pipette_axis=pip_axis, available=pressure_sensor_available
|
|
663
|
+
)
|
|
664
|
+
|
|
640
665
|
async def cache_gripper(self, instrument_data: AttachedGripper) -> bool:
|
|
641
666
|
"""Set up gripper based on scanned information."""
|
|
642
667
|
grip_cal = load_gripper_calibration_offset(instrument_data.get("id"))
|
|
@@ -775,6 +800,8 @@ class OT3API(
|
|
|
775
800
|
"""
|
|
776
801
|
Function to update motor estimation for a set of axes
|
|
777
802
|
"""
|
|
803
|
+
await self._backend.update_motor_status()
|
|
804
|
+
|
|
778
805
|
if axes is None:
|
|
779
806
|
axes = [ax for ax in Axis]
|
|
780
807
|
|
|
@@ -943,8 +970,8 @@ class OT3API(
|
|
|
943
970
|
):
|
|
944
971
|
# move toward home until a safe distance
|
|
945
972
|
await self._backend.tip_action(
|
|
946
|
-
origin=
|
|
947
|
-
targets=[(
|
|
973
|
+
origin=current_pos_float,
|
|
974
|
+
targets=[(self._config.safe_home_distance, 400)],
|
|
948
975
|
)
|
|
949
976
|
|
|
950
977
|
# update current position
|
|
@@ -1021,14 +1048,14 @@ class OT3API(
|
|
|
1021
1048
|
|
|
1022
1049
|
async def _cache_current_position(self) -> Dict[Axis, float]:
|
|
1023
1050
|
"""Cache current position from backend and return in absolute deck coords."""
|
|
1024
|
-
self._current_position = self.
|
|
1051
|
+
self._current_position = self.get_deck_from_machine(
|
|
1025
1052
|
await self._backend.update_position()
|
|
1026
1053
|
)
|
|
1027
1054
|
return self._current_position
|
|
1028
1055
|
|
|
1029
1056
|
async def _cache_encoder_position(self) -> Dict[Axis, float]:
|
|
1030
1057
|
"""Cache encoder position from backend and return in absolute deck coords."""
|
|
1031
|
-
self._encoder_position = self.
|
|
1058
|
+
self._encoder_position = self.get_deck_from_machine(
|
|
1032
1059
|
await self._backend.update_encoder_position()
|
|
1033
1060
|
)
|
|
1034
1061
|
if self.has_gripper():
|
|
@@ -1162,7 +1189,7 @@ class OT3API(
|
|
|
1162
1189
|
speed: Optional[float] = None,
|
|
1163
1190
|
critical_point: Optional[CriticalPoint] = None,
|
|
1164
1191
|
max_speeds: Union[None, Dict[Axis, float], OT3AxisMap[float]] = None,
|
|
1165
|
-
|
|
1192
|
+
expect_stalls: bool = False,
|
|
1166
1193
|
) -> None:
|
|
1167
1194
|
"""Move the critical point of the specified mount to a location
|
|
1168
1195
|
relative to the deck, at the specified speed."""
|
|
@@ -1206,7 +1233,7 @@ class OT3API(
|
|
|
1206
1233
|
target_position,
|
|
1207
1234
|
speed=speed,
|
|
1208
1235
|
max_speeds=checked_max,
|
|
1209
|
-
expect_stalls=
|
|
1236
|
+
expect_stalls=expect_stalls,
|
|
1210
1237
|
)
|
|
1211
1238
|
|
|
1212
1239
|
async def move_axes( # noqa: C901
|
|
@@ -1214,6 +1241,7 @@ class OT3API(
|
|
|
1214
1241
|
position: Mapping[Axis, float],
|
|
1215
1242
|
speed: Optional[float] = None,
|
|
1216
1243
|
max_speeds: Optional[Dict[Axis, float]] = None,
|
|
1244
|
+
expect_stalls: bool = False,
|
|
1217
1245
|
) -> None:
|
|
1218
1246
|
"""Moves the effectors of the specified axis to the specified position.
|
|
1219
1247
|
The effector of the x,y axis is the center of the carriage.
|
|
@@ -1228,7 +1256,9 @@ class OT3API(
|
|
|
1228
1256
|
message=f"{axis} is not present", detail={"axis": str(axis)}
|
|
1229
1257
|
)
|
|
1230
1258
|
|
|
1259
|
+
self._log.info(f"Attempting to move {position} with speed {speed}.")
|
|
1231
1260
|
if not self._backend.check_encoder_status(list(position.keys())):
|
|
1261
|
+
self._log.info("Calling home in move_axes")
|
|
1232
1262
|
await self.home()
|
|
1233
1263
|
self._assert_motor_ok(list(position.keys()))
|
|
1234
1264
|
|
|
@@ -1267,7 +1297,11 @@ class OT3API(
|
|
|
1267
1297
|
if axis not in absolute_positions:
|
|
1268
1298
|
absolute_positions[axis] = position_value
|
|
1269
1299
|
|
|
1270
|
-
await self._move(
|
|
1300
|
+
await self._move(
|
|
1301
|
+
target_position=absolute_positions,
|
|
1302
|
+
speed=speed,
|
|
1303
|
+
expect_stalls=expect_stalls,
|
|
1304
|
+
)
|
|
1271
1305
|
|
|
1272
1306
|
async def move_rel(
|
|
1273
1307
|
self,
|
|
@@ -1277,7 +1311,7 @@ class OT3API(
|
|
|
1277
1311
|
max_speeds: Union[None, Dict[Axis, float], OT3AxisMap[float]] = None,
|
|
1278
1312
|
check_bounds: MotionChecks = MotionChecks.NONE,
|
|
1279
1313
|
fail_on_not_homed: bool = False,
|
|
1280
|
-
|
|
1314
|
+
expect_stalls: bool = False,
|
|
1281
1315
|
) -> None:
|
|
1282
1316
|
"""Move the critical point of the specified mount by a specified
|
|
1283
1317
|
displacement in a specified direction, at the specified speed."""
|
|
@@ -1319,7 +1353,7 @@ class OT3API(
|
|
|
1319
1353
|
speed=speed,
|
|
1320
1354
|
max_speeds=checked_max,
|
|
1321
1355
|
check_bounds=check_bounds,
|
|
1322
|
-
expect_stalls=
|
|
1356
|
+
expect_stalls=expect_stalls,
|
|
1323
1357
|
)
|
|
1324
1358
|
|
|
1325
1359
|
async def _cache_and_maybe_retract_mount(self, mount: OT3Mount) -> None:
|
|
@@ -1439,6 +1473,10 @@ class OT3API(
|
|
|
1439
1473
|
check_motion_bounds(to_check, target_position, bounds, check_bounds)
|
|
1440
1474
|
self._log.info(f"Move: deck {target_position} becomes machine {machine_pos}")
|
|
1441
1475
|
origin = await self._backend.update_position()
|
|
1476
|
+
|
|
1477
|
+
if self._gantry_load == GantryLoad.HIGH_THROUGHPUT:
|
|
1478
|
+
origin[Axis.Q] = self._backend.gear_motor_position or 0.0
|
|
1479
|
+
|
|
1442
1480
|
async with contextlib.AsyncExitStack() as stack:
|
|
1443
1481
|
if acquire_lock:
|
|
1444
1482
|
await stack.enter_async_context(self._motion_lock)
|
|
@@ -1640,7 +1678,12 @@ class OT3API(
|
|
|
1640
1678
|
await self._backend.disengage_axes(which)
|
|
1641
1679
|
|
|
1642
1680
|
async def engage_axes(self, which: List[Axis]) -> None:
|
|
1643
|
-
await self._backend.engage_axes(
|
|
1681
|
+
await self._backend.engage_axes(
|
|
1682
|
+
[axis for axis in which if self._backend.axis_is_present(axis)]
|
|
1683
|
+
)
|
|
1684
|
+
|
|
1685
|
+
def axis_is_present(self, axis: Axis) -> bool:
|
|
1686
|
+
return self._backend.axis_is_present(axis)
|
|
1644
1687
|
|
|
1645
1688
|
async def get_limit_switches(self) -> Dict[Axis, bool]:
|
|
1646
1689
|
res = await self._backend.get_limit_switches()
|
|
@@ -1826,7 +1869,7 @@ class OT3API(
|
|
|
1826
1869
|
if (
|
|
1827
1870
|
self.gantry_load == GantryLoad.HIGH_THROUGHPUT
|
|
1828
1871
|
and instrument.nozzle_manager.current_configuration.configuration
|
|
1829
|
-
== NozzleConfigurationType.FULL
|
|
1872
|
+
== top_types.NozzleConfigurationType.FULL
|
|
1830
1873
|
):
|
|
1831
1874
|
spec = self._pipette_handler.plan_ht_pick_up_tip(
|
|
1832
1875
|
instrument.nozzle_manager.current_configuration.tip_count
|
|
@@ -2156,8 +2199,8 @@ class OT3API(
|
|
|
2156
2199
|
# only move tip motors if they are not already below the sensor
|
|
2157
2200
|
if tip_motor_pos_float < tip_presence_check_target:
|
|
2158
2201
|
await self._backend.tip_action(
|
|
2159
|
-
origin=
|
|
2160
|
-
targets=[(
|
|
2202
|
+
origin=tip_motor_pos_float,
|
|
2203
|
+
targets=[(tip_presence_check_target, 400)],
|
|
2161
2204
|
)
|
|
2162
2205
|
try:
|
|
2163
2206
|
yield
|
|
@@ -2228,11 +2271,11 @@ class OT3API(
|
|
|
2228
2271
|
gear_origin_float = self._backend.gear_motor_position or 0.0
|
|
2229
2272
|
|
|
2230
2273
|
move_targets = [
|
|
2231
|
-
(
|
|
2274
|
+
(move_segment.distance, move_segment.speed or 400)
|
|
2232
2275
|
for move_segment in pipette_spec
|
|
2233
2276
|
]
|
|
2234
2277
|
await self._backend.tip_action(
|
|
2235
|
-
origin=
|
|
2278
|
+
origin=gear_origin_float, targets=move_targets
|
|
2236
2279
|
)
|
|
2237
2280
|
await self.home_gear_motors()
|
|
2238
2281
|
|
|
@@ -2282,11 +2325,16 @@ class OT3API(
|
|
|
2282
2325
|
instrument.working_volume = tip_volume
|
|
2283
2326
|
|
|
2284
2327
|
async def tip_drop_moves(
|
|
2285
|
-
self,
|
|
2328
|
+
self,
|
|
2329
|
+
mount: Union[top_types.Mount, OT3Mount],
|
|
2330
|
+
home_after: bool = False,
|
|
2331
|
+
ignore_plunger: bool = False,
|
|
2286
2332
|
) -> None:
|
|
2287
2333
|
realmount = OT3Mount.from_mount(mount)
|
|
2288
|
-
|
|
2289
|
-
|
|
2334
|
+
if ignore_plunger is False:
|
|
2335
|
+
await self._move_to_plunger_bottom(
|
|
2336
|
+
realmount, rate=1.0, check_current_vol=False
|
|
2337
|
+
)
|
|
2290
2338
|
|
|
2291
2339
|
if self.gantry_load == GantryLoad.HIGH_THROUGHPUT:
|
|
2292
2340
|
spec = self._pipette_handler.plan_ht_drop_tip()
|
|
@@ -2557,7 +2605,7 @@ class OT3API(
|
|
|
2557
2605
|
mount: Union[top_types.Mount, OT3Mount],
|
|
2558
2606
|
critical_point: Optional[CriticalPoint] = None,
|
|
2559
2607
|
) -> float:
|
|
2560
|
-
carriage_pos = self.
|
|
2608
|
+
carriage_pos = self.get_deck_from_machine(self._backend.home_position())
|
|
2561
2609
|
pos_at_home = self._effector_pos_from_carriage_pos(
|
|
2562
2610
|
OT3Mount.from_mount(mount), carriage_pos, critical_point
|
|
2563
2611
|
)
|
|
@@ -2639,10 +2687,9 @@ class OT3API(
|
|
|
2639
2687
|
probe_settings: LiquidProbeSettings,
|
|
2640
2688
|
probe: InstrumentProbeType,
|
|
2641
2689
|
p_travel: float,
|
|
2690
|
+
z_offset_for_plunger_prep: float,
|
|
2642
2691
|
force_both_sensors: bool = False,
|
|
2643
|
-
response_queue: Optional[
|
|
2644
|
-
asyncio.Queue[Dict[SensorId, List[SensorDataType]]]
|
|
2645
|
-
] = None,
|
|
2692
|
+
response_queue: Optional[PipetteSensorResponseQueue] = None,
|
|
2646
2693
|
) -> float:
|
|
2647
2694
|
plunger_direction = -1 if probe_settings.aspirate_while_sensing else 1
|
|
2648
2695
|
end_z = await self._backend.liquid_probe(
|
|
@@ -2653,13 +2700,14 @@ class OT3API(
|
|
|
2653
2700
|
probe_settings.sensor_threshold_pascals,
|
|
2654
2701
|
probe_settings.plunger_impulse_time,
|
|
2655
2702
|
probe_settings.samples_for_baselining,
|
|
2703
|
+
z_offset_for_plunger_prep,
|
|
2656
2704
|
probe=probe,
|
|
2657
2705
|
force_both_sensors=force_both_sensors,
|
|
2658
2706
|
response_queue=response_queue,
|
|
2659
2707
|
)
|
|
2660
2708
|
machine_pos = await self._backend.update_position()
|
|
2661
2709
|
machine_pos[Axis.by_mount(mount)] = end_z
|
|
2662
|
-
deck_end_z = self.
|
|
2710
|
+
deck_end_z = self.get_deck_from_machine(machine_pos)[Axis.by_mount(mount)]
|
|
2663
2711
|
offset = offset_for_mount(
|
|
2664
2712
|
mount,
|
|
2665
2713
|
top_types.Point(*self._config.left_mount_offset),
|
|
@@ -2676,9 +2724,7 @@ class OT3API(
|
|
|
2676
2724
|
probe_settings: Optional[LiquidProbeSettings] = None,
|
|
2677
2725
|
probe: Optional[InstrumentProbeType] = None,
|
|
2678
2726
|
force_both_sensors: bool = False,
|
|
2679
|
-
response_queue: Optional[
|
|
2680
|
-
asyncio.Queue[Dict[SensorId, List[SensorDataType]]]
|
|
2681
|
-
] = None,
|
|
2727
|
+
response_queue: Optional[PipetteSensorResponseQueue] = None,
|
|
2682
2728
|
) -> float:
|
|
2683
2729
|
"""Search for and return liquid level height.
|
|
2684
2730
|
|
|
@@ -2804,6 +2850,7 @@ class OT3API(
|
|
|
2804
2850
|
probe_settings,
|
|
2805
2851
|
checked_probe,
|
|
2806
2852
|
plunger_travel_mm + sensor_baseline_plunger_move_mm,
|
|
2853
|
+
z_offset_for_plunger_prep,
|
|
2807
2854
|
force_both_sensors,
|
|
2808
2855
|
response_queue,
|
|
2809
2856
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Dict, Optional
|
|
2
2
|
from typing_extensions import Protocol
|
|
3
3
|
|
|
4
|
-
from ..types import SubSystem, SubSystemState
|
|
4
|
+
from ..types import SubSystem, SubSystemState, Axis
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class HardwareManager(Protocol):
|
|
@@ -45,3 +45,7 @@ class HardwareManager(Protocol):
|
|
|
45
45
|
async def get_serial_number(self) -> Optional[str]:
|
|
46
46
|
"""Get the robot serial number, if provisioned. If not provisioned, will be None."""
|
|
47
47
|
...
|
|
48
|
+
|
|
49
|
+
def axis_is_present(self, axis: Axis) -> bool:
|
|
50
|
+
"""Get whether a motor axis is present on the machine."""
|
|
51
|
+
...
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
from typing_extensions import Protocol
|
|
3
3
|
|
|
4
|
+
from opentrons.types import Point
|
|
5
|
+
from opentrons.hardware_control.types import CriticalPoint
|
|
4
6
|
from .types import MountArgType, CalibrationType, ConfigType
|
|
5
7
|
|
|
6
8
|
from .instrument_configurer import InstrumentConfigurer
|
|
@@ -16,6 +18,22 @@ class LiquidHandler(
|
|
|
16
18
|
Calibratable[CalibrationType],
|
|
17
19
|
Protocol[CalibrationType, MountArgType, ConfigType],
|
|
18
20
|
):
|
|
21
|
+
def critical_point_for(
|
|
22
|
+
self,
|
|
23
|
+
mount: MountArgType,
|
|
24
|
+
cp_override: Optional[CriticalPoint] = None,
|
|
25
|
+
) -> Point:
|
|
26
|
+
"""
|
|
27
|
+
Determine the current critical point for the specified mount.
|
|
28
|
+
|
|
29
|
+
:param mount: A robot mount that the instrument is on.
|
|
30
|
+
:param cp_override: The critical point override to use.
|
|
31
|
+
|
|
32
|
+
If no critical point override is specified, the robot defaults to nozzle location `A1` or the mount critical point.
|
|
33
|
+
:return: Point.
|
|
34
|
+
"""
|
|
35
|
+
...
|
|
36
|
+
|
|
19
37
|
async def update_nozzle_configuration_for_mount(
|
|
20
38
|
self,
|
|
21
39
|
mount: MountArgType,
|
|
@@ -165,7 +183,10 @@ class LiquidHandler(
|
|
|
165
183
|
...
|
|
166
184
|
|
|
167
185
|
async def tip_drop_moves(
|
|
168
|
-
self,
|
|
186
|
+
self,
|
|
187
|
+
mount: MountArgType,
|
|
188
|
+
home_after: bool = True,
|
|
189
|
+
ignore_plunger: bool = False,
|
|
169
190
|
) -> None:
|
|
170
191
|
...
|
|
171
192
|
|
|
@@ -9,6 +9,12 @@ from .types import MountArgType
|
|
|
9
9
|
class MotionController(Protocol[MountArgType]):
|
|
10
10
|
"""Protocol specifying fundamental motion controls."""
|
|
11
11
|
|
|
12
|
+
def get_deck_from_machine(
|
|
13
|
+
self, machine_pos: Dict[Axis, float]
|
|
14
|
+
) -> Dict[Axis, float]:
|
|
15
|
+
"""Convert machine coordinates to deck coordinates."""
|
|
16
|
+
...
|
|
17
|
+
|
|
12
18
|
async def halt(self, disengage_before_stopping: bool = False) -> None:
|
|
13
19
|
"""Immediately stop motion.
|
|
14
20
|
|
|
@@ -165,6 +171,7 @@ class MotionController(Protocol[MountArgType]):
|
|
|
165
171
|
position: Mapping[Axis, float],
|
|
166
172
|
speed: Optional[float] = None,
|
|
167
173
|
max_speeds: Optional[Dict[Axis, float]] = None,
|
|
174
|
+
expect_stalls: bool = False,
|
|
168
175
|
) -> None:
|
|
169
176
|
"""Moves the effectors of the specified axis to the specified position.
|
|
170
177
|
The effector of the x,y axis is the center of the carriage.
|
|
@@ -154,7 +154,7 @@ def load_attitude_matrix() -> DeckCalibration:
|
|
|
154
154
|
return DeckCalibration(
|
|
155
155
|
attitude=calibration_data.attitude,
|
|
156
156
|
source=calibration_data.source,
|
|
157
|
-
status=types.CalibrationStatus(**calibration_data.status.
|
|
157
|
+
status=types.CalibrationStatus(**calibration_data.status.model_dump()),
|
|
158
158
|
last_modified=calibration_data.last_modified,
|
|
159
159
|
pipette_calibrated_with=calibration_data.pipette_calibrated_with,
|
|
160
160
|
tiprack=calibration_data.tiprack,
|