opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.0a0__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 (230) 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 +207 -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/instruments/ot2/pipette_handler.py +22 -82
  20. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
  21. opentrons/hardware_control/module_control.py +43 -2
  22. opentrons/hardware_control/modules/__init__.py +7 -1
  23. opentrons/hardware_control/modules/absorbance_reader.py +230 -83
  24. opentrons/hardware_control/modules/errors.py +7 -0
  25. opentrons/hardware_control/modules/heater_shaker.py +8 -3
  26. opentrons/hardware_control/modules/magdeck.py +12 -3
  27. opentrons/hardware_control/modules/mod_abc.py +27 -2
  28. opentrons/hardware_control/modules/tempdeck.py +15 -7
  29. opentrons/hardware_control/modules/thermocycler.py +69 -3
  30. opentrons/hardware_control/modules/types.py +11 -5
  31. opentrons/hardware_control/modules/update.py +11 -5
  32. opentrons/hardware_control/modules/utils.py +3 -1
  33. opentrons/hardware_control/ot3_calibration.py +6 -6
  34. opentrons/hardware_control/ot3api.py +126 -89
  35. opentrons/hardware_control/poller.py +15 -11
  36. opentrons/hardware_control/protocols/__init__.py +1 -7
  37. opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
  38. opentrons/hardware_control/protocols/liquid_handler.py +5 -0
  39. opentrons/motion_planning/__init__.py +2 -0
  40. opentrons/motion_planning/waypoints.py +32 -0
  41. opentrons/protocol_api/__init__.py +2 -1
  42. opentrons/protocol_api/_liquid.py +87 -1
  43. opentrons/protocol_api/_parameter_context.py +10 -1
  44. opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
  45. opentrons/protocol_api/core/engine/instrument.py +29 -25
  46. opentrons/protocol_api/core/engine/labware.py +10 -2
  47. opentrons/protocol_api/core/engine/module_core.py +129 -17
  48. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +355 -0
  49. opentrons/protocol_api/core/engine/protocol.py +55 -2
  50. opentrons/protocol_api/core/instrument.py +2 -0
  51. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
  52. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +5 -2
  53. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
  54. opentrons/protocol_api/core/module.py +22 -4
  55. opentrons/protocol_api/core/protocol.py +5 -2
  56. opentrons/protocol_api/instrument_context.py +52 -20
  57. opentrons/protocol_api/labware.py +13 -1
  58. opentrons/protocol_api/module_contexts.py +68 -13
  59. opentrons/protocol_api/protocol_context.py +38 -4
  60. opentrons/protocol_api/validation.py +5 -3
  61. opentrons/protocol_engine/__init__.py +10 -9
  62. opentrons/protocol_engine/actions/__init__.py +5 -0
  63. opentrons/protocol_engine/actions/actions.py +42 -25
  64. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  65. opentrons/protocol_engine/clients/sync_client.py +7 -1
  66. opentrons/protocol_engine/clients/transports.py +1 -1
  67. opentrons/protocol_engine/commands/__init__.py +0 -4
  68. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
  69. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +161 -0
  70. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +53 -9
  71. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +160 -0
  72. opentrons/protocol_engine/commands/absorbance_reader/read.py +196 -0
  73. opentrons/protocol_engine/commands/aspirate.py +29 -16
  74. opentrons/protocol_engine/commands/aspirate_in_place.py +32 -15
  75. opentrons/protocol_engine/commands/blow_out.py +63 -14
  76. opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
  77. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
  78. opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
  79. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
  80. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
  81. opentrons/protocol_engine/commands/command.py +28 -17
  82. opentrons/protocol_engine/commands/command_unions.py +37 -24
  83. opentrons/protocol_engine/commands/comment.py +5 -3
  84. opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
  85. opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
  86. opentrons/protocol_engine/commands/custom.py +5 -3
  87. opentrons/protocol_engine/commands/dispense.py +42 -20
  88. opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
  89. opentrons/protocol_engine/commands/drop_tip.py +68 -15
  90. opentrons/protocol_engine/commands/drop_tip_in_place.py +52 -11
  91. opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
  92. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
  93. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
  94. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
  95. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
  96. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
  97. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
  98. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
  99. opentrons/protocol_engine/commands/home.py +11 -5
  100. opentrons/protocol_engine/commands/liquid_probe.py +146 -88
  101. opentrons/protocol_engine/commands/load_labware.py +19 -5
  102. opentrons/protocol_engine/commands/load_liquid.py +18 -7
  103. opentrons/protocol_engine/commands/load_module.py +43 -6
  104. opentrons/protocol_engine/commands/load_pipette.py +18 -17
  105. opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
  106. opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
  107. opentrons/protocol_engine/commands/move_labware.py +106 -19
  108. opentrons/protocol_engine/commands/move_relative.py +15 -3
  109. opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
  110. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
  111. opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
  112. opentrons/protocol_engine/commands/move_to_well.py +37 -10
  113. opentrons/protocol_engine/commands/pick_up_tip.py +50 -29
  114. opentrons/protocol_engine/commands/pipetting_common.py +39 -15
  115. opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
  116. opentrons/protocol_engine/commands/reload_labware.py +13 -4
  117. opentrons/protocol_engine/commands/retract_axis.py +6 -3
  118. opentrons/protocol_engine/commands/save_position.py +2 -3
  119. opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
  120. opentrons/protocol_engine/commands/set_status_bar.py +5 -3
  121. opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
  122. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
  123. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
  124. opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
  125. opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
  126. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
  127. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
  128. opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
  129. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
  130. opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
  131. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
  132. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
  133. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
  134. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
  135. opentrons/protocol_engine/commands/touch_tip.py +19 -7
  136. opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
  137. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
  138. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
  139. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
  140. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +194 -0
  141. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +75 -0
  142. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +5 -3
  143. opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
  144. opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
  145. opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
  146. opentrons/protocol_engine/create_protocol_engine.py +41 -8
  147. opentrons/protocol_engine/engine_support.py +2 -1
  148. opentrons/protocol_engine/error_recovery_policy.py +14 -3
  149. opentrons/protocol_engine/errors/__init__.py +18 -0
  150. opentrons/protocol_engine/errors/exceptions.py +114 -2
  151. opentrons/protocol_engine/execution/__init__.py +2 -0
  152. opentrons/protocol_engine/execution/command_executor.py +22 -13
  153. opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
  154. opentrons/protocol_engine/execution/door_watcher.py +1 -1
  155. opentrons/protocol_engine/execution/equipment.py +2 -1
  156. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  157. opentrons/protocol_engine/execution/gantry_mover.py +4 -2
  158. opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
  159. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
  160. opentrons/protocol_engine/execution/labware_movement.py +6 -3
  161. opentrons/protocol_engine/execution/movement.py +8 -3
  162. opentrons/protocol_engine/execution/pipetting.py +7 -4
  163. opentrons/protocol_engine/execution/queue_worker.py +6 -2
  164. opentrons/protocol_engine/execution/run_control.py +1 -1
  165. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
  166. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
  167. opentrons/protocol_engine/execution/tip_handler.py +77 -43
  168. opentrons/protocol_engine/notes/__init__.py +14 -2
  169. opentrons/protocol_engine/notes/notes.py +18 -1
  170. opentrons/protocol_engine/plugins.py +1 -1
  171. opentrons/protocol_engine/protocol_engine.py +54 -31
  172. opentrons/protocol_engine/resources/__init__.py +2 -0
  173. opentrons/protocol_engine/resources/deck_data_provider.py +58 -5
  174. opentrons/protocol_engine/resources/file_provider.py +157 -0
  175. opentrons/protocol_engine/resources/fixture_validation.py +5 -0
  176. opentrons/protocol_engine/resources/labware_validation.py +10 -0
  177. opentrons/protocol_engine/state/__init__.py +0 -70
  178. opentrons/protocol_engine/state/addressable_areas.py +1 -1
  179. opentrons/protocol_engine/state/command_history.py +21 -2
  180. opentrons/protocol_engine/state/commands.py +110 -31
  181. opentrons/protocol_engine/state/files.py +59 -0
  182. opentrons/protocol_engine/state/frustum_helpers.py +440 -0
  183. opentrons/protocol_engine/state/geometry.py +359 -15
  184. opentrons/protocol_engine/state/labware.py +166 -63
  185. opentrons/protocol_engine/state/liquids.py +1 -1
  186. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +19 -3
  187. opentrons/protocol_engine/state/modules.py +167 -85
  188. opentrons/protocol_engine/state/motion.py +16 -9
  189. opentrons/protocol_engine/state/pipettes.py +157 -317
  190. opentrons/protocol_engine/state/state.py +30 -1
  191. opentrons/protocol_engine/state/state_summary.py +3 -0
  192. opentrons/protocol_engine/state/tips.py +69 -114
  193. opentrons/protocol_engine/state/update_types.py +408 -0
  194. opentrons/protocol_engine/state/wells.py +236 -0
  195. opentrons/protocol_engine/types.py +90 -0
  196. opentrons/protocol_reader/file_format_validator.py +83 -15
  197. opentrons/protocol_runner/json_translator.py +21 -5
  198. opentrons/protocol_runner/legacy_command_mapper.py +27 -6
  199. opentrons/protocol_runner/legacy_context_plugin.py +27 -71
  200. opentrons/protocol_runner/protocol_runner.py +6 -3
  201. opentrons/protocol_runner/run_orchestrator.py +26 -6
  202. opentrons/protocols/advanced_control/mix.py +3 -5
  203. opentrons/protocols/advanced_control/transfers.py +125 -56
  204. opentrons/protocols/api_support/constants.py +1 -1
  205. opentrons/protocols/api_support/definitions.py +1 -1
  206. opentrons/protocols/api_support/labware_like.py +4 -4
  207. opentrons/protocols/api_support/tip_tracker.py +2 -2
  208. opentrons/protocols/api_support/types.py +15 -2
  209. opentrons/protocols/api_support/util.py +30 -42
  210. opentrons/protocols/duration/errors.py +1 -1
  211. opentrons/protocols/duration/estimator.py +50 -29
  212. opentrons/protocols/execution/dev_types.py +2 -2
  213. opentrons/protocols/execution/execute_json_v4.py +15 -10
  214. opentrons/protocols/execution/execute_python.py +8 -3
  215. opentrons/protocols/geometry/planning.py +12 -12
  216. opentrons/protocols/labware.py +17 -33
  217. opentrons/simulate.py +3 -3
  218. opentrons/types.py +30 -3
  219. opentrons/util/logging_config.py +34 -0
  220. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/METADATA +5 -4
  221. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/RECORD +227 -215
  222. opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
  223. opentrons/protocol_engine/commands/configuring_common.py +0 -26
  224. opentrons/protocol_runner/thread_async_queue.py +0 -174
  225. /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
  226. /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
  227. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/LICENSE +0 -0
  228. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/WHEEL +0 -0
  229. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/entry_points.txt +0 -0
  230. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,11 @@
