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.
Files changed (238) hide show
  1. opentrons/calibration_storage/deck_configuration.py +3 -3
  2. opentrons/calibration_storage/file_operators.py +3 -3
  3. opentrons/calibration_storage/helpers.py +3 -1
  4. opentrons/calibration_storage/ot2/models/v1.py +16 -29
  5. opentrons/calibration_storage/ot2/tip_length.py +7 -4
  6. opentrons/calibration_storage/ot3/models/v1.py +14 -23
  7. opentrons/cli/analyze.py +18 -6
  8. opentrons/config/defaults_ot3.py +1 -0
  9. opentrons/drivers/asyncio/communication/__init__.py +2 -0
  10. opentrons/drivers/asyncio/communication/errors.py +16 -3
  11. opentrons/drivers/asyncio/communication/serial_connection.py +24 -9
  12. opentrons/drivers/command_builder.py +2 -2
  13. opentrons/drivers/flex_stacker/__init__.py +9 -0
  14. opentrons/drivers/flex_stacker/abstract.py +89 -0
  15. opentrons/drivers/flex_stacker/driver.py +260 -0
  16. opentrons/drivers/flex_stacker/simulator.py +109 -0
  17. opentrons/drivers/flex_stacker/types.py +138 -0
  18. opentrons/drivers/heater_shaker/driver.py +18 -3
  19. opentrons/drivers/temp_deck/driver.py +13 -3
  20. opentrons/drivers/thermocycler/driver.py +17 -3
  21. opentrons/execute.py +3 -1
  22. opentrons/hardware_control/__init__.py +1 -2
  23. opentrons/hardware_control/api.py +33 -21
  24. opentrons/hardware_control/backends/flex_protocol.py +17 -7
  25. opentrons/hardware_control/backends/ot3controller.py +213 -63
  26. opentrons/hardware_control/backends/ot3simulator.py +18 -9
  27. opentrons/hardware_control/backends/ot3utils.py +43 -15
  28. opentrons/hardware_control/dev_types.py +4 -0
  29. opentrons/hardware_control/emulation/heater_shaker.py +4 -0
  30. opentrons/hardware_control/emulation/module_server/client.py +1 -1
  31. opentrons/hardware_control/emulation/module_server/server.py +5 -3
  32. opentrons/hardware_control/emulation/settings.py +3 -4
  33. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +2 -1
  34. opentrons/hardware_control/instruments/ot2/pipette.py +15 -22
  35. opentrons/hardware_control/instruments/ot2/pipette_handler.py +8 -1
  36. opentrons/hardware_control/instruments/ot3/gripper.py +2 -2
  37. opentrons/hardware_control/instruments/ot3/pipette.py +23 -22
  38. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -1
  39. opentrons/hardware_control/modules/mod_abc.py +2 -2
  40. opentrons/hardware_control/motion_utilities.py +68 -0
  41. opentrons/hardware_control/nozzle_manager.py +39 -41
  42. opentrons/hardware_control/ot3_calibration.py +1 -1
  43. opentrons/hardware_control/ot3api.py +78 -31
  44. opentrons/hardware_control/protocols/gripper_controller.py +3 -0
  45. opentrons/hardware_control/protocols/hardware_manager.py +5 -1
  46. opentrons/hardware_control/protocols/liquid_handler.py +22 -1
  47. opentrons/hardware_control/protocols/motion_controller.py +7 -0
  48. opentrons/hardware_control/robot_calibration.py +1 -1
  49. opentrons/hardware_control/types.py +61 -0
  50. opentrons/legacy_commands/commands.py +37 -0
  51. opentrons/legacy_commands/types.py +39 -0
  52. opentrons/protocol_api/__init__.py +20 -1
  53. opentrons/protocol_api/_liquid.py +24 -49
  54. opentrons/protocol_api/_liquid_properties.py +754 -0
  55. opentrons/protocol_api/_types.py +24 -0
  56. opentrons/protocol_api/core/common.py +2 -0
  57. opentrons/protocol_api/core/engine/instrument.py +191 -10
  58. opentrons/protocol_api/core/engine/labware.py +29 -7
  59. opentrons/protocol_api/core/engine/protocol.py +130 -5
  60. opentrons/protocol_api/core/engine/robot.py +139 -0
  61. opentrons/protocol_api/core/engine/well.py +4 -1
  62. opentrons/protocol_api/core/instrument.py +73 -4
  63. opentrons/protocol_api/core/labware.py +13 -4
  64. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +87 -3
  65. opentrons/protocol_api/core/legacy/legacy_labware_core.py +13 -4
  66. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +32 -1
  67. opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
  68. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +61 -3
  69. opentrons/protocol_api/core/protocol.py +34 -1
  70. opentrons/protocol_api/core/robot.py +51 -0
  71. opentrons/protocol_api/instrument_context.py +299 -44
  72. opentrons/protocol_api/labware.py +248 -9
  73. opentrons/protocol_api/module_contexts.py +21 -17
  74. opentrons/protocol_api/protocol_context.py +125 -4
  75. opentrons/protocol_api/robot_context.py +204 -32
  76. opentrons/protocol_api/validation.py +262 -3
  77. opentrons/protocol_engine/__init__.py +4 -0
  78. opentrons/protocol_engine/actions/actions.py +2 -3
  79. opentrons/protocol_engine/clients/sync_client.py +18 -0
  80. opentrons/protocol_engine/commands/__init__.py +121 -0
  81. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +1 -3
  82. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +20 -6
  83. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +1 -2
  84. opentrons/protocol_engine/commands/absorbance_reader/read.py +40 -10
  85. opentrons/protocol_engine/commands/air_gap_in_place.py +160 -0
  86. opentrons/protocol_engine/commands/aspirate.py +103 -53
  87. opentrons/protocol_engine/commands/aspirate_in_place.py +55 -51
  88. opentrons/protocol_engine/commands/blow_out.py +44 -39
  89. opentrons/protocol_engine/commands/blow_out_in_place.py +21 -32
  90. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +13 -6
  91. opentrons/protocol_engine/commands/calibration/calibrate_module.py +1 -1
  92. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +3 -3
  93. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +1 -1
  94. opentrons/protocol_engine/commands/command.py +73 -66
  95. opentrons/protocol_engine/commands/command_unions.py +140 -1
  96. opentrons/protocol_engine/commands/comment.py +1 -1
  97. opentrons/protocol_engine/commands/configure_for_volume.py +10 -3
  98. opentrons/protocol_engine/commands/configure_nozzle_layout.py +6 -4
  99. opentrons/protocol_engine/commands/custom.py +6 -12
  100. opentrons/protocol_engine/commands/dispense.py +82 -48
  101. opentrons/protocol_engine/commands/dispense_in_place.py +71 -51
  102. opentrons/protocol_engine/commands/drop_tip.py +52 -31
  103. opentrons/protocol_engine/commands/drop_tip_in_place.py +79 -8
  104. opentrons/protocol_engine/commands/evotip_dispense.py +156 -0
  105. opentrons/protocol_engine/commands/evotip_seal_pipette.py +331 -0
  106. opentrons/protocol_engine/commands/evotip_unseal_pipette.py +160 -0
  107. opentrons/protocol_engine/commands/generate_command_schema.py +4 -11
  108. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  109. opentrons/protocol_engine/commands/get_tip_presence.py +1 -1
  110. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +1 -1
  111. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +1 -1
  112. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +1 -1
  113. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +1 -1
  114. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +1 -1
  115. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +1 -1
  116. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +10 -4
  117. opentrons/protocol_engine/commands/home.py +13 -4
  118. opentrons/protocol_engine/commands/liquid_probe.py +125 -31
  119. opentrons/protocol_engine/commands/load_labware.py +33 -6
  120. opentrons/protocol_engine/commands/load_lid.py +146 -0
  121. opentrons/protocol_engine/commands/load_lid_stack.py +189 -0
  122. opentrons/protocol_engine/commands/load_liquid.py +12 -4
  123. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  124. opentrons/protocol_engine/commands/load_module.py +31 -10
  125. opentrons/protocol_engine/commands/load_pipette.py +19 -8
  126. opentrons/protocol_engine/commands/magnetic_module/disengage.py +1 -1
  127. opentrons/protocol_engine/commands/magnetic_module/engage.py +1 -1
  128. opentrons/protocol_engine/commands/move_labware.py +28 -6
  129. opentrons/protocol_engine/commands/move_relative.py +35 -25
  130. opentrons/protocol_engine/commands/move_to_addressable_area.py +40 -27
  131. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +53 -32
  132. opentrons/protocol_engine/commands/move_to_coordinates.py +36 -22
  133. opentrons/protocol_engine/commands/move_to_well.py +40 -24
  134. opentrons/protocol_engine/commands/movement_common.py +338 -0
  135. opentrons/protocol_engine/commands/pick_up_tip.py +49 -27
  136. opentrons/protocol_engine/commands/pipetting_common.py +169 -87
  137. opentrons/protocol_engine/commands/prepare_to_aspirate.py +24 -33
  138. opentrons/protocol_engine/commands/reload_labware.py +1 -1
  139. opentrons/protocol_engine/commands/retract_axis.py +1 -1
  140. opentrons/protocol_engine/commands/robot/__init__.py +69 -0
  141. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +86 -0
  142. opentrons/protocol_engine/commands/robot/common.py +18 -0
  143. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  144. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  145. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  146. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +77 -0
  147. opentrons/protocol_engine/commands/save_position.py +14 -5
  148. opentrons/protocol_engine/commands/set_rail_lights.py +1 -1
  149. opentrons/protocol_engine/commands/set_status_bar.py +1 -1
  150. opentrons/protocol_engine/commands/temperature_module/deactivate.py +1 -1
  151. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +1 -1
  152. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +10 -4
  153. opentrons/protocol_engine/commands/thermocycler/close_lid.py +1 -1
  154. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +1 -1
  155. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +1 -1
  156. opentrons/protocol_engine/commands/thermocycler/open_lid.py +1 -1
  157. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +9 -3
  158. opentrons/protocol_engine/commands/thermocycler/run_profile.py +9 -3
  159. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +11 -4
  160. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +1 -1
  161. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +1 -1
  162. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +1 -1
  163. opentrons/protocol_engine/commands/touch_tip.py +65 -16
  164. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +5 -2
  165. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +13 -4
  166. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +2 -5
  167. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +1 -1
  168. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +4 -2
  169. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +2 -5
  170. opentrons/protocol_engine/commands/verify_tip_presence.py +11 -4
  171. opentrons/protocol_engine/commands/wait_for_duration.py +10 -3
  172. opentrons/protocol_engine/commands/wait_for_resume.py +10 -3
  173. opentrons/protocol_engine/errors/__init__.py +12 -0
  174. opentrons/protocol_engine/errors/error_occurrence.py +19 -20
  175. opentrons/protocol_engine/errors/exceptions.py +76 -0
  176. opentrons/protocol_engine/execution/command_executor.py +1 -1
  177. opentrons/protocol_engine/execution/equipment.py +73 -5
  178. opentrons/protocol_engine/execution/gantry_mover.py +369 -8
  179. opentrons/protocol_engine/execution/hardware_stopper.py +7 -7
  180. opentrons/protocol_engine/execution/movement.py +27 -0
  181. opentrons/protocol_engine/execution/pipetting.py +5 -1
  182. opentrons/protocol_engine/execution/tip_handler.py +34 -15
  183. opentrons/protocol_engine/notes/notes.py +1 -1
  184. opentrons/protocol_engine/protocol_engine.py +7 -6
  185. opentrons/protocol_engine/resources/labware_data_provider.py +1 -1
  186. opentrons/protocol_engine/resources/labware_validation.py +18 -0
  187. opentrons/protocol_engine/resources/module_data_provider.py +1 -1
  188. opentrons/protocol_engine/resources/pipette_data_provider.py +26 -0
  189. opentrons/protocol_engine/slot_standardization.py +9 -9
  190. opentrons/protocol_engine/state/_move_types.py +9 -5
  191. opentrons/protocol_engine/state/_well_math.py +193 -0
  192. opentrons/protocol_engine/state/addressable_areas.py +25 -61
  193. opentrons/protocol_engine/state/command_history.py +12 -0
  194. opentrons/protocol_engine/state/commands.py +22 -14
  195. opentrons/protocol_engine/state/files.py +10 -12
  196. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  197. opentrons/protocol_engine/state/frustum_helpers.py +63 -69
  198. opentrons/protocol_engine/state/geometry.py +47 -1
  199. opentrons/protocol_engine/state/labware.py +92 -26
  200. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  201. opentrons/protocol_engine/state/liquids.py +16 -4
  202. opentrons/protocol_engine/state/modules.py +56 -71
  203. opentrons/protocol_engine/state/motion.py +6 -1
  204. opentrons/protocol_engine/state/pipettes.py +149 -58
  205. opentrons/protocol_engine/state/state.py +21 -2
  206. opentrons/protocol_engine/state/state_summary.py +4 -2
  207. opentrons/protocol_engine/state/tips.py +11 -44
  208. opentrons/protocol_engine/state/update_types.py +343 -48
  209. opentrons/protocol_engine/state/wells.py +19 -11
  210. opentrons/protocol_engine/types.py +176 -28
  211. opentrons/protocol_reader/extract_labware_definitions.py +5 -2
  212. opentrons/protocol_reader/file_format_validator.py +5 -5
  213. opentrons/protocol_runner/json_file_reader.py +9 -3
  214. opentrons/protocol_runner/json_translator.py +51 -25
  215. opentrons/protocol_runner/legacy_command_mapper.py +66 -64
  216. opentrons/protocol_runner/protocol_runner.py +35 -4
  217. opentrons/protocol_runner/python_protocol_wrappers.py +1 -1
  218. opentrons/protocol_runner/run_orchestrator.py +13 -3
  219. opentrons/protocols/advanced_control/common.py +38 -0
  220. opentrons/protocols/advanced_control/mix.py +1 -1
  221. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  222. opentrons/protocols/advanced_control/transfers/common.py +56 -0
  223. opentrons/protocols/advanced_control/{transfers.py → transfers/transfer.py} +10 -85
  224. opentrons/protocols/api_support/definitions.py +1 -1
  225. opentrons/protocols/api_support/instrument.py +1 -1
  226. opentrons/protocols/api_support/util.py +10 -0
  227. opentrons/protocols/labware.py +70 -8
  228. opentrons/protocols/models/json_protocol.py +5 -9
  229. opentrons/simulate.py +3 -1
  230. opentrons/types.py +162 -2
  231. opentrons/util/entrypoint_util.py +2 -5
  232. opentrons/util/logging_config.py +1 -1
  233. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/METADATA +16 -15
  234. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/RECORD +238 -208
  235. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/WHEEL +1 -1
  236. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/LICENSE +0 -0
  237. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/entry_points.txt +0 -0
  238. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,139 @@
