opentrons 8.6.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of opentrons might be problematic. Click here for more details.

Files changed (600) hide show
  1. opentrons/__init__.py +150 -0
  2. opentrons/_version.py +34 -0
  3. opentrons/calibration_storage/__init__.py +54 -0
  4. opentrons/calibration_storage/deck_configuration.py +62 -0
  5. opentrons/calibration_storage/encoder_decoder.py +31 -0
  6. opentrons/calibration_storage/file_operators.py +142 -0
  7. opentrons/calibration_storage/helpers.py +103 -0
  8. opentrons/calibration_storage/ot2/__init__.py +34 -0
  9. opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
  10. opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
  11. opentrons/calibration_storage/ot2/models/__init__.py +0 -0
  12. opentrons/calibration_storage/ot2/models/v1.py +149 -0
  13. opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
  14. opentrons/calibration_storage/ot2/tip_length.py +281 -0
  15. opentrons/calibration_storage/ot3/__init__.py +31 -0
  16. opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
  17. opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
  18. opentrons/calibration_storage/ot3/models/__init__.py +0 -0
  19. opentrons/calibration_storage/ot3/models/v1.py +122 -0
  20. opentrons/calibration_storage/ot3/module_offset.py +138 -0
  21. opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
  22. opentrons/calibration_storage/types.py +45 -0
  23. opentrons/cli/__init__.py +21 -0
  24. opentrons/cli/__main__.py +5 -0
  25. opentrons/cli/analyze.py +501 -0
  26. opentrons/config/__init__.py +631 -0
  27. opentrons/config/advanced_settings.py +871 -0
  28. opentrons/config/defaults_ot2.py +214 -0
  29. opentrons/config/defaults_ot3.py +499 -0
  30. opentrons/config/feature_flags.py +86 -0
  31. opentrons/config/gripper_config.py +55 -0
  32. opentrons/config/reset.py +203 -0
  33. opentrons/config/robot_configs.py +187 -0
  34. opentrons/config/types.py +183 -0
  35. opentrons/drivers/__init__.py +0 -0
  36. opentrons/drivers/absorbance_reader/__init__.py +11 -0
  37. opentrons/drivers/absorbance_reader/abstract.py +72 -0
  38. opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
  39. opentrons/drivers/absorbance_reader/driver.py +81 -0
  40. opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
  41. opentrons/drivers/absorbance_reader/simulator.py +84 -0
  42. opentrons/drivers/asyncio/__init__.py +0 -0
  43. opentrons/drivers/asyncio/communication/__init__.py +22 -0
  44. opentrons/drivers/asyncio/communication/async_serial.py +183 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +552 -0
  47. opentrons/drivers/command_builder.py +102 -0
  48. opentrons/drivers/flex_stacker/__init__.py +13 -0
  49. opentrons/drivers/flex_stacker/abstract.py +214 -0
  50. opentrons/drivers/flex_stacker/driver.py +768 -0
  51. opentrons/drivers/flex_stacker/errors.py +68 -0
  52. opentrons/drivers/flex_stacker/simulator.py +309 -0
  53. opentrons/drivers/flex_stacker/types.py +367 -0
  54. opentrons/drivers/flex_stacker/utils.py +19 -0
  55. opentrons/drivers/heater_shaker/__init__.py +5 -0
  56. opentrons/drivers/heater_shaker/abstract.py +76 -0
  57. opentrons/drivers/heater_shaker/driver.py +204 -0
  58. opentrons/drivers/heater_shaker/simulator.py +94 -0
  59. opentrons/drivers/mag_deck/__init__.py +6 -0
  60. opentrons/drivers/mag_deck/abstract.py +44 -0
  61. opentrons/drivers/mag_deck/driver.py +208 -0
  62. opentrons/drivers/mag_deck/simulator.py +63 -0
  63. opentrons/drivers/rpi_drivers/__init__.py +33 -0
  64. opentrons/drivers/rpi_drivers/dev_types.py +94 -0
  65. opentrons/drivers/rpi_drivers/gpio.py +282 -0
  66. opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
  67. opentrons/drivers/rpi_drivers/interfaces.py +15 -0
  68. opentrons/drivers/rpi_drivers/types.py +364 -0
  69. opentrons/drivers/rpi_drivers/usb.py +102 -0
  70. opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
  71. opentrons/drivers/serial_communication.py +151 -0
  72. opentrons/drivers/smoothie_drivers/__init__.py +4 -0
  73. opentrons/drivers/smoothie_drivers/connection.py +51 -0
  74. opentrons/drivers/smoothie_drivers/constants.py +121 -0
  75. opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
  76. opentrons/drivers/smoothie_drivers/errors.py +49 -0
  77. opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
  78. opentrons/drivers/smoothie_drivers/simulator.py +99 -0
  79. opentrons/drivers/smoothie_drivers/types.py +16 -0
  80. opentrons/drivers/temp_deck/__init__.py +10 -0
  81. opentrons/drivers/temp_deck/abstract.py +54 -0
  82. opentrons/drivers/temp_deck/driver.py +197 -0
  83. opentrons/drivers/temp_deck/simulator.py +57 -0
  84. opentrons/drivers/thermocycler/__init__.py +12 -0
  85. opentrons/drivers/thermocycler/abstract.py +99 -0
  86. opentrons/drivers/thermocycler/driver.py +395 -0
  87. opentrons/drivers/thermocycler/simulator.py +126 -0
  88. opentrons/drivers/types.py +107 -0
  89. opentrons/drivers/utils.py +222 -0
  90. opentrons/execute.py +742 -0
  91. opentrons/hardware_control/__init__.py +65 -0
  92. opentrons/hardware_control/__main__.py +77 -0
  93. opentrons/hardware_control/adapters.py +98 -0
  94. opentrons/hardware_control/api.py +1347 -0
  95. opentrons/hardware_control/backends/__init__.py +7 -0
  96. opentrons/hardware_control/backends/controller.py +400 -0
  97. opentrons/hardware_control/backends/errors.py +9 -0
  98. opentrons/hardware_control/backends/estop_state.py +164 -0
  99. opentrons/hardware_control/backends/flex_protocol.py +497 -0
  100. opentrons/hardware_control/backends/ot3controller.py +1930 -0
  101. opentrons/hardware_control/backends/ot3simulator.py +900 -0
  102. opentrons/hardware_control/backends/ot3utils.py +664 -0
  103. opentrons/hardware_control/backends/simulator.py +442 -0
  104. opentrons/hardware_control/backends/status_bar_state.py +240 -0
  105. opentrons/hardware_control/backends/subsystem_manager.py +431 -0
  106. opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
  107. opentrons/hardware_control/backends/types.py +14 -0
  108. opentrons/hardware_control/constants.py +6 -0
  109. opentrons/hardware_control/dev_types.py +125 -0
  110. opentrons/hardware_control/emulation/__init__.py +0 -0
  111. opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
  112. opentrons/hardware_control/emulation/app.py +56 -0
  113. opentrons/hardware_control/emulation/connection_handler.py +38 -0
  114. opentrons/hardware_control/emulation/heater_shaker.py +150 -0
  115. opentrons/hardware_control/emulation/magdeck.py +60 -0
  116. opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
  117. opentrons/hardware_control/emulation/module_server/client.py +78 -0
  118. opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
  119. opentrons/hardware_control/emulation/module_server/models.py +31 -0
  120. opentrons/hardware_control/emulation/module_server/server.py +110 -0
  121. opentrons/hardware_control/emulation/parser.py +74 -0
  122. opentrons/hardware_control/emulation/proxy.py +241 -0
  123. opentrons/hardware_control/emulation/run_emulator.py +68 -0
  124. opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
  125. opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
  126. opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
  127. opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
  128. opentrons/hardware_control/emulation/settings.py +119 -0
  129. opentrons/hardware_control/emulation/simulations.py +133 -0
  130. opentrons/hardware_control/emulation/smoothie.py +192 -0
  131. opentrons/hardware_control/emulation/tempdeck.py +69 -0
  132. opentrons/hardware_control/emulation/thermocycler.py +128 -0
  133. opentrons/hardware_control/emulation/types.py +10 -0
  134. opentrons/hardware_control/emulation/util.py +38 -0
  135. opentrons/hardware_control/errors.py +43 -0
  136. opentrons/hardware_control/execution_manager.py +164 -0
  137. opentrons/hardware_control/instruments/__init__.py +5 -0
  138. opentrons/hardware_control/instruments/instrument_abc.py +39 -0
  139. opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
  140. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
  141. opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
  142. opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
  143. opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
  144. opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
  145. opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
  146. opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
  147. opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
  148. opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
  149. opentrons/hardware_control/module_control.py +332 -0
  150. opentrons/hardware_control/modules/__init__.py +69 -0
  151. opentrons/hardware_control/modules/absorbance_reader.py +373 -0
  152. opentrons/hardware_control/modules/errors.py +7 -0
  153. opentrons/hardware_control/modules/flex_stacker.py +948 -0
  154. opentrons/hardware_control/modules/heater_shaker.py +426 -0
  155. opentrons/hardware_control/modules/lid_temp_status.py +35 -0
  156. opentrons/hardware_control/modules/magdeck.py +233 -0
  157. opentrons/hardware_control/modules/mod_abc.py +245 -0
  158. opentrons/hardware_control/modules/module_calibration.py +93 -0
  159. opentrons/hardware_control/modules/plate_temp_status.py +61 -0
  160. opentrons/hardware_control/modules/tempdeck.py +299 -0
  161. opentrons/hardware_control/modules/thermocycler.py +731 -0
  162. opentrons/hardware_control/modules/types.py +417 -0
  163. opentrons/hardware_control/modules/update.py +255 -0
  164. opentrons/hardware_control/modules/utils.py +73 -0
  165. opentrons/hardware_control/motion_utilities.py +318 -0
  166. opentrons/hardware_control/nozzle_manager.py +422 -0
  167. opentrons/hardware_control/ot3_calibration.py +1171 -0
  168. opentrons/hardware_control/ot3api.py +3227 -0
  169. opentrons/hardware_control/pause_manager.py +31 -0
  170. opentrons/hardware_control/poller.py +112 -0
  171. opentrons/hardware_control/protocols/__init__.py +106 -0
  172. opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
  173. opentrons/hardware_control/protocols/calibratable.py +45 -0
  174. opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
  175. opentrons/hardware_control/protocols/configurable.py +48 -0
  176. opentrons/hardware_control/protocols/event_sourcer.py +18 -0
  177. opentrons/hardware_control/protocols/execution_controllable.py +33 -0
  178. opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
  179. opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
  180. opentrons/hardware_control/protocols/gripper_controller.py +55 -0
  181. opentrons/hardware_control/protocols/hardware_manager.py +51 -0
  182. opentrons/hardware_control/protocols/identifiable.py +16 -0
  183. opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
  184. opentrons/hardware_control/protocols/liquid_handler.py +266 -0
  185. opentrons/hardware_control/protocols/module_provider.py +16 -0
  186. opentrons/hardware_control/protocols/motion_controller.py +243 -0
  187. opentrons/hardware_control/protocols/position_estimator.py +45 -0
  188. opentrons/hardware_control/protocols/simulatable.py +10 -0
  189. opentrons/hardware_control/protocols/stoppable.py +9 -0
  190. opentrons/hardware_control/protocols/types.py +27 -0
  191. opentrons/hardware_control/robot_calibration.py +224 -0
  192. opentrons/hardware_control/scripts/README.md +28 -0
  193. opentrons/hardware_control/scripts/__init__.py +1 -0
  194. opentrons/hardware_control/scripts/gripper_control.py +208 -0
  195. opentrons/hardware_control/scripts/ot3gripper +7 -0
  196. opentrons/hardware_control/scripts/ot3repl +7 -0
  197. opentrons/hardware_control/scripts/repl.py +187 -0
  198. opentrons/hardware_control/scripts/tc_control.py +97 -0
  199. opentrons/hardware_control/simulator_setup.py +260 -0
  200. opentrons/hardware_control/thread_manager.py +431 -0
  201. opentrons/hardware_control/threaded_async_lock.py +97 -0
  202. opentrons/hardware_control/types.py +792 -0
  203. opentrons/hardware_control/util.py +234 -0
  204. opentrons/legacy_broker.py +53 -0
  205. opentrons/legacy_commands/__init__.py +1 -0
  206. opentrons/legacy_commands/commands.py +483 -0
  207. opentrons/legacy_commands/helpers.py +153 -0
  208. opentrons/legacy_commands/module_commands.py +215 -0
  209. opentrons/legacy_commands/protocol_commands.py +54 -0
  210. opentrons/legacy_commands/publisher.py +155 -0
  211. opentrons/legacy_commands/robot_commands.py +51 -0
  212. opentrons/legacy_commands/types.py +1115 -0
  213. opentrons/motion_planning/__init__.py +32 -0
  214. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  215. opentrons/motion_planning/deck_conflict.py +396 -0
  216. opentrons/motion_planning/errors.py +35 -0
  217. opentrons/motion_planning/types.py +42 -0
  218. opentrons/motion_planning/waypoints.py +218 -0
  219. opentrons/ordered_set.py +138 -0
  220. opentrons/protocol_api/__init__.py +105 -0
  221. opentrons/protocol_api/_liquid.py +157 -0
  222. opentrons/protocol_api/_liquid_properties.py +814 -0
  223. opentrons/protocol_api/_nozzle_layout.py +31 -0
  224. opentrons/protocol_api/_parameter_context.py +300 -0
  225. opentrons/protocol_api/_parameters.py +31 -0
  226. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  227. opentrons/protocol_api/_types.py +43 -0
  228. opentrons/protocol_api/config.py +23 -0
  229. opentrons/protocol_api/core/__init__.py +23 -0
  230. opentrons/protocol_api/core/common.py +33 -0
  231. opentrons/protocol_api/core/core_map.py +74 -0
  232. opentrons/protocol_api/core/engine/__init__.py +22 -0
  233. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  234. opentrons/protocol_api/core/engine/deck_conflict.py +348 -0
  235. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  236. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  237. opentrons/protocol_api/core/engine/labware.py +238 -0
  238. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  239. opentrons/protocol_api/core/engine/module_core.py +1025 -0
  240. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  241. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  242. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  243. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  244. opentrons/protocol_api/core/engine/robot.py +139 -0
  245. opentrons/protocol_api/core/engine/stringify.py +74 -0
  246. opentrons/protocol_api/core/engine/transfer_components_executor.py +990 -0
  247. opentrons/protocol_api/core/engine/well.py +241 -0
  248. opentrons/protocol_api/core/instrument.py +459 -0
  249. opentrons/protocol_api/core/labware.py +151 -0
  250. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  251. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  252. opentrons/protocol_api/core/legacy/deck.py +369 -0
  253. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  254. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  255. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  256. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  257. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  258. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  259. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  260. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  261. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  262. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  263. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  265. opentrons/protocol_api/core/module.py +484 -0
  266. opentrons/protocol_api/core/protocol.py +311 -0
  267. opentrons/protocol_api/core/robot.py +51 -0
  268. opentrons/protocol_api/core/well.py +116 -0
  269. opentrons/protocol_api/core/well_grid.py +45 -0
  270. opentrons/protocol_api/create_protocol_context.py +177 -0
  271. opentrons/protocol_api/deck.py +223 -0
  272. opentrons/protocol_api/disposal_locations.py +244 -0
  273. opentrons/protocol_api/instrument_context.py +3212 -0
  274. opentrons/protocol_api/labware.py +1579 -0
  275. opentrons/protocol_api/module_contexts.py +1425 -0
  276. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  277. opentrons/protocol_api/protocol_context.py +1688 -0
  278. opentrons/protocol_api/robot_context.py +303 -0
  279. opentrons/protocol_api/validation.py +761 -0
  280. opentrons/protocol_engine/__init__.py +155 -0
  281. opentrons/protocol_engine/actions/__init__.py +65 -0
  282. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  283. opentrons/protocol_engine/actions/action_handler.py +13 -0
  284. opentrons/protocol_engine/actions/actions.py +302 -0
  285. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  286. opentrons/protocol_engine/clients/__init__.py +5 -0
  287. opentrons/protocol_engine/clients/sync_client.py +174 -0
  288. opentrons/protocol_engine/clients/transports.py +197 -0
  289. opentrons/protocol_engine/commands/__init__.py +757 -0
  290. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  296. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  297. opentrons/protocol_engine/commands/aspirate.py +244 -0
  298. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  299. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  300. opentrons/protocol_engine/commands/blow_out.py +146 -0
  301. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  302. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  303. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  306. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  307. opentrons/protocol_engine/commands/command.py +308 -0
  308. opentrons/protocol_engine/commands/command_unions.py +974 -0
  309. opentrons/protocol_engine/commands/comment.py +57 -0
  310. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  311. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  312. opentrons/protocol_engine/commands/custom.py +67 -0
  313. opentrons/protocol_engine/commands/dispense.py +194 -0
  314. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  315. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  316. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  317. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  318. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  319. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  320. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  321. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  322. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  323. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  324. opentrons/protocol_engine/commands/flex_stacker/store.py +326 -0
  325. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  326. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  327. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  328. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  329. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  330. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  331. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  333. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  334. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  336. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  337. opentrons/protocol_engine/commands/home.py +100 -0
  338. opentrons/protocol_engine/commands/identify_module.py +86 -0
  339. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  340. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  341. opentrons/protocol_engine/commands/load_labware.py +210 -0
  342. opentrons/protocol_engine/commands/load_lid.py +154 -0
  343. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  344. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  345. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  346. opentrons/protocol_engine/commands/load_module.py +223 -0
  347. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  348. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  349. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  350. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  351. opentrons/protocol_engine/commands/move_labware.py +546 -0
  352. opentrons/protocol_engine/commands/move_relative.py +102 -0
  353. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  355. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  356. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  357. opentrons/protocol_engine/commands/movement_common.py +338 -0
  358. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  359. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  360. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  361. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  362. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  363. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  364. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  365. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  366. opentrons/protocol_engine/commands/robot/common.py +18 -0
  367. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  369. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  370. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  371. opentrons/protocol_engine/commands/save_position.py +109 -0
  372. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  373. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  374. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  375. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  376. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  377. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  378. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  379. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  380. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  381. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  384. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  386. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  388. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  390. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  391. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  392. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  401. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  402. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  403. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  404. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  405. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  406. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  407. opentrons/protocol_engine/engine_support.py +28 -0
  408. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  409. opentrons/protocol_engine/errors/__init__.py +191 -0
  410. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  411. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  412. opentrons/protocol_engine/execution/__init__.py +50 -0
  413. opentrons/protocol_engine/execution/command_executor.py +216 -0
  414. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  415. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  416. opentrons/protocol_engine/execution/equipment.py +819 -0
  417. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  418. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  419. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  420. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  421. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  422. opentrons/protocol_engine/execution/movement.py +349 -0
  423. opentrons/protocol_engine/execution/pipetting.py +607 -0
  424. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  425. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  426. opentrons/protocol_engine/execution/run_control.py +33 -0
  427. opentrons/protocol_engine/execution/status_bar.py +34 -0
  428. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  429. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  430. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  431. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  432. opentrons/protocol_engine/notes/__init__.py +17 -0
  433. opentrons/protocol_engine/notes/notes.py +59 -0
  434. opentrons/protocol_engine/plugins.py +104 -0
  435. opentrons/protocol_engine/protocol_engine.py +683 -0
  436. opentrons/protocol_engine/resources/__init__.py +26 -0
  437. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  438. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  439. opentrons/protocol_engine/resources/file_provider.py +161 -0
  440. opentrons/protocol_engine/resources/fixture_validation.py +58 -0
  441. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  442. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  443. opentrons/protocol_engine/resources/model_utils.py +32 -0
  444. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  445. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  446. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  447. opentrons/protocol_engine/slot_standardization.py +128 -0
  448. opentrons/protocol_engine/state/__init__.py +1 -0
  449. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  450. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  451. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  452. opentrons/protocol_engine/state/_move_types.py +83 -0
  453. opentrons/protocol_engine/state/_well_math.py +193 -0
  454. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  455. opentrons/protocol_engine/state/command_history.py +309 -0
  456. opentrons/protocol_engine/state/commands.py +1158 -0
  457. opentrons/protocol_engine/state/config.py +39 -0
  458. opentrons/protocol_engine/state/files.py +57 -0
  459. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  460. opentrons/protocol_engine/state/geometry.py +2359 -0
  461. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  462. opentrons/protocol_engine/state/labware.py +1459 -0
  463. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  464. opentrons/protocol_engine/state/liquids.py +73 -0
  465. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  466. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  467. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  468. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  469. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  471. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  472. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  473. opentrons/protocol_engine/state/modules.py +1500 -0
  474. opentrons/protocol_engine/state/motion.py +373 -0
  475. opentrons/protocol_engine/state/pipettes.py +905 -0
  476. opentrons/protocol_engine/state/state.py +421 -0
  477. opentrons/protocol_engine/state/state_summary.py +36 -0
  478. opentrons/protocol_engine/state/tips.py +420 -0
  479. opentrons/protocol_engine/state/update_types.py +904 -0
  480. opentrons/protocol_engine/state/wells.py +290 -0
  481. opentrons/protocol_engine/types/__init__.py +308 -0
  482. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  483. opentrons/protocol_engine/types/command_annotations.py +53 -0
  484. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  485. opentrons/protocol_engine/types/execution.py +96 -0
  486. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  487. opentrons/protocol_engine/types/instrument.py +47 -0
  488. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  489. opentrons/protocol_engine/types/labware.py +131 -0
  490. opentrons/protocol_engine/types/labware_movement.py +22 -0
  491. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  492. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  493. opentrons/protocol_engine/types/liquid.py +40 -0
  494. opentrons/protocol_engine/types/liquid_class.py +59 -0
  495. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  496. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  497. opentrons/protocol_engine/types/location.py +194 -0
  498. opentrons/protocol_engine/types/module.py +303 -0
  499. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  500. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  501. opentrons/protocol_engine/types/tip.py +18 -0
  502. opentrons/protocol_engine/types/util.py +21 -0
  503. opentrons/protocol_engine/types/well_position.py +124 -0
  504. opentrons/protocol_reader/__init__.py +37 -0
  505. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  506. opentrons/protocol_reader/file_format_validator.py +152 -0
  507. opentrons/protocol_reader/file_hasher.py +27 -0
  508. opentrons/protocol_reader/file_identifier.py +284 -0
  509. opentrons/protocol_reader/file_reader_writer.py +90 -0
  510. opentrons/protocol_reader/input_file.py +16 -0
  511. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  512. opentrons/protocol_reader/protocol_reader.py +188 -0
  513. opentrons/protocol_reader/protocol_source.py +124 -0
  514. opentrons/protocol_reader/role_analyzer.py +86 -0
  515. opentrons/protocol_runner/__init__.py +26 -0
  516. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  517. opentrons/protocol_runner/json_file_reader.py +55 -0
  518. opentrons/protocol_runner/json_translator.py +314 -0
  519. opentrons/protocol_runner/legacy_command_mapper.py +848 -0
  520. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  521. opentrons/protocol_runner/protocol_runner.py +530 -0
  522. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  523. opentrons/protocol_runner/run_orchestrator.py +496 -0
  524. opentrons/protocol_runner/task_queue.py +95 -0
  525. opentrons/protocols/__init__.py +6 -0
  526. opentrons/protocols/advanced_control/__init__.py +0 -0
  527. opentrons/protocols/advanced_control/common.py +38 -0
  528. opentrons/protocols/advanced_control/mix.py +60 -0
  529. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  530. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  531. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  532. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  533. opentrons/protocols/api_support/__init__.py +0 -0
  534. opentrons/protocols/api_support/constants.py +8 -0
  535. opentrons/protocols/api_support/deck_type.py +110 -0
  536. opentrons/protocols/api_support/definitions.py +18 -0
  537. opentrons/protocols/api_support/instrument.py +151 -0
  538. opentrons/protocols/api_support/labware_like.py +233 -0
  539. opentrons/protocols/api_support/tip_tracker.py +175 -0
  540. opentrons/protocols/api_support/types.py +32 -0
  541. opentrons/protocols/api_support/util.py +403 -0
  542. opentrons/protocols/bundle.py +89 -0
  543. opentrons/protocols/duration/__init__.py +4 -0
  544. opentrons/protocols/duration/errors.py +5 -0
  545. opentrons/protocols/duration/estimator.py +628 -0
  546. opentrons/protocols/execution/__init__.py +0 -0
  547. opentrons/protocols/execution/dev_types.py +181 -0
  548. opentrons/protocols/execution/errors.py +40 -0
  549. opentrons/protocols/execution/execute.py +84 -0
  550. opentrons/protocols/execution/execute_json_v3.py +275 -0
  551. opentrons/protocols/execution/execute_json_v4.py +359 -0
  552. opentrons/protocols/execution/execute_json_v5.py +28 -0
  553. opentrons/protocols/execution/execute_python.py +169 -0
  554. opentrons/protocols/execution/json_dispatchers.py +87 -0
  555. opentrons/protocols/execution/types.py +7 -0
  556. opentrons/protocols/geometry/__init__.py +0 -0
  557. opentrons/protocols/geometry/planning.py +297 -0
  558. opentrons/protocols/labware.py +312 -0
  559. opentrons/protocols/models/__init__.py +0 -0
  560. opentrons/protocols/models/json_protocol.py +679 -0
  561. opentrons/protocols/parameters/__init__.py +0 -0
  562. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  563. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  564. opentrons/protocols/parameters/exceptions.py +34 -0
  565. opentrons/protocols/parameters/parameter_definition.py +272 -0
  566. opentrons/protocols/parameters/types.py +17 -0
  567. opentrons/protocols/parameters/validation.py +267 -0
  568. opentrons/protocols/parse.py +671 -0
  569. opentrons/protocols/types.py +159 -0
  570. opentrons/py.typed +0 -0
  571. opentrons/resources/scripts/lpc21isp +0 -0
  572. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  573. opentrons/simulate.py +1065 -0
  574. opentrons/system/__init__.py +6 -0
  575. opentrons/system/camera.py +51 -0
  576. opentrons/system/log_control.py +59 -0
  577. opentrons/system/nmcli.py +856 -0
  578. opentrons/system/resin.py +24 -0
  579. opentrons/system/smoothie_update.py +15 -0
  580. opentrons/system/wifi.py +204 -0
  581. opentrons/tools/__init__.py +0 -0
  582. opentrons/tools/args_handler.py +22 -0
  583. opentrons/tools/write_pipette_memory.py +157 -0
  584. opentrons/types.py +618 -0
  585. opentrons/util/__init__.py +1 -0
  586. opentrons/util/async_helpers.py +166 -0
  587. opentrons/util/broker.py +84 -0
  588. opentrons/util/change_notifier.py +47 -0
  589. opentrons/util/entrypoint_util.py +278 -0
  590. opentrons/util/get_union_elements.py +26 -0
  591. opentrons/util/helpers.py +6 -0
  592. opentrons/util/linal.py +178 -0
  593. opentrons/util/logging_config.py +265 -0
  594. opentrons/util/logging_queue_handler.py +61 -0
  595. opentrons/util/performance_helpers.py +157 -0
  596. opentrons-8.6.0a1.dist-info/METADATA +37 -0
  597. opentrons-8.6.0a1.dist-info/RECORD +600 -0
  598. opentrons-8.6.0a1.dist-info/WHEEL +4 -0
  599. opentrons-8.6.0a1.dist-info/entry_points.txt +3 -0
  600. opentrons-8.6.0a1.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,147 @@