1
1
  from typing import (
2
2
  Dict,
3
+ Optional,
3
4
  Protocol,
4
5
  List,
5
6
  Literal,
6
7
  Tuple,
8
+ Union,
7
9
  runtime_checkable,
8
10
  TypeVar,
9
11
  )
@@ -11,42 +13,42 @@ from typing import (
11
13
  Response = TypeVar("Response")
12
14
 
13
15
  ErrorCodeNames = Literal[
14
- "BYONOY_ERROR_NO_ERROR",
15
- "BYONOY_ERROR_UNKNOWN_ERROR",
16
- "BYONOY_ERROR_DEVICE_CLOSED",
17
- "BYONOY_ERROR_INVALID_ARGUMENT",
18
- "BYONOY_ERROR_NO_MEMORY",
19
- "BYONOY_ERROR_UNSUPPORTED_OPERATION",
20
- "BYONOY_ERROR_DEVICE_COMMUNICATION_FAILURE",
21
- "BYONOY_ERROR_DEVICE_OPERATION_FAILED",
22
- "BYONOY_ERROR_DEVICE_OPEN_PREFIX",
23
- "BYONOY_ERROR_DEVICE_NOT_FOUND",
24
- "BYONOY_ERROR_DEVICE_TOO_NEW",
25
- "BYONOY_ERROR_DEVICE_ALREADY_OPEN",
26
- "BYONOY_ERROR_FIRMWARE_UPDATE_ERROR_PREFIX",
27
- "BYONOY_ERROR_FIRMWARE_UPDATE_FILE_NOT_FOUND",
28
- "BYONOY_ERROR_FIRMWARE_UPDATE_FILE_NOT_VALID",
29
- "BYONOY_ERROR_FIRMWARE_UPDATE_FAILED",
30
- "BYONOY_ERROR_FILE_ERROR_PREFIX",
31
- "BYONOY_ERROR_FILE_WRITE_ERROR",
32
- "BYONOY_ERROR_MEASUTEMNT_ERROR_PREFIX",
33
- "BYONOY_ERROR_MEASUTEMNT_SLOT_NOT_EMPTY",
34
- "BYONOY_ERROR_NOT_INITIALIZED",
35
- "BYONOY_ERROR_INTERNAL",
16
+ "NO_ERROR",
17
+ "UNKNOWN_ERROR",
18
+ "DEVICE_CLOSED",
19
+ "INVALID_ARGUMENT",
20
+ "NO_MEMORY",
21
+ "UNSUPPORTED_OPERATION",
22
+ "DEVICE_COMMUNICATION_FAILURE",
23
+ "DEVICE_OPERATION_FAILED",
24
+ "DEVICE_OPEN_PREFIX",
25
+ "DEVICE_NOT_FOUND",
26
+ "DEVICE_TOO_NEW",
27
+ "DEVICE_ALREADY_OPEN",
28
+ "FIRMWARE_UPDATE_ERROR_PREFIX",
29
+ "FIRMWARE_UPDATE_FILE_NOT_FOUND",
30
+ "FIRMWARE_UPDATE_FILE_NOT_VALID",
31
+ "FIRMWARE_UPDATE_FAILED",
32
+ "FILE_ERROR_PREFIX",
33
+ "FILE_WRITE_ERROR",
34
+ "MEASUTEMNT_ERROR_PREFIX",
35
+ "MEASUTEMNT_SLOT_NOT_EMPTY",
36
+ "NOT_INITIALIZED",
37
+ "INTERNAL",
36
38
  ]
37
39
 
38
40
  SlotStateNames = Literal[
39
- "BYONOY_SLOT_UNKNOWN",
40
- "BYONOY_SLOT_EMPTY",
41
- "BYONOY_SLOT_OCCUPIED",
42
- "BYONOY_SLOT_UNDETERMINED",
41
+ "UNKNOWN",
42
+ "EMPTY",
43
+ "OCCUPIED",
44
+ "UNDETERMINED",
43
45
  ]
44
46
 
45
47
  DeviceStateNames = Literal[
46
- "BYONOY_DEVICE_STATE_UNKNOWN",
47
- "BYONOY_DEVICE_STATE_OK",
48
- "BYONOY_DEVICE_STATE_BROKEN_FW",
49
- "BYONOY_DEVICE_STATE_ERROR",
48
+ "UNKNOWN",
49
+ "OK",
50
+ "BROKEN_FW",
51
+ "ERROR",
50
52
  ]
51
53
 
52
54
 
@@ -69,8 +71,13 @@ class AbsorbanceHidInterface(Protocol):
69
71
  value: int
70
72
 
71
73
  @runtime_checkable
72
- class MeasurementConfig(Protocol):
74
+ class SingleMeasurementConfig(Protocol):
73
75
  sample_wavelength: int
76
+ reference_wavelength: Optional[int]
77
+
78
+ @runtime_checkable
79
+ class MultiMeasurementConfig(Protocol):
80
+ sample_wavelengths: List[int]
74
81
 
75
82
  @runtime_checkable
76
83
  class DeviceInfo(Protocol):
@@ -84,49 +91,71 @@ class AbsorbanceHidInterface(Protocol):
84
91
  name: DeviceStateNames
85
92
  value: int
86
93
 
87
- def ByonoyAbs96SingleMeasurementConfig(self) -> MeasurementConfig:
94
+ def Abs96SingleMeasurementConfig(self) -> SingleMeasurementConfig:
95
+ ...
96
+
97
+ def Abs96MultipleMeasurementConfig(self) -> MultiMeasurementConfig:
98
+ ...
99
+
100
+ def open_device(self, device: Device) -> Tuple[ErrorCode, int]:
88
101
  ...
89
102
 
90
- def byonoy_open_device(self, device: Device) -> Tuple[ErrorCode, int]:
103
+ def free_device(self, device_handle: int) -> Tuple[ErrorCode, bool]:
91
104
  ...
92
105
 
93
- def byonoy_free_device(self, device_handle: int) -> Tuple[ErrorCode, bool]:
106
+ def device_open(self, device_handle: int) -> bool:
94
107
  ...
95
108
 
96
- def byonoy_get_device_information(
109
+ def get_device_information(
97
110
  self, device_handle: int
98
111
  ) -> Tuple[ErrorCode, DeviceInfo]:
99
112
  ...
100
113
 
101
- def byonoy_get_device_status(
102
- self, device_handle: int
103
- ) -> Tuple[ErrorCode, DeviceState]:
114
+ def update_device(self, device_handle: int, firmware_file_path: str) -> ErrorCode:
104
115
  ...
105
116
 
106
- def byonoy_get_device_slot_status(
107
- self, device_handle: int
108
- ) -> Tuple[ErrorCode, SlotState]:
117
+ def get_device_status(self, device_handle: int) -> Tuple[ErrorCode, DeviceState]:
109
118
  ...
110
119
 
111
- def byonoy_get_device_parts_aligned(
112
- self, device_handle: int
113
- ) -> Tuple[ErrorCode, bool]:
120
+ def get_device_uptime(self, device_handle: int) -> Tuple[ErrorCode, int]:
121
+ ...
122
+
123
+ def get_device_slot_status(self, device_handle: int) -> Tuple[ErrorCode, SlotState]:
114
124
  ...
115
125
 
116
- def byonoy_abs96_get_available_wavelengths(
126
+ def get_device_parts_aligned(self, device_handle: int) -> Tuple[ErrorCode, bool]:
127
+ ...
128
+
129
+ def abs96_get_available_wavelengths(
117
130
  self, device_handle: int
118
131
  ) -> Tuple[ErrorCode, List[int]]:
119
132
  ...
120
133
 
121
- def byonoy_abs96_initialize_single_measurement(
122
- self, device_handle: int, conf: MeasurementConfig
134
+ def abs96_initialize_single_measurement(
135
+ self, device_handle: int, conf: SingleMeasurementConfig
136
+ ) -> ErrorCode:
137
+ ...
138
+
139
+ def abs96_initialize_multiple_measurement(
140
+ self, device_handle: int, conf: MultiMeasurementConfig
123
141
  ) -> ErrorCode:
124
142
  ...
125
143
 
126
- def byonoy_abs96_single_measure(
127
- self, device_handle: int, conf: MeasurementConfig
144
+ def abs96_single_measure(
145
+ self, device_handle: int, conf: SingleMeasurementConfig
128
146
  ) -> Tuple[ErrorCode, List[float]]:
129
147
  ...
130
148
 
131
- def byonoy_available_devices(self) -> List[Device]:
149
+ def abs96_multiple_measure(
150
+ self, device_handle: int, conf: MultiMeasurementConfig
151
+ ) -> Tuple[ErrorCode, List[List[float]]]:
132
152
  ...
153
+
154
+ def available_devices(self) -> List[Device]:
155
+ ...
156
+
157
+
158
+ MeasurementConfig = Union[
159
+ AbsorbanceHidInterface.SingleMeasurementConfig,
160
+ AbsorbanceHidInterface.MultiMeasurementConfig,
161
+ ]
@@ -1,18 +1,27 @@
1
- from typing import Dict, List, Optional
1
+ from typing import Dict, List, Optional, Tuple
2
2
  from opentrons.util.async_helpers import ensure_yield
3
3
 
4
4
  from opentrons.drivers.types import (
5
+ ABSMeasurementMode,
5
6
  AbsorbanceReaderLidStatus,
6
7
  AbsorbanceReaderDeviceState,
8
+ AbsorbanceReaderPlatePresence,
7
9
  )
8
10
 
9
11
  from .abstract import AbstractAbsorbanceReaderDriver
10
12
 
11
13
 
12
14
  class SimulatingDriver(AbstractAbsorbanceReaderDriver):
13
- def __init__(self, serial_number: Optional[str] = None) -> None:
15
+ def __init__(
16
+ self, model: Optional[str] = None, serial_number: Optional[str] = None
17
+ ) -> None:
18
+ self._lid_status = AbsorbanceReaderLidStatus.ON
19
+ self._model = model if model else "absorbanceReaderV1"
14
20
  self._serial_number = serial_number
15
21
 
22
+ def model(self) -> str:
23
+ return self._model
24
+
16
25
  @ensure_yield
17
26
  async def get_device_info(self) -> Dict[str, str]:
18
27
  """Get device info"""
@@ -39,20 +48,37 @@ class SimulatingDriver(AbstractAbsorbanceReaderDriver):
39
48
 
40
49
  @ensure_yield
41
50
  async def get_lid_status(self) -> AbsorbanceReaderLidStatus:
42
- return AbsorbanceReaderLidStatus.ON
51
+ return self._lid_status
43
52
 
44
53
  @ensure_yield
45
54
  async def get_available_wavelengths(self) -> List[int]:
46
55
  return [450, 570, 600, 650]
47
56
 
48
57
  @ensure_yield
49
- async def get_single_measurement(self, wavelength: int) -> List[float]:
50
- return [0.0]
58
+ async def get_measurement(self) -> List[List[float]]:
59
+ return [[0.0]]
51
60
 
52
61
  @ensure_yield
53
- async def initialize_measurement(self, wavelength: int) -> None:
62
+ async def initialize_measurement(
63
+ self,
64
+ wavelengths: List[int],
65
+ mode: ABSMeasurementMode = ABSMeasurementMode.SINGLE,
66
+ reference_wavelength: Optional[int] = None,
67
+ ) -> None:
54
68
  pass
55
69
 
70
+ @ensure_yield
71
+ async def get_uptime(self) -> int:
72
+ return 10
73
+
74
+ @ensure_yield
75
+ async def update_firmware(self, firmware_file_path: str) -> Tuple[bool, str]:
76
+ return True, ""
77
+
56
78
  @ensure_yield
57
79
  async def get_status(self) -> AbsorbanceReaderDeviceState:
58
80
  return AbsorbanceReaderDeviceState.OK
81
+
82
+ @ensure_yield
83
+ async def get_plate_presence(self) -> AbsorbanceReaderPlatePresence:
84
+ return AbsorbanceReaderPlatePresence.PRESENT
@@ -1,6 +1,6 @@
1
1
  """ Type definitions for modules in this tree """
2
2
  from dataclasses import dataclass
3
- from typing import Dict, NamedTuple, Optional
3
+ from typing import Any, Dict, List, NamedTuple, Optional
4
4
  from enum import Enum
5
5
 
6
6
 
@@ -83,3 +83,25 @@ class AbsorbanceReaderDeviceState(str, Enum):
83
83
  OK = "ok"
84
84
  BROKEN_FW = "broken_fw"
85
85
  ERROR = "error"
86
+
87
+
88
+ class ABSMeasurementMode(Enum):
89
+ """The current mode configured for reading the Absorbance Reader."""
90
+
91
+ SINGLE = "single"
92
+ MULTI = "multi"
93
+
94
+
95
+ @dataclass
96
+ class ABSMeasurementConfig:
97
+ measure_mode: ABSMeasurementMode
98
+ sample_wavelengths: List[int]
99
+ reference_wavelength: Optional[int]
100
+
101
+ @property
102
+ def data(self) -> Dict[str, Any]:
103
+ return {
104
+ "measureMode": self.measure_mode.value,
105
+ "sampleWavelengths": self.sample_wavelengths,
106
+ "referenceWavelength": self.reference_wavelength,
107
+ }
opentrons/execute.py CHANGED
@@ -546,6 +546,7 @@ def _create_live_context_pe(
546
546
  hardware_api=hardware_api_wrapped,
547
547
  config=_get_protocol_engine_config(),
548
548
  deck_configuration=entrypoint_util.get_deck_configuration(),
549
+ file_provider=None,
549
550
  error_recovery_policy=error_recovery_policy.never_recover,
550
551
  drop_tips_after_run=False,
551
552
  post_run_hardware_state=PostRunHardwareState.STAY_ENGAGED_IN_PLACE,
@@ -609,8 +610,6 @@ def _run_file_non_pe(
609
610
 
610
611
  context.home()
611
612
  try:
612
- # TODO (spp, 2024-03-18): use true run-time param overrides once enabled
613
- # for cli protocol simulation/ execution
614
613
  execute_apiv2.run_protocol(
615
614
  protocol, context, run_time_parameters_with_overrides=None
616
615
  )
@@ -626,6 +625,7 @@ def _run_file_pe(
626
625
  """Run a protocol file with Protocol Engine."""
627
626
 
628
627
  async def run(protocol_source: ProtocolSource) -> None:
628
+ # TODO (spp, 2024-03-18): use run-time param overrides once enabled for cli protocol execution
629
629
  hardware_api_wrapped = hardware_api.wrapped()
630
630
  protocol_engine = await create_protocol_engine(
631
631
  hardware_api=hardware_api_wrapped,
@@ -1189,11 +1189,6 @@ class API(
1189
1189
 
1190
1190
  await self.retract(mount, spec.retract_target)
1191
1191
 
1192
- def cache_tip(self, mount: top_types.Mount, tip_length: float) -> None:
1193
- instrument = self.get_pipette(mount)
1194
- instrument.add_tip(tip_length=tip_length)
1195
- instrument.set_current_volume(0)
1196
-
1197
1192
  async def pick_up_tip(
1198
1193
  self,
1199
1194
  mount: top_types.Mount,
@@ -1241,10 +1236,10 @@ class API(
1241
1236
  if prep_after:
1242
1237
  await self.prepare_for_aspirate(mount)
1243
1238
 
1244
- async def drop_tip(self, mount: top_types.Mount, home_after: bool = True) -> None:
1245
- """Drop tip at the current location."""
1246
-
1247
- spec, _remove = self.plan_check_drop_tip(mount, home_after)
1239
+ async def tip_drop_moves(
1240
+ self, mount: top_types.Mount, home_after: bool = True
1241
+ ) -> None:
1242
+ spec, _ = self.plan_check_drop_tip(mount, home_after)
1248
1243
 
1249
1244
  for move in spec.drop_moves:
1250
1245
  self._backend.set_active_current(move.current)
@@ -1272,7 +1267,20 @@ class API(
1272
1267
  await self.move_rel(mount, shake[0], speed=shake[1])
1273
1268
 
1274
1269
  self._backend.set_active_current(spec.ending_current)
1275
- _remove()
1270
+
1271
+ async def drop_tip(self, mount: top_types.Mount, home_after: bool = True) -> None:
1272
+ """Drop tip at the current location."""
1273
+ await self.tip_drop_moves(mount, home_after)
1274
+
1275
+ # todo(mm, 2024-10-17): Ideally, callers would be able to replicate the behavior
1276
+ # of this method via self.drop_tip_moves() plus other public methods. This
1277
+ # currently prevents that: there is no public equivalent for
1278
+ # instrument.set_current_volume().
1279
+ instrument = self.get_pipette(mount)
1280
+ instrument.set_current_volume(0)
1281
+
1282
+ self.set_current_tiprack_diameter(mount, 0.0)
1283
+ self.remove_tip(mount)
1276
1284
 
1277
1285
  async def create_simulating_module(
1278
1286
  self,
@@ -57,7 +57,7 @@ class Controller:
57
57
  """
58
58
 
59
59
  @classmethod
60
- async def build(cls, config: RobotConfig) -> Controller:
60
+ async def build(cls, config: Optional[RobotConfig]) -> Controller:
61
61
  """Build a Controller instance.
62
62
 
63
63
  Use this factory method rather than the initializer to handle proper
@@ -65,12 +65,13 @@ class Controller:
65
65
 
66
66
  :param config: A loaded robot config.
67
67
  """
68
+
68
69
  gpio = build_gpio_chardev("gpiochip0")
69
70
  gpio.config_by_board_rev()
70
71
  await gpio.setup()
71
72
  return cls(config, gpio)
72
73
 
73
- def __init__(self, config: RobotConfig, gpio: GPIODriverLike):
74
+ def __init__(self, config: Optional[RobotConfig], gpio: GPIODriverLike):
74
75
  """Build a Controller instance.
75
76
 
76
77
  Always prefer using :py:meth:`.build` to create an instance of this class. For
@@ -15,7 +15,7 @@ from typing import (
15
15
  from opentrons_shared_data.pipette.types import (
16
16
  PipetteName,
17
17
  )
18
- from opentrons.config.types import GantryLoad, OutputOptions
18
+ from opentrons.config.types import GantryLoad
19
19
  from opentrons.hardware_control.types import (
20
20
  BoardRevision,
21
21
  Axis,
@@ -38,6 +38,8 @@ from opentrons.hardware_control.types import (
38
38
  StatusBarState,
39
39
  )
40
40
  from opentrons.hardware_control.module_control import AttachedModulesControl
41
+ from opentrons_hardware.firmware_bindings.constants import SensorId
42
+ from opentrons_hardware.sensors.types import SensorDataType
41
43
  from ..dev_types import OT3AttachedInstruments
42
44
  from .types import HWStopCondition
43
45
 
@@ -54,6 +56,10 @@ class FlexBackend(Protocol):
54
56
  def restore_system_constraints(self) -> AsyncIterator[None]:
55
57
  ...
56
58
 
59
+ @asynccontextmanager
60
+ def grab_pressure(self, channels: int, mount: OT3Mount) -> AsyncIterator[None]:
61
+ ...
62
+
57
63
  def update_constraints_for_gantry_load(self, gantry_load: GantryLoad) -> None:
58
64
  ...
59
65
 
@@ -147,10 +153,12 @@ class FlexBackend(Protocol):
147
153
  plunger_speed: float,
148
154
  threshold_pascals: float,
149
155
  plunger_impulse_time: float,
150
- output_format: OutputOptions = OutputOptions.can_bus_only,
151
- data_files: Optional[Dict[InstrumentProbeType, str]] = None,
156
+ num_baseline_reads: int,
152
157
  probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
153
158
  force_both_sensors: bool = False,
159
+ response_queue: Optional[
160
+ asyncio.Queue[Dict[SensorId, List[SensorDataType]]]
161
+ ] = None,
154
162
  ) -> float:
155
163
  ...
156
164
 
@@ -366,8 +374,6 @@ class FlexBackend(Protocol):
366
374
  speed_mm_per_s: float,
367
375
  sensor_threshold_pf: float,
368
376
  probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
369
- output_format: OutputOptions = OutputOptions.sync_only,
370
- data_files: Optional[Dict[InstrumentProbeType, str]] = None,
371
377
  ) -> bool:
372
378
  ...
373
379
 
@@ -25,7 +25,7 @@ from typing import (
25
25
  Union,
26
26
  Mapping,
27
27
  )
28
- from opentrons.config.types import OT3Config, GantryLoad, OutputOptions
28
+ from opentrons.config.types import OT3Config, GantryLoad
29
29
  from opentrons.config import gripper_config
30
30
  from .ot3utils import (
31
31
  axis_convert,
@@ -102,7 +102,9 @@ from opentrons_hardware.firmware_bindings.constants import (
102
102
  NodeId,
103
103
  PipetteName as FirmwarePipetteName,
104
104
  ErrorCode,
105
+ SensorId,
105
106
  )
107
+ from opentrons_hardware.sensors.types import SensorDataType
106
108
  from opentrons_hardware.firmware_bindings.messages.message_definitions import (
107
109
  StopRequest,
108
110
  )
@@ -161,6 +163,7 @@ from opentrons_hardware.hardware_control.tool_sensors import (
161
163
  capacitive_pass,
162
164
  liquid_probe,
163
165
  check_overpressure,
166
+ grab_pressure,
164
167
  )
165
168
  from opentrons_hardware.hardware_control.rear_panel_settings import (
166
169
  get_door_state,
@@ -369,6 +372,14 @@ class OT3Controller(FlexBackend):
369
372
  self._move_manager.update_constraints(old_system_constraints)
370
373
  log.debug(f"Restore previous system constraints: {old_system_constraints}")
371
374
 
375
+ @asynccontextmanager
376
+ async def grab_pressure(
377
+ self, channels: int, mount: OT3Mount
378
+ ) -> AsyncIterator[None]:
379
+ tool = axis_to_node(Axis.of_main_tool_actuator(mount))
380
+ async with grab_pressure(channels, tool, self._messenger):
381
+ yield
382
+
372
383
  def update_constraints_for_calibration_with_gantry_load(
373
384
  self,
374
385
  gantry_load: GantryLoad,
@@ -1358,28 +1369,15 @@ class OT3Controller(FlexBackend):
1358
1369
  plunger_speed: float,
1359
1370
  threshold_pascals: float,
1360
1371
  plunger_impulse_time: float,
1361
- output_option: OutputOptions = OutputOptions.can_bus_only,
1362
- data_files: Optional[Dict[InstrumentProbeType, str]] = None,
1372
+ num_baseline_reads: int,
1363
1373
  probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
1364
1374
  force_both_sensors: bool = False,
1375
+ response_queue: Optional[
1376
+ asyncio.Queue[Dict[SensorId, List[SensorDataType]]]
1377
+ ] = None,
1365
1378
  ) -> float:
1366
1379
  head_node = axis_to_node(Axis.by_mount(mount))
1367
1380
  tool = sensor_node_for_pipette(OT3Mount(mount.value))
1368
- csv_output = bool(output_option.value & OutputOptions.stream_to_csv.value)
1369
- sync_buffer_output = bool(
1370
- output_option.value & OutputOptions.sync_buffer_to_csv.value
1371
- )
1372
- can_bus_only_output = bool(
1373
- output_option.value & OutputOptions.can_bus_only.value
1374
- )
1375
- data_files_transposed = (
1376
- None
1377
- if data_files is None
1378
- else {
1379
- sensor_id_for_instrument(probe): data_files[probe]
1380
- for probe in data_files.keys()
1381
- }
1382
- )
1383
1381
  positions = await liquid_probe(
1384
1382
  messenger=self._messenger,
1385
1383
  tool=tool,
@@ -1389,12 +1387,10 @@ class OT3Controller(FlexBackend):
1389
1387
  mount_speed=mount_speed,
1390
1388
  threshold_pascals=threshold_pascals,
1391
1389
  plunger_impulse_time=plunger_impulse_time,
1392
- csv_output=csv_output,
1393
- sync_buffer_output=sync_buffer_output,
1394
- can_bus_only_output=can_bus_only_output,
1395
- data_files=data_files_transposed,
1390
+ num_baseline_reads=num_baseline_reads,
1396
1391
  sensor_id=sensor_id_for_instrument(probe),
1397
1392
  force_both_sensors=force_both_sensors,
1393
+ response_queue=response_queue,
1398
1394
  )
1399
1395
  for node, point in positions.items():
1400
1396
  self._position.update({node: point.motor_position})
@@ -1421,41 +1417,13 @@ class OT3Controller(FlexBackend):
1421
1417
  speed_mm_per_s: float,
1422
1418
  sensor_threshold_pf: float,
1423
1419
  probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
1424
- output_option: OutputOptions = OutputOptions.sync_only,
1425
- data_files: Optional[Dict[InstrumentProbeType, str]] = None,
1426
1420
  ) -> bool:
1427
- if output_option == OutputOptions.sync_buffer_to_csv:
1428
- assert (
1429
- self._subsystem_manager.device_info[
1430
- SubSystem.of_mount(mount)
1431
- ].revision.tertiary
1432
- == "1"
1433
- )
1434
- csv_output = bool(output_option.value & OutputOptions.stream_to_csv.value)
1435
- sync_buffer_output = bool(
1436
- output_option.value & OutputOptions.sync_buffer_to_csv.value
1437
- )
1438
- can_bus_only_output = bool(
1439
- output_option.value & OutputOptions.can_bus_only.value
1440
- )
1441
- data_files_transposed = (
1442
- None
1443
- if data_files is None
1444
- else {
1445
- sensor_id_for_instrument(probe): data_files[probe]
1446
- for probe in data_files.keys()
1447
- }
1448
- )
1449
1421
  status = await capacitive_probe(
1450
1422
  messenger=self._messenger,
1451
1423
  tool=sensor_node_for_mount(mount),
1452
1424
  mover=axis_to_node(moving),
1453
1425
  distance=distance_mm,
1454
1426
  mount_speed=speed_mm_per_s,
1455
- csv_output=csv_output,
1456
- sync_buffer_output=sync_buffer_output,
1457
- can_bus_only_output=can_bus_only_output,
1458
- data_files=data_files_transposed,
1459
1427
  sensor_id=sensor_id_for_instrument(probe),
1460
1428
  relative_threshold_pf=sensor_threshold_pf,
1461
1429
  )
@@ -17,7 +17,7 @@ from typing import (
17
17
  Mapping,
18
18
  )
19
19
 
20
- from opentrons.config.types import OT3Config, GantryLoad, OutputOptions
20
+ from opentrons.config.types import OT3Config, GantryLoad
21
21
  from opentrons.config import gripper_config
22
22
 
23
23
  from opentrons.hardware_control.module_control import AttachedModulesControl
@@ -63,7 +63,8 @@ from opentrons.hardware_control.dev_types import (
63
63
  from opentrons.util.async_helpers import ensure_yield
64
64
  from .types import HWStopCondition
65
65
  from .flex_protocol import FlexBackend
66
-
66
+ from opentrons_hardware.firmware_bindings.constants import SensorId
67
+ from opentrons_hardware.sensors.types import SensorDataType
67
68
 
68
69
  log = logging.getLogger(__name__)
69
70
 
@@ -346,10 +347,12 @@ class OT3Simulator(FlexBackend):
346
347
  plunger_speed: float,
347
348
  threshold_pascals: float,
348
349
  plunger_impulse_time: float,
349
- output_format: OutputOptions = OutputOptions.can_bus_only,
350
- data_files: Optional[Dict[InstrumentProbeType, str]] = None,
350
+ num_baseline_reads: int,
351
351
  probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
352
352
  force_both_sensors: bool = False,
353
+ response_queue: Optional[
354
+ asyncio.Queue[Dict[SensorId, List[SensorDataType]]]
355
+ ] = None,
353
356
  ) -> float:
354
357
  z_axis = Axis.by_mount(mount)
355
358
  pos = self._position
@@ -749,8 +752,6 @@ class OT3Simulator(FlexBackend):
749
752
  speed_mm_per_s: float,
750
753
  sensor_threshold_pf: float,
751
754
  probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
752
- output_format: OutputOptions = OutputOptions.sync_only,
753
- data_files: Optional[Dict[InstrumentProbeType, str]] = None,
754
755
  ) -> bool:
755
756
  self._position[moving] += distance_mm
756
757
  return True