1
+ from typing import Optional, Dict, Union
2
+ from opentrons.hardware_control import SyncHardwareAPI
3
+
4
+ from opentrons.types import Mount, MountType, Point, AxisType, AxisMapType
5
+ from opentrons_shared_data.pipette import types as pip_types
6
+ from opentrons.protocol_api._types import PipetteActionTypes, PlungerPositionTypes
7
+ from opentrons.protocol_engine import commands as cmd
8
+ from opentrons.protocol_engine.clients import SyncClient as EngineClient
9
+ from opentrons.protocol_engine.types import DeckPoint, MotorAxis
10
+
11
+ from opentrons.protocol_api.core.robot import AbstractRobot
12
+
13
+
14
+ _AXIS_TYPE_TO_MOTOR_AXIS = {
15
+ AxisType.X: MotorAxis.X,
16
+ AxisType.Y: MotorAxis.Y,
17
+ AxisType.P_L: MotorAxis.LEFT_PLUNGER,
18
+ AxisType.P_R: MotorAxis.RIGHT_PLUNGER,
19
+ AxisType.Z_L: MotorAxis.LEFT_Z,
20
+ AxisType.Z_R: MotorAxis.RIGHT_Z,
21
+ AxisType.Z_G: MotorAxis.EXTENSION_Z,
22
+ AxisType.G: MotorAxis.EXTENSION_JAW,
23
+ AxisType.Q: MotorAxis.AXIS_96_CHANNEL_CAM,
24
+ }
25
+
26
+
27
+ class RobotCore(AbstractRobot):
28
+ """Robot API core using a ProtocolEngine.
29
+
30
+ Args:
31
+ engine_client: A client to the ProtocolEngine that is executing the protocol.
32
+ api_version: The Python Protocol API versionat which this core is operating.
33
+ sync_hardware: A SynchronousAdapter-wrapped Hardware Control API.
34
+ """
35
+
36
+ def __init__(
37
+ self, engine_client: EngineClient, sync_hardware_api: SyncHardwareAPI
38
+ ) -> None:
39
+ self._engine_client = engine_client
40
+ self._sync_hardware_api = sync_hardware_api
41
+
42
+ def _convert_to_engine_mount(self, axis_map: AxisMapType) -> Dict[MotorAxis, float]:
43
+ return {_AXIS_TYPE_TO_MOTOR_AXIS[ax]: dist for ax, dist in axis_map.items()}
44
+
45
+ def get_pipette_type_from_engine(
46
+ self, mount: Union[Mount, str]
47
+ ) -> Optional[pip_types.PipetteNameType]:
48
+ """Get the pipette attached to the given mount."""
49
+ if isinstance(mount, Mount):
50
+ engine_mount = MountType[mount.name]
51
+ else:
52
+ if mount.lower() == "right":
53
+ engine_mount = MountType.RIGHT
54
+ else:
55
+ engine_mount = MountType.LEFT
56
+ maybe_pipette = self._engine_client.state.pipettes.get_by_mount(engine_mount)
57
+ return maybe_pipette.pipetteName if maybe_pipette else None
58
+
59
+ def get_plunger_position_from_name(
60
+ self, mount: Mount, position_name: PlungerPositionTypes
61
+ ) -> float:
62
+ engine_mount = MountType[mount.name]
63
+ maybe_pipette = self._engine_client.state.pipettes.get_by_mount(engine_mount)
64
+ if not maybe_pipette:
65
+ return 0.0
66
+ return self._engine_client.state.pipettes.lookup_plunger_position_name(
67
+ maybe_pipette.id, position_name.value
68
+ )
69
+
70
+ def get_plunger_position_from_volume(
71
+ self, mount: Mount, volume: float, action: PipetteActionTypes, robot_type: str
72
+ ) -> float:
73
+ engine_mount = MountType[mount.name]
74
+ maybe_pipette = self._engine_client.state.pipettes.get_by_mount(engine_mount)
75
+ if not maybe_pipette:
76
+ raise RuntimeError(
77
+ f"Cannot load plunger position as no pipette is attached to {mount}"
78
+ )
79
+ convert_volume = (
80
+ self._engine_client.state.pipettes.lookup_volume_to_mm_conversion(
81
+ maybe_pipette.id, volume, action.value
82
+ )
83
+ )
84
+ plunger_bottom = (
85
+ self._engine_client.state.pipettes.lookup_plunger_position_name(
86
+ maybe_pipette.id, "bottom"
87
+ )
88
+ )
89
+ mm = volume / convert_volume
90
+ if robot_type == "OT-2 Standard":
91
+ position = plunger_bottom + mm
92
+ else:
93
+ position = plunger_bottom - mm
94
+ return round(position, 6)
95
+
96
+ def move_to(self, mount: Mount, destination: Point, speed: Optional[float]) -> None:
97
+ engine_mount = MountType[mount.name]
98
+ engine_destination = DeckPoint(
99
+ x=destination.x, y=destination.y, z=destination.z
100
+ )
101
+ self._engine_client.execute_command(
102
+ cmd.robot.MoveToParams(
103
+ mount=engine_mount, destination=engine_destination, speed=speed
104
+ )
105
+ )
106
+
107
+ def move_axes_to(
108
+ self,
109
+ axis_map: AxisMapType,
110
+ critical_point: Optional[AxisMapType],
111
+ speed: Optional[float],
112
+ ) -> None:
113
+ axis_engine_map = self._convert_to_engine_mount(axis_map)
114
+ if critical_point:
115
+ critical_point_engine = self._convert_to_engine_mount(critical_point)
116
+ else:
117
+ critical_point_engine = None
118
+
119
+ self._engine_client.execute_command(
120
+ cmd.robot.MoveAxesToParams(
121
+ axis_map=axis_engine_map,
122
+ critical_point=critical_point_engine,
123
+ speed=speed,
124
+ )
125
+ )
126
+
127
+ def move_axes_relative(self, axis_map: AxisMapType, speed: Optional[float]) -> None:
128
+ axis_engine_map = self._convert_to_engine_mount(axis_map)
129
+ self._engine_client.execute_command(
130
+ cmd.robot.MoveAxesRelativeParams(axis_map=axis_engine_map, speed=speed)
131
+ )
132
+
133
+ def release_grip(self) -> None:
134
+ self._engine_client.execute_command(cmd.robot.openGripperJawParams())
135
+
136
+ def close_gripper(self, force: Optional[float] = None) -> None:
137
+ self._engine_client.execute_command(
138
+ cmd.robot.closeGripperJawParams(force=force)
139
+ )
@@ -130,7 +130,10 @@ class WellCore(AbstractWellCore):
130
130
  liquid: Liquid,