1
+ """Post-protocol hardware stopper."""
2
+ import logging
3
+ from typing import Optional
4
+
5
+ from opentrons.hardware_control import HardwareControlAPI
6
+ from opentrons.types import PipetteNotAttachedError as HwPipetteNotAttachedError
7
+
8
+ from ..resources.ot3_validation import ensure_ot3_hardware
9
+ from ..state.state import StateStore
10
+ from ..types import MotorAxis, PostRunHardwareState
11
+ from ..errors import HardwareNotSupportedError
12
+
13
+ from .movement import MovementHandler
14
+ from .gantry_mover import HardwareGantryMover
15
+ from .tip_handler import TipHandler, HardwareTipHandler
16
+ from ...hardware_control.types import OT3Mount
17
+
18
+ from opentrons.protocol_engine.types import AddressableOffsetVector
19
+
20
+ log = logging.getLogger(__name__)
21
+
22
+ # TODO(mc, 2022-03-07): this constant dup'd from opentrons.protocols.geometry.deck
23
+ # to avoid a circular dependency that needs to be figured out.
24
+ FIXED_TRASH_ID = "fixedTrash"
25
+
26
+
27
+ class HardwareStopper:
28
+ """Class to implement hardware stopping."""
29
+
30
+ def __init__(
31
+ self,
32
+ hardware_api: HardwareControlAPI,
33
+ state_store: StateStore,
34
+ movement: Optional[MovementHandler] = None,
35
+ tip_handler: Optional[TipHandler] = None,
36
+ ) -> None:
37
+ """Hardware stopper initializer."""
38
+ self._hardware_api = hardware_api
39
+ self._state_store = state_store
40
+ self._movement_handler = movement or MovementHandler(
41
+ hardware_api=hardware_api,
42
+ state_store=state_store,
43
+ gantry_mover=HardwareGantryMover(
44
+ hardware_api=hardware_api,
45
+ state_view=state_store,
46
+ ),
47
+ )
48
+ self._tip_handler = tip_handler or HardwareTipHandler(
49
+ hardware_api=hardware_api,
50
+ state_view=state_store,
51
+ )
52
+
53
+ async def _home_everything_except_plungers(self) -> None:
54
+ # TODO: Update this once gripper MotorAxis is available in engine.
55
+ try:
56
+ ot3api = ensure_ot3_hardware(hardware_api=self._hardware_api)
57
+ if (
58
+ not self._state_store.config.use_virtual_gripper
59
+ and ot3api.has_gripper()
60
+ ):
61
+ await ot3api.home_z(mount=OT3Mount.GRIPPER)
62
+ except HardwareNotSupportedError:
63
+ pass
64
+ await self._movement_handler.home(
65
+ axes=[MotorAxis.X, MotorAxis.Y, MotorAxis.LEFT_Z, MotorAxis.RIGHT_Z]
66
+ )
67
+
68
+ async def _try_to_drop_tips(self) -> None:
69
+ """Drop currently attached tip, if any, into trash after a run cancel."""
70
+ attached_tips = self._state_store.pipettes.get_all_attached_tips()
71
+
72
+ if attached_tips:
73
+ await self._hardware_api.stop(home_after=False)
74
+
75
+ await self._home_everything_except_plungers()
76
+
77
+ for pipette_id, tip in attached_tips:
78
+ try:
79
+ if self._state_store.labware.get_fixed_trash_id() == FIXED_TRASH_ID:
80
+ # OT-2 and Flex 2.15 protocols will default to the Fixed Trash Labware
81
+ self._tip_handler.cache_tip(pipette_id=pipette_id, tip=tip)
82
+ await self._movement_handler.move_to_well(
83
+ pipette_id=pipette_id,
84
+ labware_id=FIXED_TRASH_ID,
85
+ well_name="A1",
86
+ )
87
+ await self._tip_handler.drop_tip(
88
+ pipette_id=pipette_id,
89
+ home_after=False,
90
+ )
91
+ elif self._state_store.config.robot_type == "OT-2 Standard":
92
+ # API 2.16 and above OT2 protocols use addressable areas
93
+ self._tip_handler.cache_tip(pipette_id=pipette_id, tip=tip)
94
+ await self._movement_handler.move_to_addressable_area(
95
+ pipette_id=pipette_id,
96
+ addressable_area_name="fixedTrash",
97
+ offset=AddressableOffsetVector(x=0, y=0, z=0),
98
+ force_direct=False,
99
+ speed=None,
100
+ minimum_z_height=None,
101
+ )
102
+ await self._tip_handler.drop_tip(
103
+ pipette_id=pipette_id,
104
+ home_after=False,
105
+ )
106
+ else:
107
+ log.debug(
108
+ "Flex Protocols API Version 2.16 and beyond do not support automatic tip dropping at this time."
109
+ )
110
+
111
+ except HwPipetteNotAttachedError:
112
+ # this will happen normally during protocol analysis, but
113
+ # should not happen during an actual run
114
+ log.debug(f"Pipette ID {pipette_id} no longer attached.")
115
+
116
+ async def do_halt(self, disengage_before_stopping: bool = False) -> None:
117
+ """Issue a halt signal to the hardware API.
118
+
119
+ After issuing a halt, you must call do_stop_and_recover after
120
+ anything using the HardwareAPI has settled.
121
+ """
122
+ await self._hardware_api.halt(
123
+ disengage_before_stopping=disengage_before_stopping
124
+ )
125
+
126
+ async def do_stop_and_recover(
127
+ self,
128
+ post_run_hardware_state: PostRunHardwareState,
129
+ drop_tips_after_run: bool = False,
130
+ ) -> None:
131
+ """Stop and reset the HardwareAPI, homing and dropping tips independently if specified. If modules are attached that require recovery handle them."""
132
+ home_after_stop = post_run_hardware_state in (
133
+ PostRunHardwareState.HOME_AND_STAY_ENGAGED,
134
+ PostRunHardwareState.HOME_THEN_DISENGAGE,
135
+ )
136
+ try:
137
+ if drop_tips_after_run:
138
+ await self._try_to_drop_tips()
139
+
140
+ await self._hardware_api.stop(home_after=False)
141
+
142
+ if home_after_stop:
143
+ await self._home_everything_except_plungers()
144
+ finally:
145
+ # Ensure module state recovery is handled
146
+ for module in self._hardware_api.attached_modules:
147
+ module.cleanup_persistent()
@@ -0,0 +1,207 @@
1
+ """Helpers for flagging unsafe movements around a Heater-Shaker Module."""
2
+
3
+ from typing import List, Optional
4
+
5
+ from opentrons.motion_planning.adjacent_slots_getters import (
6
+ get_east_west_slots,
7
+ get_north_south_slots,
8
+ )
9
+
10
+ from ..errors import (
11
+ PipetteMovementRestrictedByHeaterShakerError,
12
+ HeaterShakerLabwareLatchNotOpenError,
13
+ HeaterShakerLabwareLatchStatusUnknown,
14
+ WrongModuleTypeError,
15
+ )
16
+ from ..state.state import StateStore
17
+ from ..state.module_substates import HeaterShakerModuleSubState
18
+ from ..types import (
19
+ HeaterShakerMovementRestrictors,
20
+ HeaterShakerLatchStatus,
21
+ LabwareLocation,
22
+ ModuleLocation,
23
+ )
24
+ from ...hardware_control import HardwareControlAPI
25
+ from ...hardware_control.modules import HeaterShaker as HardwareHeaterShaker
26
+ from ...drivers.types import (
27
+ HeaterShakerLabwareLatchStatus as HeaterShakerHardwareLatchStatus,
28
+ )
29
+
30
+
31
+ class HeaterShakerMovementFlagger:
32
+ """A helper for flagging unsafe movements to a Heater-Shaker."""
33
+
34
+ def __init__(
35
+ self, state_store: StateStore, hardware_api: HardwareControlAPI
36
+ ) -> None:
37
+ self._state_store = state_store
38
+ self._hardware_api = hardware_api
39
+
40
+ async def raise_if_labware_latched_on_heater_shaker(
41
+ self, labware_parent: LabwareLocation
42
+ ) -> None:
43
+ """Flag unsafe movements to a heater-shaker.
44
+
45
+ If the given labware is on a heater-shaker, and that heater-shaker's labware
46
+ latch is not open according to the engine's h/s state as well as the
47
+ hardware API (for non-virtual modules), raises HeaterShakerLabwareLatchNotOpenError.
48
+ If it is a virtual module, checks only for heater-shaker latch state in engine.
49
+
50
+ Otherwise, no-ops.
51
+ """
52
+ if isinstance(labware_parent, ModuleLocation):
53
+ module_id = labware_parent.moduleId
54
+ else:
55
+ return # Labware not on a module.
56
+ try:
57
+ hs_substate = self._state_store.modules.get_heater_shaker_module_substate(
58
+ module_id=module_id
59
+ )
60
+ except WrongModuleTypeError:
61
+ return # Labware on a module, but not a Heater-Shaker.
62
+
63
+ if hs_substate.labware_latch_status == HeaterShakerLatchStatus.CLOSED:
64
+ raise HeaterShakerLabwareLatchNotOpenError(
65
+ "Heater-Shaker labware latch must be open when moving labware to/from it."
66
+ )
67
+ elif hs_substate.labware_latch_status == HeaterShakerLatchStatus.UNKNOWN:
68
+ raise HeaterShakerLabwareLatchStatusUnknown(
69
+ "Heater-Shaker labware latch must be opened before moving labware to/from it."
70
+ )
71
+
72
+ # There is a chance that the engine might not have the latest latch status;
73
+ # do a hardware state check to be sure that the latch is truly open
74
+ if not self._state_store.config.use_virtual_modules:
75
+ await self._check_hardware_module_latch_status(hs_substate)
76
+
77
+ async def _check_hardware_module_latch_status(
78
+ self, hs_substate: HeaterShakerModuleSubState
79
+ ) -> None:
80
+ try:
81
+ hs_latch_status = await self._get_hardware_heater_shaker_latch_status(
82
+ module_id=hs_substate.module_id
83
+ )
84
+ except self._HardwareHeaterShakerMissingError as e:
85
+ raise HeaterShakerLabwareLatchNotOpenError(
86
+ "Heater-Shaker labware latch must be open when moving labware to/from it,"
87
+ " but the latch status is unknown."
88
+ ) from e
89
+
90
+ if hs_latch_status != HeaterShakerHardwareLatchStatus.IDLE_OPEN:
91
+ raise HeaterShakerLabwareLatchNotOpenError(
92
+ f"Heater-Shaker labware latch must be open when moving labware to/from it,"
93
+ f" but the latch is currently {hs_latch_status}"
94
+ )
95
+
96
+ async def _get_hardware_heater_shaker_latch_status(
97
+ self,
98
+ module_id: str,
99
+ ) -> HeaterShakerHardwareLatchStatus:
100
+ """Get latch status of the hardware H/S corresponding with the module ID.
101
+
102
+ Returns:
103
+ Latch status of the requested attached heater-shaker.
104
+
105
+ Raises:
106
+ _HardwareHeaterShakerMissingError: If we can't find that H/S in
107
+ the hardware API, so we can't fetch its current latch status.
108
+ It's unclear if this can happen in practice...
109
+ maybe if the module disconnects between when it was loaded into
110
+ Protocol Engine and when this function is called?
111
+ """
112
+ hs_serial = self._state_store.modules.get_serial_number(module_id=module_id)
113
+ heater_shaker = await self._find_heater_shaker_by_serial(
114
+ serial_number=hs_serial
115
+ )
116
+ if heater_shaker is None:
117
+ raise self._HardwareHeaterShakerMissingError(
118
+ f"No Heater-Shaker found with serial number {hs_serial}"
119
+ )
120
+
121
+ latch_status = heater_shaker.labware_latch_status
122
+ # An attached H/S should always have latch status unless it's in error or
123
+ # it was just connected and hasn't been polled for status yet.
124
+ assert latch_status is not None, (
125
+ "Did not receive a valid latch status from heater-shaker. "
126
+ "Cannot verify safe labware movement."
127
+ )
128
+ return latch_status
129
+
130
+ async def _find_heater_shaker_by_serial(
131
+ self, serial_number: str
132
+ ) -> Optional[HardwareHeaterShaker]:
133
+ """Find the hardware H/S with the given serial number.
134
+
135
+ Returns:
136
+ The matching hardware H/S, or None if none was found.
137
+ """
138
+ for module in self._hardware_api.attached_modules:
139
+ # Different module types have different keys under .device_info.
140
+ # Heater-Shaker should always have .device_info["serial"].
141
+ if (
142
+ isinstance(module, HardwareHeaterShaker)
143
+ and module.device_info["serial"] == serial_number
144
+ ):
145
+ return module
146
+ return None
147
+
148
+ def raise_if_movement_restricted(
149
+ self,
150
+ hs_movement_restrictors: List[HeaterShakerMovementRestrictors],
151
+ destination_slot: int,
152
+ is_multi_channel: bool,
153
+ destination_is_tip_rack: bool,
154
+ ) -> None:
155
+ """Flag restricted movement around/to a Heater-Shaker."""
156
+ for hs_movement_restrictor in hs_movement_restrictors:
157
+ dest_east_west = destination_slot in get_east_west_slots(
158
+ hs_movement_restrictor.deck_slot
159
+ )
160
+ dest_north_south = destination_slot in get_north_south_slots(
161
+ hs_movement_restrictor.deck_slot
162
+ )
163
+ dest_heater_shaker = destination_slot == hs_movement_restrictor.deck_slot
164
+
165
+ # If Heater-Shaker is running, can't move to or around it
166
+ if (
167
+ any([dest_east_west, dest_north_south, dest_heater_shaker])
168
+ and hs_movement_restrictor.plate_shaking
169
+ ):
170
+ raise PipetteMovementRestrictedByHeaterShakerError(
171
+ "Cannot move pipette to Heater-Shaker or adjacent slot while module is shaking"
172
+ )
173
+
174
+ # If Heater-Shaker's latch is open, can't move to it or east and west of it
175
+ elif hs_movement_restrictor.latch_status != HeaterShakerLatchStatus.CLOSED:
176
+ if dest_heater_shaker:
177
+ raise PipetteMovementRestrictedByHeaterShakerError(
178
+ f"Cannot move pipette to Heater-Shaker while labware latch"
179
+ f" {'has not been closed' if hs_movement_restrictor.latch_status == HeaterShakerLatchStatus.UNKNOWN else 'is open'}."
180
+ )
181
+ if (
182
+ dest_east_west
183
+ and self._state_store.config.robot_type == "OT-2 Standard"
184
+ ):
185
+ raise PipetteMovementRestrictedByHeaterShakerError(
186
+ "Cannot move pipette to left or right of Heater-Shaker while labware latch "
187
+ f" {'has not been closed' if hs_movement_restrictor.latch_status == HeaterShakerLatchStatus.UNKNOWN else 'is open'}."
188
+ )
189
+
190
+ elif (
191
+ is_multi_channel
192
+ and self._state_store.config.robot_type == "OT-2 Standard"
193
+ ):
194
+ # Can't go to east/west slot under any circumstances on OT-2
195
+ # if pipette is multi-channel
196
+ if dest_east_west:
197
+ raise PipetteMovementRestrictedByHeaterShakerError(
198
+ "Cannot move 8-Channel pipette to slot adjacent to the left or right of Heater-Shaker"
199
+ )
200
+ # Can only go north/south if the labware is a tip rack
201
+ elif dest_north_south and not destination_is_tip_rack:
202
+ raise PipetteMovementRestrictedByHeaterShakerError(
203
+ "Cannot move 8-Channel pipette to non-tip-rack labware directly in front of or behind a Heater-Shaker"
204
+ )
205
+
206
+ class _HardwareHeaterShakerMissingError(Exception):
207
+ pass
@@ -0,0 +1,297 @@
1
+ """Labware movement command handling."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional, TYPE_CHECKING, overload
6
+
7
+ from opentrons_shared_data.labware.labware_definition import LabwareDefinition
8
+
9
+ from opentrons.types import Point
10
+
11
+ from opentrons.hardware_control import HardwareControlAPI
12
+ from opentrons.hardware_control.types import OT3Mount, Axis
13
+ from opentrons.motion_planning import get_gripper_labware_movement_waypoints
14
+
15
+ from opentrons.protocol_engine.state.state import StateStore
16
+ from opentrons.protocol_engine.resources.ot3_validation import ensure_ot3_hardware
17
+
18
+ from .thermocycler_movement_flagger import ThermocyclerMovementFlagger
19
+ from .heater_shaker_movement_flagger import HeaterShakerMovementFlagger
20
+ from .thermocycler_plate_lifter import ThermocyclerPlateLifter
21
+
22
+ from ..errors import (
23
+ GripperNotAttachedError,
24
+ LabwareMovementNotAllowedError,
25
+ ThermocyclerNotOpenError,
26
+ HeaterShakerLabwareLatchNotOpenError,
27
+ CannotPerformGripperAction,
28
+ )
29
+
30
+ from ..types import (
31
+ OnLabwareLocation,
32
+ LabwareLocation,
33
+ OnDeckLabwareLocation,
34
+ )
35
+
36
+ if TYPE_CHECKING:
37
+ from opentrons.protocol_engine.execution import EquipmentHandler, MovementHandler
38
+
39
+ _GRIPPER_HOMED_POSITION_Z = 166.125 # Height of the center of the gripper critical point from the deck when homed
40
+
41
+
42
+ class LabwareMovementHandler:
43
+ """Implementation logic for labware movement."""
44
+
45
+ _hardware_api: HardwareControlAPI
46
+ _state_store: StateStore
47
+ _movement: MovementHandler
48
+ _equipment: EquipmentHandler
49
+
50
+ def __init__(
51
+ self,
52
+ hardware_api: HardwareControlAPI,
53
+ state_store: StateStore,
54
+ equipment: EquipmentHandler,
55
+ movement: MovementHandler,
56
+ thermocycler_plate_lifter: Optional[ThermocyclerPlateLifter] = None,
57
+ thermocycler_movement_flagger: Optional[ThermocyclerMovementFlagger] = None,
58
+ heater_shaker_movement_flagger: Optional[HeaterShakerMovementFlagger] = None,
59
+ ) -> None:
60
+ """Initialize a LabwareMovementHandler instance."""
61
+ self._hardware_api = hardware_api
62
+ self._state_store = state_store
63
+ self._equipment = equipment
64
+ self._thermocycler_plate_lifter = (
65
+ thermocycler_plate_lifter
66
+ or ThermocyclerPlateLifter(
67
+ state_store=self._state_store,
68
+ equipment=equipment,
69
+ movement=movement,
70
+ )
71
+ )
72
+ self._tc_movement_flagger = (
73
+ thermocycler_movement_flagger
74
+ or ThermocyclerMovementFlagger(
75
+ state_store=self._state_store,
76
+ hardware_api=self._hardware_api,
77
+ equipment=self._equipment
78
+ or EquipmentHandler(
79
+ hardware_api=self._hardware_api,
80
+ state_store=self._state_store,
81
+ ),
82
+ )
83
+ )
84
+ self._hs_movement_flagger = (
85
+ heater_shaker_movement_flagger
86
+ or HeaterShakerMovementFlagger(
87
+ state_store=self._state_store, hardware_api=self._hardware_api
88
+ )
89
+ )
90
+
91
+ @overload
92
+ async def move_labware_with_gripper(
93
+ self,
94
+ *,
95
+ labware_id: str,
96
+ current_location: OnDeckLabwareLocation,
97
+ new_location: OnDeckLabwareLocation,
98
+ user_pick_up_offset: Point,
99
+ user_drop_offset: Point,
100
+ post_drop_slide_offset: Optional[Point],
101
+ ) -> None:
102
+ ...
103
+
104
+ @overload
105
+ async def move_labware_with_gripper(
106
+ self,
107
+ *,
108
+ labware_definition: LabwareDefinition,
109
+ current_location: OnDeckLabwareLocation,
110
+ new_location: OnDeckLabwareLocation,
111
+ user_pick_up_offset: Point,
112
+ user_drop_offset: Point,
113
+ post_drop_slide_offset: Optional[Point],
114
+ gripper_z_offset: Optional[float],
115
+ ) -> None:
116
+ ...
117
+
118
+ async def move_labware_with_gripper( # noqa: C901
119
+ self,
120
+ *,
121
+ labware_id: str | None = None,
122
+ labware_definition: LabwareDefinition | None = None,
123
+ current_location: OnDeckLabwareLocation,
124
+ new_location: OnDeckLabwareLocation,
125
+ user_pick_up_offset: Point,
126
+ user_drop_offset: Point,
127
+ post_drop_slide_offset: Optional[Point],
128
+ gripper_z_offset: Optional[float] = None,
129
+ ) -> None:
130
+ """Physically move a labware from one location to another using the gripper.
131
+
132
+ Generally, provide the `labware_id` of a loaded labware, and this method will
133
+ automatically look up its labware definition. If you're physically moving
134
+ something that has not been loaded as a labware (this is not common),
135
+ provide the `labware_definition` yourself instead.
136
+ """
137
+ use_virtual_gripper = self._state_store.config.use_virtual_gripper
138
+
139
+ if labware_definition is None:
140
+ assert labware_id is not None # From this method's @typing.overloads.
141
+ labware_definition = self._state_store.labware.get_definition(labware_id)
142
+
143
+ from_labware_center = self._state_store.geometry.get_labware_grip_point(
144
+ labware_definition=labware_definition, location=current_location
145
+ )
146
+ to_labware_center = self._state_store.geometry.get_labware_grip_point(
147
+ labware_definition=labware_definition, location=new_location
148
+ )
149
+
150
+ if use_virtual_gripper:
151
+ # todo(mm, 2024-11-07): We should do this collision checking even when we
152
+ # only have a `labware_definition`, not a `labware_id`. Resolve when
153
+ # `check_gripper_labware_tip_collision()` can be made independent of `labware_id`.
154
+ if labware_id is not None:
155
+ self._state_store.geometry.check_gripper_labware_tip_collision(
156
+ # During Analysis we will pass in hard coded estimates for certain positions only accessible during execution
157
+ gripper_homed_position_z=_GRIPPER_HOMED_POSITION_Z,
158
+ labware_id=labware_id,
159
+ current_location=current_location,
160
+ )
161
+ return
162
+
163
+ ot3api = ensure_ot3_hardware(
164
+ hardware_api=self._hardware_api,
165
+ error_msg="Gripper is only available on Opentrons Flex",
166
+ )
167
+
168
+ if not ot3api.has_gripper():
169
+ raise GripperNotAttachedError(
170
+ "No gripper found for performing labware movements."
171
+ )
172
+ if not ot3api.gripper_jaw_can_home():
173
+ raise CannotPerformGripperAction(
174
+ "Cannot pick up labware when gripper is already gripping."
175
+ )
176
+
177
+ gripper_mount = OT3Mount.GRIPPER
178
+
179
+ # Retract all mounts
180
+ await ot3api.home(axes=[Axis.Z_L, Axis.Z_R, Axis.Z_G])
181
+ gripper_homed_position = await ot3api.gantry_position(mount=gripper_mount)
182
+
183
+ # todo(mm, 2024-11-07): We should do this collision checking even when we
184
+ # only have a `labware_definition`, not a `labware_id`. Resolve when
185
+ # `check_gripper_labware_tip_collision()` can be made independent of `labware_id`.
186
+ if labware_id is not None:
187
+ self._state_store.geometry.check_gripper_labware_tip_collision(
188
+ gripper_homed_position_z=gripper_homed_position.z,
189
+ labware_id=labware_id,
190
+ current_location=current_location,
191
+ )
192
+
193
+ async with self._thermocycler_plate_lifter.lift_plate_for_labware_movement(
194
+ labware_location=current_location
195
+ ):
196
+ final_offsets = (
197
+ self._state_store.geometry.get_final_labware_movement_offset_vectors(
198
+ from_location=current_location,
199
+ to_location=new_location,
200
+ additional_pick_up_offset=user_pick_up_offset,
201
+ additional_drop_offset=user_drop_offset,
202
+ current_labware=labware_definition,
203
+ )
204
+ )
205
+ movement_waypoints = get_gripper_labware_movement_waypoints(
206
+ from_labware_center=from_labware_center,
207
+ to_labware_center=to_labware_center,
208
+ gripper_home_z=gripper_homed_position.z,
209
+ offset_data=final_offsets,
210
+ post_drop_slide_offset=post_drop_slide_offset,
211
+ gripper_home_z_offset=gripper_z_offset,
212
+ )
213
+ labware_grip_force = self._state_store.labware.get_grip_force(
214
+ labware_definition
215
+ )
216
+ holding_labware = False
217
+ for waypoint_data in movement_waypoints:
218
+ if waypoint_data.jaw_open:
219
+ if waypoint_data.dropping:
220
+ # This `disengage_axes` step is important in order to engage
221
+ # the electronic brake on the Z axis of the gripper. The brake
222
+ # has a stronger holding force on the axis than the hold current,
223
+ # and prevents the axis from spuriously dropping when e.g. the notch
224
+ # on the side of a falling tiprack catches the jaw.
225
+ await ot3api.disengage_axes([Axis.Z_G])
226
+ await ot3api.ungrip()
227
+ holding_labware = True
228
+ if waypoint_data.dropping:
229
+ # We lost the position estimation after disengaging the axis, so
230
+ # it is necessary to home it next
231
+ await ot3api.home_z(OT3Mount.GRIPPER)
232
+ else:
233
+ await ot3api.grip(force_newtons=labware_grip_force)
234
+ # we only want to check position after the gripper has opened and
235
+ # should be holding labware
236
+ if holding_labware:
237
+ labware_bbox = self._state_store.labware.get_dimensions(
238
+ labware_definition=labware_definition
239
+ )
240
+ well_bbox = self._state_store.labware.get_well_bbox(
241
+ labware_definition=labware_definition
242
+ )
243
+ # todo(mm, 2024-09-26): This currently raises a lower-level 2015 FailedGripperPickupError.
244
+ # Convert this to a higher-level 3001 LabwareDroppedError or 3002 LabwareNotPickedUpError,
245
+ # depending on what waypoint we're at, to propagate a more specific error code to users.
246
+ ot3api.raise_error_if_gripper_pickup_failed(
247
+ expected_grip_width=labware_bbox.y,
248
+ grip_width_uncertainty_wider=abs(
249
+ max(well_bbox.y - labware_bbox.y, 0)
250
+ ),
251
+ grip_width_uncertainty_narrower=abs(
252
+ min(well_bbox.y - labware_bbox.y, 0)
253
+ ),
254
+ )
255
+ await ot3api.move_to(
256
+ mount=gripper_mount, abs_position=waypoint_data.position
257
+ )
258
+
259
+ # this makes sure gripper jaw is closed between two move labware calls
260
+ await ot3api.idle_gripper()
261
+
262
+ async def ensure_movement_not_obstructed_by_module(
263
+ self, labware_id: str, new_location: LabwareLocation
264
+ ) -> None:
265
+ """Ensure that the labware movement is not obstructed by a parent module.
266
+
267
+ Raises: LabwareMovementNotAllowedError if either current location or
268
+ new location is a module that is in a state that prevents the labware from
269
+ being moved (either manually or using gripper).
270
+ """
271
+ current_parent = self._state_store.labware.get_parent_location(
272
+ labware_id=labware_id
273
+ )
274
+ if isinstance(new_location, OnLabwareLocation):
275
+ new_location = self._state_store.labware.get_parent_location(
276
+ labware_id=new_location.labwareId
277
+ )
278
+ for parent in (current_parent, new_location):
279
+ try:
280
+ await self._tc_movement_flagger.ensure_labware_in_open_thermocycler(
281
+ labware_parent=parent
282
+ )
283
+ if not self._state_store.labware.is_lid(labware_id):
284
+ # Lid placement is actually improved by holding the labware latched on the H/S
285
+ # So, we skip this check for lids.
286
+ await self._hs_movement_flagger.raise_if_labware_latched_on_heater_shaker(
287
+ labware_parent=parent
288
+ )
289
+ except ThermocyclerNotOpenError:
290
+ raise LabwareMovementNotAllowedError(
291
+ "Cannot move labware to or from a Thermocycler with its lid closed."
292
+ )
293
+ except HeaterShakerLabwareLatchNotOpenError:
294
+ raise LabwareMovementNotAllowedError(
295
+ "Cannot move labware to or from a Heater-Shaker"
296
+ " with its labware latch closed."
297
+ )