opentrons 8.1.0__py2.py3-none-any.whl → 8.2.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/cli/analyze.py +71 -7
  2. opentrons/config/__init__.py +9 -0
  3. opentrons/config/advanced_settings.py +22 -0
  4. opentrons/config/defaults_ot3.py +14 -36
  5. opentrons/config/feature_flags.py +4 -0
  6. opentrons/config/types.py +6 -17
  7. opentrons/drivers/absorbance_reader/abstract.py +27 -3
  8. opentrons/drivers/absorbance_reader/async_byonoy.py +208 -154
  9. opentrons/drivers/absorbance_reader/driver.py +24 -15
  10. opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
  11. opentrons/drivers/absorbance_reader/simulator.py +32 -6
  12. opentrons/drivers/types.py +23 -1
  13. opentrons/execute.py +2 -2
  14. opentrons/hardware_control/api.py +18 -10
  15. opentrons/hardware_control/backends/controller.py +3 -2
  16. opentrons/hardware_control/backends/flex_protocol.py +11 -5
  17. opentrons/hardware_control/backends/ot3controller.py +18 -50
  18. opentrons/hardware_control/backends/ot3simulator.py +7 -6
  19. opentrons/hardware_control/backends/ot3utils.py +1 -0
  20. opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
  21. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
  22. opentrons/hardware_control/module_control.py +43 -2
  23. opentrons/hardware_control/modules/__init__.py +7 -1
  24. opentrons/hardware_control/modules/absorbance_reader.py +232 -83
  25. opentrons/hardware_control/modules/errors.py +7 -0
  26. opentrons/hardware_control/modules/heater_shaker.py +8 -3
  27. opentrons/hardware_control/modules/magdeck.py +12 -3
  28. opentrons/hardware_control/modules/mod_abc.py +27 -2
  29. opentrons/hardware_control/modules/tempdeck.py +15 -7
  30. opentrons/hardware_control/modules/thermocycler.py +69 -3
  31. opentrons/hardware_control/modules/types.py +11 -5
  32. opentrons/hardware_control/modules/update.py +11 -5
  33. opentrons/hardware_control/modules/utils.py +3 -1
  34. opentrons/hardware_control/ot3_calibration.py +6 -6
  35. opentrons/hardware_control/ot3api.py +131 -94
  36. opentrons/hardware_control/poller.py +15 -11
  37. opentrons/hardware_control/protocols/__init__.py +1 -7
  38. opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
  39. opentrons/hardware_control/protocols/liquid_handler.py +5 -0
  40. opentrons/hardware_control/protocols/position_estimator.py +3 -1
  41. opentrons/hardware_control/types.py +2 -0
  42. opentrons/legacy_commands/helpers.py +8 -2
  43. opentrons/motion_planning/__init__.py +2 -0
  44. opentrons/motion_planning/waypoints.py +32 -0
  45. opentrons/protocol_api/__init__.py +2 -1
  46. opentrons/protocol_api/_liquid.py +87 -1
  47. opentrons/protocol_api/_parameter_context.py +10 -1
  48. opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
  49. opentrons/protocol_api/core/engine/instrument.py +29 -25
  50. opentrons/protocol_api/core/engine/labware.py +20 -4
  51. opentrons/protocol_api/core/engine/module_core.py +166 -17
  52. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +362 -0
  53. opentrons/protocol_api/core/engine/protocol.py +30 -2
  54. opentrons/protocol_api/core/instrument.py +2 -0
  55. opentrons/protocol_api/core/labware.py +4 -0
  56. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
  57. opentrons/protocol_api/core/legacy/legacy_labware_core.py +5 -0
  58. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +6 -2
  59. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
  60. opentrons/protocol_api/core/module.py +22 -4
  61. opentrons/protocol_api/core/protocol.py +6 -2
  62. opentrons/protocol_api/instrument_context.py +52 -20
  63. opentrons/protocol_api/labware.py +13 -1
  64. opentrons/protocol_api/module_contexts.py +115 -17
  65. opentrons/protocol_api/protocol_context.py +49 -5
  66. opentrons/protocol_api/validation.py +5 -3
  67. opentrons/protocol_engine/__init__.py +10 -9
  68. opentrons/protocol_engine/actions/__init__.py +3 -0
  69. opentrons/protocol_engine/actions/actions.py +30 -25
  70. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  71. opentrons/protocol_engine/clients/sync_client.py +1 -1
  72. opentrons/protocol_engine/clients/transports.py +1 -1
  73. opentrons/protocol_engine/commands/__init__.py +0 -4
  74. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
  75. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +148 -0
  76. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +65 -9
  77. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +148 -0
  78. opentrons/protocol_engine/commands/absorbance_reader/read.py +200 -0
  79. opentrons/protocol_engine/commands/aspirate.py +29 -16
  80. opentrons/protocol_engine/commands/aspirate_in_place.py +33 -16
  81. opentrons/protocol_engine/commands/blow_out.py +63 -14
  82. opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
  83. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
  84. opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
  85. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
  86. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
  87. opentrons/protocol_engine/commands/command.py +31 -18
  88. opentrons/protocol_engine/commands/command_unions.py +37 -24
  89. opentrons/protocol_engine/commands/comment.py +5 -3
  90. opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
  91. opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
  92. opentrons/protocol_engine/commands/custom.py +5 -3
  93. opentrons/protocol_engine/commands/dispense.py +42 -20
  94. opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
  95. opentrons/protocol_engine/commands/drop_tip.py +70 -16
  96. opentrons/protocol_engine/commands/drop_tip_in_place.py +59 -13
  97. opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
  98. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
  99. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
  100. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
  101. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
  102. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
  103. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
  104. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
  105. opentrons/protocol_engine/commands/home.py +11 -5
  106. opentrons/protocol_engine/commands/liquid_probe.py +146 -88
  107. opentrons/protocol_engine/commands/load_labware.py +28 -5
  108. opentrons/protocol_engine/commands/load_liquid.py +18 -7
  109. opentrons/protocol_engine/commands/load_module.py +4 -6
  110. opentrons/protocol_engine/commands/load_pipette.py +18 -17
  111. opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
  112. opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
  113. opentrons/protocol_engine/commands/move_labware.py +155 -23
  114. opentrons/protocol_engine/commands/move_relative.py +15 -3
  115. opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
  116. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
  117. opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
  118. opentrons/protocol_engine/commands/move_to_well.py +37 -10
  119. opentrons/protocol_engine/commands/pick_up_tip.py +51 -30
  120. opentrons/protocol_engine/commands/pipetting_common.py +47 -16
  121. opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
  122. opentrons/protocol_engine/commands/reload_labware.py +13 -4
  123. opentrons/protocol_engine/commands/retract_axis.py +6 -3
  124. opentrons/protocol_engine/commands/save_position.py +2 -3
  125. opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
  126. opentrons/protocol_engine/commands/set_status_bar.py +5 -3
  127. opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
  128. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
  129. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
  130. opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
  131. opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
  132. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
  133. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
  134. opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
  135. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
  136. opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
  137. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
  138. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
  139. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
  140. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
  141. opentrons/protocol_engine/commands/touch_tip.py +19 -7
  142. opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
  143. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
  144. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
  145. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
  146. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  147. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  148. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +10 -4
  149. opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
  150. opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
  151. opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
  152. opentrons/protocol_engine/create_protocol_engine.py +60 -10
  153. opentrons/protocol_engine/engine_support.py +2 -1
  154. opentrons/protocol_engine/error_recovery_policy.py +14 -3
  155. opentrons/protocol_engine/errors/__init__.py +20 -0
  156. opentrons/protocol_engine/errors/error_occurrence.py +8 -3
  157. opentrons/protocol_engine/errors/exceptions.py +127 -2
  158. opentrons/protocol_engine/execution/__init__.py +2 -0
  159. opentrons/protocol_engine/execution/command_executor.py +22 -13
  160. opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
  161. opentrons/protocol_engine/execution/door_watcher.py +1 -1
  162. opentrons/protocol_engine/execution/equipment.py +2 -1
  163. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  164. opentrons/protocol_engine/execution/gantry_mover.py +4 -2
  165. opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
  166. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
  167. opentrons/protocol_engine/execution/labware_movement.py +73 -22
  168. opentrons/protocol_engine/execution/movement.py +17 -7
  169. opentrons/protocol_engine/execution/pipetting.py +7 -4
  170. opentrons/protocol_engine/execution/queue_worker.py +6 -2
  171. opentrons/protocol_engine/execution/run_control.py +1 -1
  172. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
  173. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
  174. opentrons/protocol_engine/execution/tip_handler.py +77 -43
  175. opentrons/protocol_engine/notes/__init__.py +14 -2
  176. opentrons/protocol_engine/notes/notes.py +18 -1
  177. opentrons/protocol_engine/plugins.py +1 -1
  178. opentrons/protocol_engine/protocol_engine.py +47 -31
  179. opentrons/protocol_engine/resources/__init__.py +2 -0
  180. opentrons/protocol_engine/resources/deck_data_provider.py +19 -5
  181. opentrons/protocol_engine/resources/file_provider.py +161 -0
  182. opentrons/protocol_engine/resources/fixture_validation.py +11 -1
  183. opentrons/protocol_engine/resources/labware_validation.py +10 -0
  184. opentrons/protocol_engine/state/__init__.py +0 -70
  185. opentrons/protocol_engine/state/addressable_areas.py +1 -1
  186. opentrons/protocol_engine/state/command_history.py +21 -2
  187. opentrons/protocol_engine/state/commands.py +110 -31
  188. opentrons/protocol_engine/state/files.py +59 -0
  189. opentrons/protocol_engine/state/frustum_helpers.py +440 -0
  190. opentrons/protocol_engine/state/geometry.py +445 -59
  191. opentrons/protocol_engine/state/labware.py +264 -84
  192. opentrons/protocol_engine/state/liquids.py +1 -1
  193. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +21 -3
  194. opentrons/protocol_engine/state/modules.py +145 -90
  195. opentrons/protocol_engine/state/motion.py +33 -14
  196. opentrons/protocol_engine/state/pipettes.py +157 -317
  197. opentrons/protocol_engine/state/state.py +30 -1
  198. opentrons/protocol_engine/state/state_summary.py +3 -0
  199. opentrons/protocol_engine/state/tips.py +69 -114
  200. opentrons/protocol_engine/state/update_types.py +424 -0
  201. opentrons/protocol_engine/state/wells.py +236 -0
  202. opentrons/protocol_engine/types.py +90 -0
  203. opentrons/protocol_reader/file_format_validator.py +83 -15
  204. opentrons/protocol_runner/json_translator.py +21 -5
  205. opentrons/protocol_runner/legacy_command_mapper.py +27 -6
  206. opentrons/protocol_runner/legacy_context_plugin.py +27 -71
  207. opentrons/protocol_runner/protocol_runner.py +6 -3
  208. opentrons/protocol_runner/run_orchestrator.py +41 -6
  209. opentrons/protocols/advanced_control/mix.py +3 -5
  210. opentrons/protocols/advanced_control/transfers.py +125 -56
  211. opentrons/protocols/api_support/constants.py +1 -1
  212. opentrons/protocols/api_support/definitions.py +1 -1
  213. opentrons/protocols/api_support/labware_like.py +4 -4
  214. opentrons/protocols/api_support/tip_tracker.py +2 -2
  215. opentrons/protocols/api_support/types.py +15 -2
  216. opentrons/protocols/api_support/util.py +30 -42
  217. opentrons/protocols/duration/errors.py +1 -1
  218. opentrons/protocols/duration/estimator.py +50 -29
  219. opentrons/protocols/execution/dev_types.py +2 -2
  220. opentrons/protocols/execution/execute_json_v4.py +15 -10
  221. opentrons/protocols/execution/execute_python.py +8 -3
  222. opentrons/protocols/geometry/planning.py +12 -12
  223. opentrons/protocols/labware.py +17 -33
  224. opentrons/protocols/parameters/csv_parameter_interface.py +3 -1
  225. opentrons/simulate.py +3 -3
  226. opentrons/types.py +30 -3
  227. opentrons/util/logging_config.py +34 -0
  228. {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/METADATA +5 -4
  229. {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/RECORD +235 -223
  230. opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
  231. opentrons/protocol_engine/commands/configuring_common.py +0 -26
  232. opentrons/protocol_runner/thread_async_queue.py +0 -174
  233. /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
  234. /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
  235. {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/LICENSE +0 -0
  236. {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/WHEEL +0 -0
  237. {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/entry_points.txt +0 -0
  238. {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/top_level.txt +0 -0
@@ -6,11 +6,10 @@ from typing_extensions import Literal
6
6
 
7
7
  from .pipetting_common import (
8
8
  OverpressureError,
9
- OverpressureErrorInternalData,
10
9
  PipetteIdMixin,
11
10
  AspirateVolumeMixin,
12
11
  FlowRateMixin,
13
- WellLocationMixin,
12
+ LiquidHandlingWellLocationMixin,
14
13
  BaseLiquidHandlingResult,
15
14
  DestinationPositionResult,
16
15
  )
@@ -25,12 +24,13 @@ from ..errors.error_occurrence import ErrorOccurrence
25
24
 
26
25
  from opentrons.hardware_control import HardwareControlAPI
27
26
 
27
+ from ..state.update_types import StateUpdate, CLEAR
28
28
  from ..types import WellLocation, WellOrigin, CurrentWell, DeckPoint
29
29
 
30
30
  if TYPE_CHECKING:
31
31
  from ..execution import MovementHandler, PipettingHandler
32
32
  from ..resources import ModelUtils
33
- from ..state import StateView
33
+ from ..state.state import StateView
34
34
  from ..notes import CommandNoteAdder
35
35
 
36
36
 
@@ -38,7 +38,7 @@ AspirateCommandType = Literal["aspirate"]
38
38
 
39
39
 
40
40
  class AspirateParams(
41
- PipetteIdMixin, AspirateVolumeMixin, FlowRateMixin, WellLocationMixin
41
+ PipetteIdMixin, AspirateVolumeMixin, FlowRateMixin, LiquidHandlingWellLocationMixin
42
42
  ):
43
43
  """Parameters required to aspirate from a specific well."""
44
44
 
@@ -52,8 +52,8 @@ class AspirateResult(BaseLiquidHandlingResult, DestinationPositionResult):
52
52
 
53
53
 
54
54
  _ExecuteReturn = Union[
55
- SuccessData[AspirateResult, None],
56
- DefinedErrorData[OverpressureError, OverpressureErrorInternalData],
55
+ SuccessData[AspirateResult],
56
+ DefinedErrorData[OverpressureError],
57
57
  ]
58
58
 
59
59
 
@@ -92,6 +92,7 @@ class AspirateImplementation(AbstractCommandImpl[AspirateParams, _ExecuteReturn]
92
92
  )
93
93
 
94
94
  current_well = None
95
+ state_update = StateUpdate()
95
96
 
96
97
  if not ready_to_aspirate:
97
98
  await self._movement.move_to_well(
@@ -117,6 +118,14 @@ class AspirateImplementation(AbstractCommandImpl[AspirateParams, _ExecuteReturn]
117
118
  well_name=well_name,
118
119
  well_location=params.wellLocation,
119
120
  current_well=current_well,
121
+ operation_volume=-params.volume,
122
+ )
123
+ deck_point = DeckPoint.construct(x=position.x, y=position.y, z=position.z)
124
+ state_update.set_pipette_location(
125
+ pipette_id=pipette_id,
126
+ new_labware_id=labware_id,
127
+ new_well_name=well_name,
128
+ new_deck_point=deck_point,
120
129
  )
121
130
 
122
131
  try:
@@ -127,6 +136,11 @@ class AspirateImplementation(AbstractCommandImpl[AspirateParams, _ExecuteReturn]
127
136
  command_note_adder=self._command_note_adder,
128
137
  )
129
138
  except PipetteOverpressureError as e:
139
+ state_update.set_liquid_operated(
140
+ labware_id=labware_id,
141
+ well_name=well_name,
142
+ volume_added=CLEAR,
143
+ )
130
144
  return DefinedErrorData(
131
145
  public=OverpressureError(
132
146
  id=self._model_utils.generate_id(),
@@ -140,25 +154,24 @@ class AspirateImplementation(AbstractCommandImpl[AspirateParams, _ExecuteReturn]
140
154
  ],
141
155
  errorInfo={"retryLocation": (position.x, position.y, position.z)},
142
156
  ),
143
- private=OverpressureErrorInternalData(
144
- position=DeckPoint.construct(
145
- x=position.x, y=position.y, z=position.z
146
- )
147
- ),
157
+ state_update=state_update,
148
158
  )
149
159
  else:
160
+ state_update.set_liquid_operated(
161
+ labware_id=labware_id,
162
+ well_name=well_name,
163
+ volume_added=-volume_aspirated,
164
+ )
150
165
  return SuccessData(
151
166
  public=AspirateResult(
152
167
  volume=volume_aspirated,
153
- position=DeckPoint.construct(
154
- x=position.x, y=position.y, z=position.z
155
- ),
168
+ position=deck_point,
156
169
  ),
157
- private=None,
170
+ state_update=state_update,
158
171
  )
159
172
 
160
173
 
161
- class Aspirate(BaseCommand[AspirateParams, AspirateResult, ErrorOccurrence]):
174
+ class Aspirate(BaseCommand[AspirateParams, AspirateResult, OverpressureError]):
162
175
  """Aspirate command model."""
163
176
 
164
177
  commandType: AspirateCommandType = "aspirate"
@@ -14,7 +14,6 @@ from .pipetting_common import (
14
14
  FlowRateMixin,
15
15
  BaseLiquidHandlingResult,
16
16
  OverpressureError,
17
- OverpressureErrorInternalData,
18
17
  )
19
18
  from .command import (
20
19
  AbstractCommandImpl,
@@ -25,12 +24,13 @@ from .command import (
25
24
  )
26
25
  from ..errors.error_occurrence import ErrorOccurrence
27
26
  from ..errors.exceptions import PipetteNotReadyToAspirateError
28
- from ..types import DeckPoint
27
+ from ..state.update_types import StateUpdate, CLEAR
28
+ from ..types import CurrentWell
29
29
 
30
30
  if TYPE_CHECKING:
31
31
  from ..execution import PipettingHandler, GantryMover
32
32
  from ..resources import ModelUtils
33
- from ..state import StateView
33
+ from ..state.state import StateView
34
34
  from ..notes import CommandNoteAdder
35
35
 
36
36
  AspirateInPlaceCommandType = Literal["aspirateInPlace"]
@@ -49,8 +49,8 @@ class AspirateInPlaceResult(BaseLiquidHandlingResult):
49
49
 
50
50
 
51
51
  _ExecuteReturn = Union[
52
- SuccessData[AspirateInPlaceResult, None],
53
- DefinedErrorData[OverpressureError, OverpressureErrorInternalData],
52
+ SuccessData[AspirateInPlaceResult],
53
+ DefinedErrorData[OverpressureError],
54
54
  ]
55
55
 
56
56
 
@@ -83,16 +83,21 @@ class AspirateInPlaceImplementation(
83
83
  TipNotAttachedError: if no tip is attached to the pipette.
84
84
  PipetteNotReadyToAspirateError: pipette plunger is not ready.
85
85
  """
86
+ state_update = StateUpdate()
87
+
86
88
  ready_to_aspirate = self._pipetting.get_is_ready_to_aspirate(
87
89
  pipette_id=params.pipetteId,
88
90
  )
89
-
90
91
  if not ready_to_aspirate:
91
92
  raise PipetteNotReadyToAspirateError(
92
93
  "Pipette cannot aspirate in place because of a previous blow out."
93
94
  " The first aspirate following a blow-out must be from a specific well"
94
95
  " so the plunger can be reset in a known safe position."
95
96
  )
97
+
98
+ current_location = self._state_view.pipettes.get_current_location()
99
+ current_position = await self._gantry_mover.get_position(params.pipetteId)
100
+
96
101
  try:
97
102
  volume = await self._pipetting.aspirate_in_place(
98
103
  pipette_id=params.pipetteId,
@@ -101,7 +106,15 @@ class AspirateInPlaceImplementation(
101
106
  command_note_adder=self._command_note_adder,
102
107
  )
103
108
  except PipetteOverpressureError as e:
104
- current_position = await self._gantry_mover.get_position(params.pipetteId)
109
+ if (
110
+ isinstance(current_location, CurrentWell)
111
+ and current_location.pipette_id == params.pipetteId
112
+ ):
113
+ state_update.set_liquid_operated(
114
+ labware_id=current_location.labware_id,
115
+ well_name=current_location.well_name,
116
+ volume_added=CLEAR,
117
+ )
105
118
  return DefinedErrorData(
106
119
  public=OverpressureError(
107
120
  id=self._model_utils.generate_id(),
@@ -123,22 +136,26 @@ class AspirateInPlaceImplementation(
123
136
  }
124
137
  ),
125
138
  ),
126
- private=OverpressureErrorInternalData(
127
- position=DeckPoint(
128
- x=current_position.x,
129
- y=current_position.y,
130
- z=current_position.z,
131
- ),
132
- ),
139
+ state_update=state_update,
133
140
  )
134
141
  else:
142
+ if (
143
+ isinstance(current_location, CurrentWell)
144
+ and current_location.pipette_id == params.pipetteId
145
+ ):
146
+ state_update.set_liquid_operated(
147
+ labware_id=current_location.labware_id,
148
+ well_name=current_location.well_name,
149
+ volume_added=-volume,
150
+ )
135
151
  return SuccessData(
136
- public=AspirateInPlaceResult(volume=volume), private=None
152
+ public=AspirateInPlaceResult(volume=volume),
153
+ state_update=state_update,
137
154
  )
138
155
 
139
156
 
140
157
  class AspirateInPlace(
141
- BaseCommand[AspirateInPlaceParams, AspirateInPlaceResult, ErrorOccurrence]
158
+ BaseCommand[AspirateInPlaceParams, AspirateInPlaceResult, OverpressureError]
142
159
  ):
143
160
  """AspirateInPlace command model."""
144
161
 
@@ -1,16 +1,26 @@
1
1
  """Blow-out command request, result, and implementation models."""
2
2
  from __future__ import annotations
3
- from typing import TYPE_CHECKING, Optional, Type
3
+ from typing import TYPE_CHECKING, Optional, Type, Union
4
+ from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
4
5
  from typing_extensions import Literal
5
6
 
7
+
8
+ from ..state.update_types import StateUpdate
6
9
  from ..types import DeckPoint
7
10
  from .pipetting_common import (
11
+ OverpressureError,
8
12
  PipetteIdMixin,
9
13
  FlowRateMixin,
10
14
  WellLocationMixin,
11
15
  DestinationPositionResult,
12
16
  )
13
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
17
+ from .command import (
18
+ AbstractCommandImpl,
19
+ BaseCommand,
20
+ BaseCommandCreate,
21
+ DefinedErrorData,
22
+ SuccessData,
23
+ )
14
24
  from ..errors.error_occurrence import ErrorOccurrence
15
25
 
16
26
  from opentrons.hardware_control import HardwareControlAPI
@@ -18,7 +28,9 @@ from opentrons.hardware_control import HardwareControlAPI
18
28
 
19
29
  if TYPE_CHECKING:
20
30
  from ..execution import MovementHandler, PipettingHandler
21
- from ..state import StateView
31
+ from ..state.state import StateView
32
+ from ..resources import ModelUtils
33
+
22
34
 
23
35
  BlowOutCommandType = Literal["blowout"]
24
36
 
@@ -35,9 +47,13 @@ class BlowOutResult(DestinationPositionResult):
35
47
  pass
36
48
 
37
49
 
38
- class BlowOutImplementation(
39
- AbstractCommandImpl[BlowOutParams, SuccessData[BlowOutResult, None]]
40
- ):
50
+ _ExecuteReturn = Union[
51
+ SuccessData[BlowOutResult],
52
+ DefinedErrorData[OverpressureError],
53
+ ]
54
+
55
+
56
+ class BlowOutImplementation(AbstractCommandImpl[BlowOutParams, _ExecuteReturn]):
41
57
  """BlowOut command implementation."""
42
58
 
43
59
  def __init__(
@@ -46,29 +62,62 @@ class BlowOutImplementation(
46
62
  pipetting: PipettingHandler,
47
63
  state_view: StateView,
48
64
  hardware_api: HardwareControlAPI,
65
+ model_utils: ModelUtils,
49
66
  **kwargs: object,
50
67
  ) -> None:
51
68
  self._movement = movement
52
69
  self._pipetting = pipetting
53
70
  self._state_view = state_view
54
71
  self._hardware_api = hardware_api
72
+ self._model_utils = model_utils
55
73
 
56
- async def execute(self, params: BlowOutParams) -> SuccessData[BlowOutResult, None]:
74
+ async def execute(self, params: BlowOutParams) -> _ExecuteReturn:
57
75
  """Move to and blow-out the requested well."""
76
+ state_update = StateUpdate()
77
+
58
78
  x, y, z = await self._movement.move_to_well(
59
79
  pipette_id=params.pipetteId,
60
80
  labware_id=params.labwareId,
61
81
  well_name=params.wellName,
62
82
  well_location=params.wellLocation,
63
83
  )
64
-
65
- await self._pipetting.blow_out_in_place(
66
- pipette_id=params.pipetteId, flow_rate=params.flowRate
67
- )
68
-
69
- return SuccessData(
70
- public=BlowOutResult(position=DeckPoint(x=x, y=y, z=z)), private=None
84
+ deck_point = DeckPoint.construct(x=x, y=y, z=z)
85
+ state_update.set_pipette_location(
86
+ pipette_id=params.pipetteId,
87
+ new_labware_id=params.labwareId,
88
+ new_well_name=params.wellName,
89
+ new_deck_point=deck_point,
71
90
  )
91
+ try:
92
+ await self._pipetting.blow_out_in_place(
93
+ pipette_id=params.pipetteId, flow_rate=params.flowRate
94
+ )
95
+ except PipetteOverpressureError as e:
96
+ return DefinedErrorData(
97
+ public=OverpressureError(
98
+ id=self._model_utils.generate_id(),
99
+ createdAt=self._model_utils.get_timestamp(),
100
+ wrappedErrors=[
101
+ ErrorOccurrence.from_failed(
102
+ id=self._model_utils.generate_id(),
103
+ createdAt=self._model_utils.get_timestamp(),
104
+ error=e,
105
+ )
106
+ ],
107
+ errorInfo={
108
+ "retryLocation": (
109
+ x,
110
+ y,
111
+ z,
112
+ )
113
+ },
114
+ ),
115
+ )
116
+ else:
117
+ return SuccessData(
118
+ public=BlowOutResult(position=deck_point),
119
+ state_update=state_update,
120
+ )
72
121
 
73
122
 
74
123
  class BlowOut(BaseCommand[BlowOutParams, BlowOutResult, ErrorOccurrence]):
@@ -1,23 +1,32 @@
1
1
  """Blow-out in place command request, result, and implementation models."""
2
2
 
3
3
  from __future__ import annotations
4
- from typing import TYPE_CHECKING, Optional, Type
4
+ from typing import TYPE_CHECKING, Optional, Type, Union
5
+ from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
5
6
  from typing_extensions import Literal
6
7
  from pydantic import BaseModel
7
8
 
8
9
  from .pipetting_common import (
10
+ OverpressureError,
9
11
  PipetteIdMixin,
10
12
  FlowRateMixin,
11
13
  )
12
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
14
+ from .command import (
15
+ AbstractCommandImpl,
16
+ BaseCommand,
17
+ BaseCommandCreate,
18
+ DefinedErrorData,
19
+ SuccessData,
20
+ )
13
21
  from ..errors.error_occurrence import ErrorOccurrence
14
22
 
15
23
  from opentrons.hardware_control import HardwareControlAPI
16
24
 
17
25
 
18
26
  if TYPE_CHECKING:
19
- from ..execution import PipettingHandler
20
- from ..state import StateView
27
+ from ..execution import PipettingHandler, GantryMover
28
+ from ..state.state import StateView
29
+ from ..resources import ModelUtils
21
30
 
22
31
 
23
32
  BlowOutInPlaceCommandType = Literal["blowOutInPlace"]
@@ -35,8 +44,14 @@ class BlowOutInPlaceResult(BaseModel):
35
44
  pass
36
45
 
37
46
 
47
+ _ExecuteReturn = Union[
48
+ SuccessData[BlowOutInPlaceResult],
49
+ DefinedErrorData[OverpressureError],
50
+ ]
51
+
52
+
38
53
  class BlowOutInPlaceImplementation(
39
- AbstractCommandImpl[BlowOutInPlaceParams, SuccessData[BlowOutInPlaceResult, None]]
54
+ AbstractCommandImpl[BlowOutInPlaceParams, _ExecuteReturn]
40
55
  ):
41
56
  """BlowOutInPlace command implementation."""
42
57
 
@@ -45,21 +60,48 @@ class BlowOutInPlaceImplementation(
45
60
  pipetting: PipettingHandler,
46
61
  state_view: StateView,
47
62
  hardware_api: HardwareControlAPI,
63
+ model_utils: ModelUtils,
64
+ gantry_mover: GantryMover,
48
65
  **kwargs: object,
49
66
  ) -> None:
50
67
  self._pipetting = pipetting
51
68
  self._state_view = state_view
52
69
  self._hardware_api = hardware_api
70
+ self._model_utils = model_utils
71
+ self._gantry_mover = gantry_mover
53
72
 
54
- async def execute(
55
- self, params: BlowOutInPlaceParams
56
- ) -> SuccessData[BlowOutInPlaceResult, None]:
73
+ async def execute(self, params: BlowOutInPlaceParams) -> _ExecuteReturn:
57
74
  """Blow-out without moving the pipette."""
58
- await self._pipetting.blow_out_in_place(
59
- pipette_id=params.pipetteId, flow_rate=params.flowRate
60
- )
61
-
62
- return SuccessData(public=BlowOutInPlaceResult(), private=None)
75
+ try:
76
+ current_position = await self._gantry_mover.get_position(params.pipetteId)
77
+ await self._pipetting.blow_out_in_place(
78
+ pipette_id=params.pipetteId, flow_rate=params.flowRate
79
+ )
80
+ except PipetteOverpressureError as e:
81
+ return DefinedErrorData(
82
+ public=OverpressureError(
83
+ id=self._model_utils.generate_id(),
84
+ createdAt=self._model_utils.get_timestamp(),
85
+ wrappedErrors=[
86
+ ErrorOccurrence.from_failed(
87
+ id=self._model_utils.generate_id(),
88
+ createdAt=self._model_utils.get_timestamp(),
89
+ error=e,
90
+ )
91
+ ],
92
+ errorInfo={
93
+ "retryLocation": (
94
+ current_position.x,
95
+ current_position.y,
96
+ current_position.z,
97
+ )
98
+ },
99
+ ),
100
+ )
101
+ else:
102
+ return SuccessData(
103
+ public=BlowOutInPlaceResult(),
104
+ )
63
105
 
64
106
 
65
107
  class BlowOutInPlace(
@@ -71,9 +71,7 @@ class CalibrateGripperResult(BaseModel):
71
71
 
72
72
 
73
73
  class CalibrateGripperImplementation(
74
- AbstractCommandImpl[
75
- CalibrateGripperParams, SuccessData[CalibrateGripperResult, None]
76
- ]
74
+ AbstractCommandImpl[CalibrateGripperParams, SuccessData[CalibrateGripperResult]]
77
75
  ):
78
76
  """The implementation of a `calibrateGripper` command."""
79
77
 
@@ -87,7 +85,7 @@ class CalibrateGripperImplementation(
87
85
 
88
86
  async def execute(
89
87
  self, params: CalibrateGripperParams
90
- ) -> SuccessData[CalibrateGripperResult, None]:
88
+ ) -> SuccessData[CalibrateGripperResult]:
91
89
  """Execute a `calibrateGripper` command.
92
90
 
93
91
  1. Move from the current location to the calibration area on the deck.
@@ -126,7 +124,6 @@ class CalibrateGripperImplementation(
126
124
  ),
127
125
  savedCalibration=calibration_data,
128
126
  ),
129
- private=None,
130
127
  )
131
128
 
132
129
  @staticmethod
@@ -12,7 +12,7 @@ from ...errors.error_occurrence import ErrorOccurrence
12
12
 
13
13
  # Work around type-only circular dependencies.
14
14
  if TYPE_CHECKING:
15
- from ...state import StateView
15
+ from ...state.state import StateView
16
16
 
17
17
  from ...types import ModuleOffsetVector, DeckSlotLocation
18
18
 
@@ -49,7 +49,7 @@ class CalibrateModuleResult(BaseModel):
49
49
 
50
50
 
51
51
  class CalibrateModuleImplementation(
52
- AbstractCommandImpl[CalibrateModuleParams, SuccessData[CalibrateModuleResult, None]]
52
+ AbstractCommandImpl[CalibrateModuleParams, SuccessData[CalibrateModuleResult]]
53
53
  ):
54
54
  """CalibrateModule command implementation."""
55
55
 
@@ -64,7 +64,7 @@ class CalibrateModuleImplementation(
64
64
 
65
65
  async def execute(
66
66
  self, params: CalibrateModuleParams
67
- ) -> SuccessData[CalibrateModuleResult, None]:
67
+ ) -> SuccessData[CalibrateModuleResult]:
68
68
  """Execute calibrate-module command."""
69
69
  ot3_api = ensure_ot3_hardware(
70
70
  self._hardware_api,
@@ -91,7 +91,6 @@ class CalibrateModuleImplementation(
91
91
  ),
92
92
  location=slot,
93
93
  ),
94
- private=None,
95
94
  )
96
95
 
97
96
 
@@ -34,9 +34,7 @@ class CalibratePipetteResult(BaseModel):
34
34
 
35
35
 
36
36
  class CalibratePipetteImplementation(
37
- AbstractCommandImpl[
38
- CalibratePipetteParams, SuccessData[CalibratePipetteResult, None]
39
- ]
37
+ AbstractCommandImpl[CalibratePipetteParams, SuccessData[CalibratePipetteResult]]
40
38
  ):
41
39
  """CalibratePipette command implementation."""
42
40
 
@@ -49,7 +47,7 @@ class CalibratePipetteImplementation(
49
47
 
50
48
  async def execute(
51
49
  self, params: CalibratePipetteParams
52
- ) -> SuccessData[CalibratePipetteResult, None]:
50
+ ) -> SuccessData[CalibratePipetteResult]:
53
51
  """Execute calibrate-pipette command."""
54
52
  # TODO (tz, 20-9-22): Add a better solution to determine if a command can be executed on an OT-3/OT-2
55
53
  ot3_api = ensure_ot3_hardware(
@@ -72,7 +70,6 @@ class CalibratePipetteImplementation(
72
70
  x=pipette_offset.x, y=pipette_offset.y, z=pipette_offset.z
73
71
  )
74
72
  ),
75
- private=None,
76
73
  )
77
74
 
78
75
 
@@ -15,7 +15,7 @@ from opentrons.protocol_engine.resources.ot3_validation import ensure_ot3_hardwa
15
15
 
16
16
  if TYPE_CHECKING:
17
17
  from opentrons.hardware_control import HardwareControlAPI
18
- from ...state import StateView
18
+ from ...state.state import StateView
19
19
 
20
20
  # These offsets supplied from HW
21
21
  _ATTACH_POINT = Point(x=0, y=110)
@@ -57,7 +57,7 @@ class MoveToMaintenancePositionResult(BaseModel):
57
57
  class MoveToMaintenancePositionImplementation(
58
58
  AbstractCommandImpl[
59
59
  MoveToMaintenancePositionParams,
60
- SuccessData[MoveToMaintenancePositionResult, None],
60
+ SuccessData[MoveToMaintenancePositionResult],
61
61
  ]
62
62
  ):
63
63
  """Calibration set up position command implementation."""
@@ -73,7 +73,7 @@ class MoveToMaintenancePositionImplementation(
73
73
 
74
74
  async def execute(
75
75
  self, params: MoveToMaintenancePositionParams
76
- ) -> SuccessData[MoveToMaintenancePositionResult, None]:
76
+ ) -> SuccessData[MoveToMaintenancePositionResult]:
77
77
  """Move the requested mount to a maintenance deck slot."""
78
78
  ot3_api = ensure_ot3_hardware(
79
79
  self._hardware_api,
@@ -118,7 +118,9 @@ class MoveToMaintenancePositionImplementation(
118
118
  )
119
119
  await ot3_api.disengage_axes([Axis.Z_R])
120
120
 
121
- return SuccessData(public=MoveToMaintenancePositionResult(), private=None)
121
+ return SuccessData(
122
+ public=MoveToMaintenancePositionResult(),
123
+ )
122
124
 
123
125
 
124
126
  class MoveToMaintenancePosition(