131
131
  volume: float,
132
132
  ) -> None:
133
- """Load liquid into a well."""
133
+ """Load liquid into a well.
134
+
135
+ If the well is known to be empty, use ``load_empty()`` instead of calling this with a 0.0 volume.
136
+ """
134
137
  self._engine_client.execute_command(
135
138
  cmd.LoadLiquidParams(
136
139
  labwareId=self._labware_id,
@@ -3,14 +3,14 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from abc import abstractmethod, ABC
6
- from typing import Any, Generic, Optional, TypeVar, Union
6
+ from typing import Any, Generic, Optional, TypeVar, Union, List
7
7
 
8
8
  from opentrons import types
9
9
  from opentrons.hardware_control.dev_types import PipetteDict
10
10
  from opentrons.protocols.api_support.util import FlowRates
11
+ from opentrons.protocols.advanced_control.transfers.common import TransferTipPolicyV2
11
12
  from opentrons.protocol_api._nozzle_layout import NozzleLayout
12
- from opentrons.hardware_control.nozzle_manager import NozzleMap
13
-
13
+ from opentrons.protocol_api._liquid import LiquidClass
14
14
  from ..disposal_locations import TrashBin, WasteChute
15
15
  from .well import WellCoreType
16
16
 
@@ -24,6 +24,14 @@ class AbstractInstrument(ABC, Generic[WellCoreType]):
24
24
  def set_default_speed(self, speed: float) -> None:
25
25
  ...
26
26
 
27
+ @abstractmethod
28
+ def air_gap_in_place(self, volume: float, flow_rate: float) -> None:
29
+ """Aspirate a given volume of air from the current location of the pipette.
30
+ Args:
31
+ volume: The volume of air to aspirate, in microliters.
32
+ flow_rate: The flow rate of air into the pipette, in microliters.
33
+ """
34
+
27
35
  @abstractmethod
28
36
  def aspirate(
29
37
  self,
@@ -172,6 +180,33 @@ class AbstractInstrument(ABC, Generic[WellCoreType]):
172
180
  ) -> None:
173
181
  ...
174
182
 
183
+ @abstractmethod
184
+ def resin_tip_seal(
185
+ self,
186
+ location: types.Location,
187
+ well_core: WellCoreType,
188
+ in_place: Optional[bool] = False,
189
+ ) -> None:
190
+ ...
191
+
192
+ @abstractmethod
193
+ def resin_tip_unseal(
194
+ self,
195
+ location: types.Location,
196
+ well_core: WellCoreType,
197
+ ) -> None:
198
+ ...
199
+
200
+ @abstractmethod
201
+ def resin_tip_dispense(
202
+ self,
203
+ location: types.Location,
204
+ well_core: WellCoreType,
205
+ volume: Optional[float] = None,
206
+ flow_rate: Optional[float] = None,
207
+ ) -> None:
208
+ ...
209
+
175
210
  @abstractmethod
176
211
  def get_mount(self) -> types.Mount:
177
212
  ...
@@ -222,7 +257,7 @@ class AbstractInstrument(ABC, Generic[WellCoreType]):
222
257
  ...
223
258
 
224
259
  @abstractmethod
225
- def get_nozzle_map(self) -> NozzleMap:
260
+ def get_nozzle_map(self) -> types.NozzleMapInterface:
226
261
  ...
227
262
 
228
263
  @abstractmethod
@@ -253,6 +288,10 @@ class AbstractInstrument(ABC, Generic[WellCoreType]):
253
288
  def get_liquid_presence_detection(self) -> bool:
254
289
  ...
255
290
 
291
+ @abstractmethod
292
+ def _pressure_supported_by_pipette(self) -> bool:
293
+ ...
294
+
256
295
  @abstractmethod
257
296
  def set_liquid_presence_detection(self, enable: bool) -> None:
258
297
  ...
@@ -298,6 +337,32 @@ class AbstractInstrument(ABC, Generic[WellCoreType]):
298
337
  """
299
338
  ...
300
339
 
340
+ @abstractmethod
341
+ def load_liquid_class(
342
+ self,
343
+ liquid_class: LiquidClass,
344
+ pipette_load_name: str,
345
+ tiprack_uri: str,
346
+ ) -> str:
347
+ """Load the liquid class properties of given pipette and tiprack into the engine.
348
+
349
+ Returns: ID of the liquid class record
350
+ """
351
+ ...
352
+
353
+ @abstractmethod
354
+ def transfer_liquid(
355
+ self,
356
+ liquid_class_id: str,
357
+ volume: float,
358
+ source: List[WellCoreType],
359
+ dest: List[WellCoreType],
360
+ new_tip: TransferTipPolicyV2,
361
+ trash_location: Union[WellCoreType, types.Location, TrashBin, WasteChute],
362
+ ) -> None:
363
+ """Transfer a liquid from source to dest according to liquid class properties."""
364
+ ...
365
+
301
366
  @abstractmethod
302
367
  def is_tip_tracking_available(self) -> bool:
303
368
  """Return whether auto tip tracking is available for the pipette's current nozzle configuration."""
@@ -327,5 +392,9 @@ class AbstractInstrument(ABC, Generic[WellCoreType]):
327
392
  """Do a liquid probe to find the level of the liquid in the well."""
328
393
  ...
329
394
 
395
+ @abstractmethod
396
+ def nozzle_configuration_valid_for_lld(self) -> bool:
397
+ """Check if the nozzle configuration currently supports LLD."""
398
+
330
399
 
331
400
  InstrumentCoreType = TypeVar("InstrumentCoreType", bound=AbstractInstrument[Any])
@@ -1,8 +1,9 @@
1
1
  """The interface that implements InstrumentContext."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from abc import ABC, abstractmethod
5
- from typing import Any, Generic, List, NamedTuple, Optional, TypeVar
6
+ from typing import Any, Generic, List, NamedTuple, Optional, TypeVar, Dict
6
7
 
7
8
  from opentrons_shared_data.labware.types import (
8
9
  LabwareUri,
@@ -10,8 +11,8 @@ from opentrons_shared_data.labware.types import (
10
11
  LabwareDefinition as LabwareDefinitionDict,
11
12
  )
12
13
 
13
- from opentrons.types import DeckSlotName, Point
14
- from opentrons.hardware_control.nozzle_manager import NozzleMap
14
+ from opentrons.types import DeckSlotName, Point, NozzleMapInterface
15
+ from .._liquid import Liquid
15
16
 
16
17
  from .well import WellCoreType
17
18
 
@@ -118,7 +119,7 @@ class AbstractLabware(ABC, Generic[WellCoreType]):
118
119
  self,
119
120
  num_tips: int,
120
121
  starting_tip: Optional[WellCoreType],
121
- nozzle_map: Optional[NozzleMap],
122
+ nozzle_map: Optional[NozzleMapInterface],
122
123
  ) -> Optional[str]:
123
124
  """Get the name of the next available tip(s) in the rack, if available."""
124
125
 
@@ -134,5 +135,13 @@ class AbstractLabware(ABC, Generic[WellCoreType]):
134
135
  def get_deck_slot(self) -> Optional[DeckSlotName]:
135
136
  """Get the deck slot the labware or its parent is in, if any."""
136
137
 
138
+ @abstractmethod
139
+ def load_liquid(self, volumes: Dict[str, float], liquid: Liquid) -> None:
140
+ """Load liquid into wells of the labware."""
141
+
142
+ @abstractmethod
143
+ def load_empty(self, wells: List[str]) -> None:
144
+ """Mark wells of the labware as empty."""
145
+
137
146
 
138
147
  LabwareCoreType = TypeVar("LabwareCoreType", bound=AbstractLabware[Any])
@@ -1,12 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- from typing import TYPE_CHECKING, Optional, Union
4
+ from typing import TYPE_CHECKING, Optional, Union, List
5
5
 
6
6
  from opentrons import types
7
7
  from opentrons.hardware_control import CriticalPoint
8
8
  from opentrons.hardware_control.dev_types import PipetteDict
9
9
  from opentrons.protocol_api.core.common import WellCore
10
+ from opentrons.protocols.advanced_control.transfers.common import TransferTipPolicyV2
10
11
  from opentrons.protocols.api_support import instrument as instrument_support
11
12
  from opentrons.protocols.api_support.definitions import MAX_SUPPORTED_VERSION
12
13
  from opentrons.protocols.api_support.labware_like import LabwareLike
@@ -19,7 +20,7 @@ from opentrons.protocols.api_support.util import (
19
20
  )
20
21
  from opentrons.protocols.geometry import planning
21
22
  from opentrons.protocol_api._nozzle_layout import NozzleLayout
22
- from opentrons.hardware_control.nozzle_manager import NozzleMap
23
+ from opentrons.protocol_api._liquid import LiquidClass
23
24
 
24
25
  from ...disposal_locations import TrashBin, WasteChute
25
26
  from ..instrument import AbstractInstrument
@@ -72,6 +73,9 @@ class LegacyInstrumentCore(AbstractInstrument[LegacyWellCore]):
72
73
  """Sets the speed at which the robot's gantry moves."""
73
74
  self._default_speed = speed
74
75
 
76
+ def air_gap_in_place(self, volume: float, flow_rate: float) -> None:
77
+ assert False, "Air gap tracking only available in API version 2.22 and later"
78
+
75
79
  def aspirate(
76
80
  self,
77
81
  location: types.Location,
@@ -304,6 +308,30 @@ class LegacyInstrumentCore(AbstractInstrument[LegacyWellCore]):
304
308
  ) -> None:
305
309
  raise APIVersionError(api_element="Dropping tips in a trash bin or waste chute")
306
310
 
311
+ def resin_tip_seal(
312
+ self,
313
+ location: types.Location,
314
+ well_core: WellCore,
315
+ in_place: Optional[bool] = False,
316
+ ) -> None:
317
+ raise APIVersionError(api_element="Sealing resin tips.")
318
+
319
+ def resin_tip_unseal(
320
+ self,
321
+ location: types.Location,
322
+ well_core: WellCore,
323
+ ) -> None:
324
+ raise APIVersionError(api_element="Unsealing resin tips.")
325
+
326
+ def resin_tip_dispense(
327
+ self,
328
+ location: types.Location,
329
+ well_core: WellCore,
330
+ volume: Optional[float] = None,
331
+ flow_rate: Optional[float] = None,
332
+ ) -> None:
333
+ raise APIVersionError(api_element="Dispensing liquid from resin tips.")
334
+
307
335
  def home(self) -> None:
308
336
  """Home the mount"""
309
337
  self._protocol_interface.get_hardware().home_z(
@@ -396,6 +424,32 @@ class LegacyInstrumentCore(AbstractInstrument[LegacyWellCore]):
396
424
  location=location, mount=location_cache_mount
397
425
  )
398
426
 
427
+ def evotip_seal(
428
+ self,
429
+ location: types.Location,
430
+ well_core: LegacyWellCore,
431
+ in_place: Optional[bool] = False,
432
+ ) -> None:
433
+ """This will never be called because it was added in API 2.22."""
434
+ assert False, "evotip_seal only supported in API 2.22 & later"
435
+
436
+ def evotip_unseal(
437
+ self, location: types.Location, well_core: WellCore, home_after: Optional[bool]
438
+ ) -> None:
439
+ """This will never be called because it was added in API 2.22."""
440
+ assert False, "evotip_unseal only supported in API 2.22 & later"
441
+
442
+ def evotip_dispense(
443
+ self,
444
+ location: types.Location,
445
+ well_core: WellCore,
446
+ volume: Optional[float] = None,
447
+ flow_rate: Optional[float] = None,
448
+ push_out: Optional[float] = None,
449
+ ) -> None:
450
+ """This will never be called because it was added in API 2.22."""
451
+ assert False, "evotip_dispense only supported in API 2.22 & later"
452
+
399
453
  def get_mount(self) -> types.Mount:
400
454
  """Get the mount this pipette is attached to."""
401
455
  return self._mount
@@ -552,11 +606,34 @@ class LegacyInstrumentCore(AbstractInstrument[LegacyWellCore]):
552
606
  """This will never be called because it was added in API 2.16."""
553
607
  pass
554
608
 
609
+ def load_liquid_class(
610
+ self,
611
+ liquid_class: LiquidClass,
612
+ pipette_load_name: str,
613
+ tiprack_uri: str,
614
+ ) -> str:
615
+ """This will never be called because it was added in .."""
616
+ # TODO(spp, 2024-11-20): update the docstring and error to include API version
617
+ assert False, "load_liquid_class is not supported in legacy context"
618
+
619
+ def transfer_liquid(
620
+ self,
621
+ liquid_class_id: str,
622
+ volume: float,
623
+ source: List[LegacyWellCore],
624
+ dest: List[LegacyWellCore],
625
+ new_tip: TransferTipPolicyV2,
626
+ trash_location: Union[LegacyWellCore, types.Location, TrashBin, WasteChute],
627
+ ) -> None:
628
+ """This will never be called because it was added in .."""
629
+ # TODO(spp, 2024-11-20): update the docstring and error to include API version
630
+ assert False, "transfer_liquid is not supported in legacy context"
631
+
555
632
  def get_active_channels(self) -> int:
556
633
  """This will never be called because it was added in API 2.16."""
557
634
  assert False, "get_active_channels only supported in API 2.16 & later"
558
635
 
559
- def get_nozzle_map(self) -> NozzleMap:
636
+ def get_nozzle_map(self) -> types.NozzleMapInterface:
560
637
  """This will never be called because it was added in API 2.18."""
561
638
  assert False, "get_nozzle_map only supported in API 2.18 & later"
562
639
 
@@ -583,3 +660,10 @@ class LegacyInstrumentCore(AbstractInstrument[LegacyWellCore]):
583
660
  ) -> float:
584
661
  """This will never be called because it was added in API 2.20."""
585
662
  assert False, "liquid_probe_without_recovery only supported in API 2.20 & later"
663
+
664
+ def _pressure_supported_by_pipette(self) -> bool:
665
+ return False
666
+
667
+ def nozzle_configuration_valid_for_lld(self) -> bool:
668
+ """Check if the nozzle configuration currently supports LLD."""
669
+ return False
@@ -1,13 +1,14 @@
1
- from typing import List, Optional
1
+ from typing import List, Optional, Dict
2
2
 
3
3
  from opentrons.calibration_storage import helpers
4
4
  from opentrons.protocols.geometry.labware_geometry import LabwareGeometry
5
5
  from opentrons.protocols.api_support.tip_tracker import TipTracker
6
6
 
7
- from opentrons.types import DeckSlotName, Location, Point
8
- from opentrons.hardware_control.nozzle_manager import NozzleMap
7
+ from opentrons.types import DeckSlotName, Location, Point, NozzleMapInterface
8
+
9
9
  from opentrons_shared_data.labware.types import LabwareParameters, LabwareDefinition
10
10
 
11
+ from ..._liquid import Liquid
11
12
  from ..labware import AbstractLabware, LabwareLoadParams
12
13
  from .legacy_well_core import LegacyWellCore
13
14
  from .well_geometry import WellGeometry
@@ -162,7 +163,7 @@ class LegacyLabwareCore(AbstractLabware[LegacyWellCore]):
162
163
  self,
163
164
  num_tips: int,
164
165
  starting_tip: Optional[LegacyWellCore],
165
- nozzle_map: Optional[NozzleMap],
166
+ nozzle_map: Optional[NozzleMapInterface],
166
167
  ) -> Optional[str]:
167
168
  if nozzle_map is not None:
168
169
  raise ValueError(
@@ -220,3 +221,11 @@ class LegacyLabwareCore(AbstractLabware[LegacyWellCore]):
220
221
  """Get the deck slot the labware is in, if in a deck slot."""
221
222
  slot = self._geometry.parent.labware.first_parent()
222
223
  return DeckSlotName.from_primitive(slot) if slot is not None else None
224
+
225
+ def load_liquid(self, volumes: Dict[str, float], liquid: Liquid) -> None:
226
+ """Load liquid into wells of the labware."""
227
+ assert False, "load_liquid only supported in API version 2.22 & later"
228
+
229
+ def load_empty(self, wells: List[str]) -> None:
230
+ """Mark wells of the labware as empty."""
231
+ assert False, "load_empty only supported in API version 2.22 & later"
@@ -6,7 +6,13 @@ from opentrons_shared_data.labware.types import LabwareDefinition
6
6
  from opentrons_shared_data.pipette.types import PipetteNameType
7
7
  from opentrons_shared_data.robot.types import RobotType
8
8
 
9
- from opentrons.types import DeckSlotName, StagingSlotName, Location, Mount, Point
9
+ from opentrons.types import (
10
+ DeckSlotName,
11
+ StagingSlotName,
12
+ Location,
13
+ Mount,
14
+ Point,
15
+ )
10
16
  from opentrons.util.broker import Broker
11
17
  from opentrons.hardware_control import SyncHardwareAPI
12
18
  from opentrons.hardware_control.modules import AbstractModule, ModuleModel, ModuleType
@@ -267,6 +273,20 @@ class LegacyProtocolCore(
267
273
  """Load an adapter using its identifying parameters"""
268
274
  raise APIVersionError(api_element="Loading adapter")
269
275
 
276
+ def load_lid(
277
+ self,
278
+ load_name: str,
279
+ location: LegacyLabwareCore,
280
+ namespace: Optional[str],
281
+ version: Optional[int],
282
+ ) -> LegacyLabwareCore:
283
+ """Load an individual lid labware using its identifying parameters. Must be loaded on a labware."""
284
+ raise APIVersionError(api_element="Loading lid")
285
+
286
+ def load_robot(self) -> None: # type: ignore
287
+ """Load an adapter using its identifying parameters"""
288
+ raise APIVersionError(api_element="Loading robot")
289
+
270
290
  def move_labware(
271
291
  self,
272
292
  labware_core: LegacyLabwareCore,
@@ -474,6 +494,17 @@ class LegacyProtocolCore(
474
494
  self._last_location = location
475
495
  self._last_mount = mount
476
496
 
497
+ def load_lid_stack(
498
+ self,
499
+ load_name: str,
500
+ location: Union[DeckSlotName, StagingSlotName, LegacyLabwareCore],
501
+ quantity: int,
502
+ namespace: Optional[str],
503
+ version: Optional[int],
504
+ ) -> LegacyLabwareCore:
505
+ """Load a Stack of Lids to a given location, creating a Lid Stack."""
506
+ raise APIVersionError(api_element="Lid stack")
507
+
477
508
  def get_module_cores(self) -> List[legacy_module_core.LegacyModuleCore]:
478
509
  """Get loaded module cores."""
479
510
  return self._module_cores
@@ -1,12 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- from typing import TYPE_CHECKING, Optional, Union
4
+ from typing import TYPE_CHECKING, Optional, Union, List
5
5
 
6
6
  from opentrons import types
7
7
  from opentrons.hardware_control.dev_types import PipetteDict
8
8
  from opentrons.hardware_control.types import HardwareAction
9
9
  from opentrons.protocol_api.core.common import WellCore
10
+ from opentrons.protocols.advanced_control.transfers.common import TransferTipPolicyV2
10
11
  from opentrons.protocols.api_support import instrument as instrument_support
11
12
  from opentrons.protocols.api_support.labware_like import LabwareLike
12
13
  from opentrons.protocols.api_support.types import APIVersion
@@ -24,7 +25,7 @@ from opentrons_shared_data.errors.exceptions import (
24
25
 
25
26
  from ...disposal_locations import TrashBin, WasteChute
26
27
  from opentrons.protocol_api._nozzle_layout import NozzleLayout
27
- from opentrons.hardware_control.nozzle_manager import NozzleMap
28
+ from opentrons.protocol_api._liquid import LiquidClass
28
29
 
29
30
  from ..instrument import AbstractInstrument
30
31
 
@@ -83,6 +84,9 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
83
84
  def set_default_speed(self, speed: float) -> None:
84
85
  self._default_speed = speed
85
86
 
87
+ def air_gap_in_place(self, volume: float, flow_rate: float) -> None:
88
+ assert False, "Air gap tracking only available in API version 2.22 and later"
89
+
86
90
  def aspirate(
87
91
  self,
88
92
  location: types.Location,
@@ -272,6 +276,30 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
272
276
  ) -> None:
273
277
  raise APIVersionError(api_element="Dropping tips in a trash bin or waste chute")
274
278
 
279
+ def resin_tip_seal(
280
+ self,
281
+ location: types.Location,
282
+ well_core: WellCore,
283
+ in_place: Optional[bool] = False,
284
+ ) -> None:
285
+ raise APIVersionError(api_element="Sealing resin tips.")
286
+
287
+ def resin_tip_unseal(
288
+ self,
289
+ location: types.Location,
290
+ well_core: WellCore,
291
+ ) -> None:
292
+ raise APIVersionError(api_element="Unsealing resin tips.")
293
+
294
+ def resin_tip_dispense(
295
+ self,
296
+ location: types.Location,
297
+ well_core: WellCore,
298
+ volume: Optional[float] = None,
299
+ flow_rate: Optional[float] = None,
300
+ ) -> None:
301
+ raise APIVersionError(api_element="Dispensing liquid from resin tips.")
302
+
275
303
  def home(self) -> None:
276
304
  self._protocol_interface.set_last_location(None)
277
305
 
@@ -470,11 +498,34 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
470
498
  """This will never be called because it was added in API 2.15."""
471
499
  pass
472
500
 
501
+ def load_liquid_class(
502
+ self,
503
+ liquid_class: LiquidClass,
504
+ pipette_load_name: str,
505
+ tiprack_uri: str,
506
+ ) -> str:
507
+ """This will never be called because it was added in .."""
508
+ # TODO(spp, 2024-11-20): update the docstring and error to include API version
509
+ assert False, "load_liquid_class is not supported in legacy context"
510
+
511
+ def transfer_liquid(
512
+ self,
513
+ liquid_class_id: str,
514
+ volume: float,
515
+ source: List[LegacyWellCore],
516
+ dest: List[LegacyWellCore],
517
+ new_tip: TransferTipPolicyV2,
518
+ trash_location: Union[LegacyWellCore, types.Location, TrashBin, WasteChute],
519
+ ) -> None:
520
+ """Transfer a liquid from source to dest according to liquid class properties."""
521
+ # TODO(spp, 2024-11-20): update the docstring and error to include API version
522
+ assert False, "transfer_liquid is not supported in legacy context"
523
+
473
524
  def get_active_channels(self) -> int:
474
525
  """This will never be called because it was added in API 2.16."""
475
526
  assert False, "get_active_channels only supported in API 2.16 & later"
476
527
 
477
- def get_nozzle_map(self) -> NozzleMap:
528
+ def get_nozzle_map(self) -> types.NozzleMapInterface:
478
529
  """This will never be called because it was added in API 2.18."""
479
530
  assert False, "get_nozzle_map only supported in API 2.18 & later"
480
531
 
@@ -501,3 +552,10 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
501
552
  ) -> float:
502
553
  """This will never be called because it was added in API 2.20."""
503
554
  assert False, "liquid_probe_without_recovery only supported in API 2.20 & later"
555
+
556
+ def _pressure_supported_by_pipette(self) -> bool:
557
+ return False
558
+
559
+ def nozzle_configuration_valid_for_lld(self) -> bool:
560
+ """Check if the nozzle configuration currently supports LLD."""
561
+ return False