opentrons 8.6.0__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 (601) 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 +557 -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 +187 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +557 -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/scripts/update_module_fw.py +274 -0
  200. opentrons/hardware_control/simulator_setup.py +260 -0
  201. opentrons/hardware_control/thread_manager.py +431 -0
  202. opentrons/hardware_control/threaded_async_lock.py +97 -0
  203. opentrons/hardware_control/types.py +792 -0
  204. opentrons/hardware_control/util.py +234 -0
  205. opentrons/legacy_broker.py +53 -0
  206. opentrons/legacy_commands/__init__.py +1 -0
  207. opentrons/legacy_commands/commands.py +483 -0
  208. opentrons/legacy_commands/helpers.py +153 -0
  209. opentrons/legacy_commands/module_commands.py +276 -0
  210. opentrons/legacy_commands/protocol_commands.py +54 -0
  211. opentrons/legacy_commands/publisher.py +155 -0
  212. opentrons/legacy_commands/robot_commands.py +51 -0
  213. opentrons/legacy_commands/types.py +1186 -0
  214. opentrons/motion_planning/__init__.py +32 -0
  215. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  216. opentrons/motion_planning/deck_conflict.py +501 -0
  217. opentrons/motion_planning/errors.py +35 -0
  218. opentrons/motion_planning/types.py +42 -0
  219. opentrons/motion_planning/waypoints.py +218 -0
  220. opentrons/ordered_set.py +138 -0
  221. opentrons/protocol_api/__init__.py +105 -0
  222. opentrons/protocol_api/_liquid.py +157 -0
  223. opentrons/protocol_api/_liquid_properties.py +814 -0
  224. opentrons/protocol_api/_nozzle_layout.py +31 -0
  225. opentrons/protocol_api/_parameter_context.py +300 -0
  226. opentrons/protocol_api/_parameters.py +31 -0
  227. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  228. opentrons/protocol_api/_types.py +43 -0
  229. opentrons/protocol_api/config.py +23 -0
  230. opentrons/protocol_api/core/__init__.py +23 -0
  231. opentrons/protocol_api/core/common.py +33 -0
  232. opentrons/protocol_api/core/core_map.py +74 -0
  233. opentrons/protocol_api/core/engine/__init__.py +22 -0
  234. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  235. opentrons/protocol_api/core/engine/deck_conflict.py +400 -0
  236. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  237. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  238. opentrons/protocol_api/core/engine/labware.py +238 -0
  239. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  240. opentrons/protocol_api/core/engine/module_core.py +1027 -0
  241. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  242. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  243. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  244. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  245. opentrons/protocol_api/core/engine/robot.py +139 -0
  246. opentrons/protocol_api/core/engine/stringify.py +74 -0
  247. opentrons/protocol_api/core/engine/transfer_components_executor.py +1006 -0
  248. opentrons/protocol_api/core/engine/well.py +241 -0
  249. opentrons/protocol_api/core/instrument.py +459 -0
  250. opentrons/protocol_api/core/labware.py +151 -0
  251. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  252. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  253. opentrons/protocol_api/core/legacy/deck.py +369 -0
  254. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  255. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  256. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  257. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  258. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  259. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  260. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  261. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  262. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  263. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  265. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  266. opentrons/protocol_api/core/module.py +484 -0
  267. opentrons/protocol_api/core/protocol.py +311 -0
  268. opentrons/protocol_api/core/robot.py +51 -0
  269. opentrons/protocol_api/core/well.py +116 -0
  270. opentrons/protocol_api/core/well_grid.py +45 -0
  271. opentrons/protocol_api/create_protocol_context.py +177 -0
  272. opentrons/protocol_api/deck.py +223 -0
  273. opentrons/protocol_api/disposal_locations.py +244 -0
  274. opentrons/protocol_api/instrument_context.py +3272 -0
  275. opentrons/protocol_api/labware.py +1579 -0
  276. opentrons/protocol_api/module_contexts.py +1447 -0
  277. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  278. opentrons/protocol_api/protocol_context.py +1688 -0
  279. opentrons/protocol_api/robot_context.py +303 -0
  280. opentrons/protocol_api/validation.py +761 -0
  281. opentrons/protocol_engine/__init__.py +155 -0
  282. opentrons/protocol_engine/actions/__init__.py +65 -0
  283. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  284. opentrons/protocol_engine/actions/action_handler.py +13 -0
  285. opentrons/protocol_engine/actions/actions.py +302 -0
  286. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  287. opentrons/protocol_engine/clients/__init__.py +5 -0
  288. opentrons/protocol_engine/clients/sync_client.py +174 -0
  289. opentrons/protocol_engine/clients/transports.py +197 -0
  290. opentrons/protocol_engine/commands/__init__.py +757 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  296. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  297. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  298. opentrons/protocol_engine/commands/aspirate.py +244 -0
  299. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  300. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  301. opentrons/protocol_engine/commands/blow_out.py +146 -0
  302. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  303. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  306. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  307. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  308. opentrons/protocol_engine/commands/command.py +308 -0
  309. opentrons/protocol_engine/commands/command_unions.py +974 -0
  310. opentrons/protocol_engine/commands/comment.py +57 -0
  311. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  312. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  313. opentrons/protocol_engine/commands/custom.py +67 -0
  314. opentrons/protocol_engine/commands/dispense.py +194 -0
  315. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  316. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  317. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  318. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  319. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  320. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  321. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  322. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  323. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  324. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  325. opentrons/protocol_engine/commands/flex_stacker/store.py +339 -0
  326. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  327. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  328. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  329. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  330. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  331. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  333. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  334. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  336. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  337. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  338. opentrons/protocol_engine/commands/home.py +100 -0
  339. opentrons/protocol_engine/commands/identify_module.py +86 -0
  340. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  341. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  342. opentrons/protocol_engine/commands/load_labware.py +210 -0
  343. opentrons/protocol_engine/commands/load_lid.py +154 -0
  344. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  345. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  346. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  347. opentrons/protocol_engine/commands/load_module.py +223 -0
  348. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  349. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  350. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  351. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  352. opentrons/protocol_engine/commands/move_labware.py +546 -0
  353. opentrons/protocol_engine/commands/move_relative.py +102 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  355. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  356. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  357. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  358. opentrons/protocol_engine/commands/movement_common.py +338 -0
  359. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  360. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  361. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  362. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  363. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  364. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  365. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  366. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  367. opentrons/protocol_engine/commands/robot/common.py +18 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  369. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  370. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  371. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  372. opentrons/protocol_engine/commands/save_position.py +109 -0
  373. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  374. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  375. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  376. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  377. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  378. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  379. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  380. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  381. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  384. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  386. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  388. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  390. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  391. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  392. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  401. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  402. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  403. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  404. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  405. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  406. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  407. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  408. opentrons/protocol_engine/engine_support.py +28 -0
  409. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  410. opentrons/protocol_engine/errors/__init__.py +191 -0
  411. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  412. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  413. opentrons/protocol_engine/execution/__init__.py +50 -0
  414. opentrons/protocol_engine/execution/command_executor.py +216 -0
  415. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  416. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  417. opentrons/protocol_engine/execution/equipment.py +819 -0
  418. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  419. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  420. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  421. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  422. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  423. opentrons/protocol_engine/execution/movement.py +350 -0
  424. opentrons/protocol_engine/execution/pipetting.py +607 -0
  425. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  426. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  427. opentrons/protocol_engine/execution/run_control.py +33 -0
  428. opentrons/protocol_engine/execution/status_bar.py +34 -0
  429. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  430. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  431. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  432. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  433. opentrons/protocol_engine/notes/__init__.py +17 -0
  434. opentrons/protocol_engine/notes/notes.py +59 -0
  435. opentrons/protocol_engine/plugins.py +104 -0
  436. opentrons/protocol_engine/protocol_engine.py +683 -0
  437. opentrons/protocol_engine/resources/__init__.py +26 -0
  438. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  439. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  440. opentrons/protocol_engine/resources/file_provider.py +161 -0
  441. opentrons/protocol_engine/resources/fixture_validation.py +68 -0
  442. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  443. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  444. opentrons/protocol_engine/resources/model_utils.py +32 -0
  445. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  446. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  447. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  448. opentrons/protocol_engine/slot_standardization.py +128 -0
  449. opentrons/protocol_engine/state/__init__.py +1 -0
  450. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  451. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  452. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  453. opentrons/protocol_engine/state/_move_types.py +83 -0
  454. opentrons/protocol_engine/state/_well_math.py +193 -0
  455. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  456. opentrons/protocol_engine/state/command_history.py +309 -0
  457. opentrons/protocol_engine/state/commands.py +1164 -0
  458. opentrons/protocol_engine/state/config.py +39 -0
  459. opentrons/protocol_engine/state/files.py +57 -0
  460. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  461. opentrons/protocol_engine/state/geometry.py +2408 -0
  462. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  463. opentrons/protocol_engine/state/labware.py +1432 -0
  464. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  465. opentrons/protocol_engine/state/liquids.py +73 -0
  466. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  467. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  468. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  469. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  471. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  472. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  473. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  474. opentrons/protocol_engine/state/modules.py +1515 -0
  475. opentrons/protocol_engine/state/motion.py +373 -0
  476. opentrons/protocol_engine/state/pipettes.py +905 -0
  477. opentrons/protocol_engine/state/state.py +421 -0
  478. opentrons/protocol_engine/state/state_summary.py +36 -0
  479. opentrons/protocol_engine/state/tips.py +420 -0
  480. opentrons/protocol_engine/state/update_types.py +904 -0
  481. opentrons/protocol_engine/state/wells.py +290 -0
  482. opentrons/protocol_engine/types/__init__.py +310 -0
  483. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  484. opentrons/protocol_engine/types/command_annotations.py +53 -0
  485. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  486. opentrons/protocol_engine/types/execution.py +96 -0
  487. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  488. opentrons/protocol_engine/types/instrument.py +47 -0
  489. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  490. opentrons/protocol_engine/types/labware.py +131 -0
  491. opentrons/protocol_engine/types/labware_movement.py +22 -0
  492. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  493. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  494. opentrons/protocol_engine/types/liquid.py +40 -0
  495. opentrons/protocol_engine/types/liquid_class.py +59 -0
  496. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  497. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  498. opentrons/protocol_engine/types/location.py +194 -0
  499. opentrons/protocol_engine/types/module.py +310 -0
  500. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  501. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  502. opentrons/protocol_engine/types/tip.py +18 -0
  503. opentrons/protocol_engine/types/util.py +21 -0
  504. opentrons/protocol_engine/types/well_position.py +124 -0
  505. opentrons/protocol_reader/__init__.py +37 -0
  506. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  507. opentrons/protocol_reader/file_format_validator.py +152 -0
  508. opentrons/protocol_reader/file_hasher.py +27 -0
  509. opentrons/protocol_reader/file_identifier.py +284 -0
  510. opentrons/protocol_reader/file_reader_writer.py +90 -0
  511. opentrons/protocol_reader/input_file.py +16 -0
  512. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  513. opentrons/protocol_reader/protocol_reader.py +188 -0
  514. opentrons/protocol_reader/protocol_source.py +124 -0
  515. opentrons/protocol_reader/role_analyzer.py +86 -0
  516. opentrons/protocol_runner/__init__.py +26 -0
  517. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  518. opentrons/protocol_runner/json_file_reader.py +55 -0
  519. opentrons/protocol_runner/json_translator.py +314 -0
  520. opentrons/protocol_runner/legacy_command_mapper.py +852 -0
  521. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  522. opentrons/protocol_runner/protocol_runner.py +530 -0
  523. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  524. opentrons/protocol_runner/run_orchestrator.py +496 -0
  525. opentrons/protocol_runner/task_queue.py +95 -0
  526. opentrons/protocols/__init__.py +6 -0
  527. opentrons/protocols/advanced_control/__init__.py +0 -0
  528. opentrons/protocols/advanced_control/common.py +38 -0
  529. opentrons/protocols/advanced_control/mix.py +60 -0
  530. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  531. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  532. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  533. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  534. opentrons/protocols/api_support/__init__.py +0 -0
  535. opentrons/protocols/api_support/constants.py +8 -0
  536. opentrons/protocols/api_support/deck_type.py +110 -0
  537. opentrons/protocols/api_support/definitions.py +18 -0
  538. opentrons/protocols/api_support/instrument.py +151 -0
  539. opentrons/protocols/api_support/labware_like.py +233 -0
  540. opentrons/protocols/api_support/tip_tracker.py +175 -0
  541. opentrons/protocols/api_support/types.py +32 -0
  542. opentrons/protocols/api_support/util.py +403 -0
  543. opentrons/protocols/bundle.py +89 -0
  544. opentrons/protocols/duration/__init__.py +4 -0
  545. opentrons/protocols/duration/errors.py +5 -0
  546. opentrons/protocols/duration/estimator.py +628 -0
  547. opentrons/protocols/execution/__init__.py +0 -0
  548. opentrons/protocols/execution/dev_types.py +181 -0
  549. opentrons/protocols/execution/errors.py +40 -0
  550. opentrons/protocols/execution/execute.py +84 -0
  551. opentrons/protocols/execution/execute_json_v3.py +275 -0
  552. opentrons/protocols/execution/execute_json_v4.py +359 -0
  553. opentrons/protocols/execution/execute_json_v5.py +28 -0
  554. opentrons/protocols/execution/execute_python.py +169 -0
  555. opentrons/protocols/execution/json_dispatchers.py +87 -0
  556. opentrons/protocols/execution/types.py +7 -0
  557. opentrons/protocols/geometry/__init__.py +0 -0
  558. opentrons/protocols/geometry/planning.py +297 -0
  559. opentrons/protocols/labware.py +312 -0
  560. opentrons/protocols/models/__init__.py +0 -0
  561. opentrons/protocols/models/json_protocol.py +679 -0
  562. opentrons/protocols/parameters/__init__.py +0 -0
  563. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  564. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  565. opentrons/protocols/parameters/exceptions.py +34 -0
  566. opentrons/protocols/parameters/parameter_definition.py +272 -0
  567. opentrons/protocols/parameters/types.py +17 -0
  568. opentrons/protocols/parameters/validation.py +267 -0
  569. opentrons/protocols/parse.py +671 -0
  570. opentrons/protocols/types.py +159 -0
  571. opentrons/py.typed +0 -0
  572. opentrons/resources/scripts/lpc21isp +0 -0
  573. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  574. opentrons/simulate.py +1065 -0
  575. opentrons/system/__init__.py +6 -0
  576. opentrons/system/camera.py +51 -0
  577. opentrons/system/log_control.py +59 -0
  578. opentrons/system/nmcli.py +856 -0
  579. opentrons/system/resin.py +24 -0
  580. opentrons/system/smoothie_update.py +15 -0
  581. opentrons/system/wifi.py +204 -0
  582. opentrons/tools/__init__.py +0 -0
  583. opentrons/tools/args_handler.py +22 -0
  584. opentrons/tools/write_pipette_memory.py +157 -0
  585. opentrons/types.py +618 -0
  586. opentrons/util/__init__.py +1 -0
  587. opentrons/util/async_helpers.py +166 -0
  588. opentrons/util/broker.py +84 -0
  589. opentrons/util/change_notifier.py +47 -0
  590. opentrons/util/entrypoint_util.py +278 -0
  591. opentrons/util/get_union_elements.py +26 -0
  592. opentrons/util/helpers.py +6 -0
  593. opentrons/util/linal.py +178 -0
  594. opentrons/util/logging_config.py +265 -0
  595. opentrons/util/logging_queue_handler.py +61 -0
  596. opentrons/util/performance_helpers.py +157 -0
  597. opentrons-8.6.0.dist-info/METADATA +37 -0
  598. opentrons-8.6.0.dist-info/RECORD +601 -0
  599. opentrons-8.6.0.dist-info/WHEEL +4 -0
  600. opentrons-8.6.0.dist-info/entry_points.txt +3 -0
  601. opentrons-8.6.0.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,116 @@
1
+ """Customize the ProtocolEngine to monitor and control legacy (APIv2) protocols."""
2
+ from __future__ import annotations
3
+
4
+ import asyncio
5
+ from contextlib import ExitStack
6
+ from typing import Optional
7
+
8
+ from opentrons.legacy_commands.types import CommandMessage as LegacyCommand
9
+ from opentrons.legacy_broker import LegacyBroker
10
+ from opentrons.protocol_api.core.legacy.load_info import LoadInfo
11
+ from opentrons.protocol_engine import AbstractPlugin, actions as pe_actions
12
+ from opentrons.util.broker import ReadOnlyBroker
13
+
14
+ from .legacy_command_mapper import LegacyCommandMapper
15
+
16
+
17
+ class LegacyContextPlugin(AbstractPlugin):
18
+ """A ProtocolEngine plugin to monitor and control an APIv2 protocol.
19
+
20
+ In the legacy ProtocolContext, protocol execution is accomplished
21
+ by direct communication with the HardwareControlAPI, as opposed to an
22
+ intermediate layer like the ProtocolEngine. This plugin wraps up
23
+ and hides this behavior, so the ProtocolEngine can monitor
24
+ the run of a legacy protocol without affecting the execution of
25
+ the protocol commands themselves.
26
+
27
+ This plugin allows a ProtocolEngine to subscribe to what is being done with the
28
+ legacy ProtocolContext, and insert matching commands into ProtocolEngine state for
29
+ purely progress-tracking purposes.
30
+ """
31
+
32
+ def __init__(
33
+ self,
34
+ engine_loop: asyncio.AbstractEventLoop,
35
+ broker: LegacyBroker,
36
+ equipment_broker: ReadOnlyBroker[LoadInfo],
37
+ legacy_command_mapper: Optional[LegacyCommandMapper] = None,
38
+ ) -> None:
39
+ """Initialize the plugin with its dependencies."""
40
+ self._engine_loop = engine_loop
41
+
42
+ self._broker = broker
43
+ self._equipment_broker = equipment_broker
44
+ self._legacy_command_mapper = legacy_command_mapper or LegacyCommandMapper()
45
+
46
+ self._subscription_exit_stack: Optional[ExitStack] = None
47
+
48
+ def setup(self) -> None:
49
+ """Set up the plugin.
50
+
51
+ Subscribe to the APIv2 context's message brokers to be informed
52
+ of the APIv2 protocol's activity.
53
+ """
54
+ # Subscribe to activity on the APIv2 context,
55
+ # and arrange to unsubscribe when this plugin is torn down.
56
+ # Use an exit stack so if any part of this setup fails,
57
+ # we clean up the parts that succeeded in reverse order.
58
+ with ExitStack() as exit_stack:
59
+ command_broker_unsubscribe = self._broker.subscribe(
60
+ topic="command",
61
+ handler=self._handle_legacy_command,
62
+ )
63
+ exit_stack.callback(command_broker_unsubscribe)
64
+
65
+ exit_stack.enter_context(
66
+ self._equipment_broker.subscribed(
67
+ callback=self._handle_equipment_loaded
68
+ )
69
+ )
70
+
71
+ # All subscriptions succeeded.
72
+ # Save the exit stack so our teardown method can use it later
73
+ # to clean up these subscriptions.
74
+ self._subscription_exit_stack = exit_stack.pop_all()
75
+
76
+ # todo(mm, 2024-08-21): This no longer needs to be async.
77
+ async def teardown(self) -> None:
78
+ """Tear down the plugin, undoing the work done in `setup()`.
79
+
80
+ Called by Protocol Engine.
81
+ At this point, the APIv2 protocol script must have exited.
82
+ """
83
+ if self._subscription_exit_stack is not None:
84
+ self._subscription_exit_stack.close()
85
+ self._subscription_exit_stack = None
86
+
87
+ def handle_action(self, action: pe_actions.Action) -> None:
88
+ """React to a ProtocolEngine action."""
89
+ # TODO(jbl 2022-07-06) handle_action stub should be completely removed
90
+ pass
91
+
92
+ def _handle_legacy_command(self, command: LegacyCommand) -> None:
93
+ """Handle a command reported by the legacy APIv2 protocol.
94
+
95
+ Used as a broker callback, so this will run in the APIv2 protocol's thread.
96
+ """
97
+ pe_actions = self._legacy_command_mapper.map_command(command=command)
98
+ future = asyncio.run_coroutine_threadsafe(
99
+ self._dispatch_action_list(pe_actions), self._engine_loop
100
+ )
101
+ future.result()
102
+
103
+ def _handle_equipment_loaded(self, load_info: LoadInfo) -> None:
104
+ """Handle an equipment load reported by the legacy APIv2 protocol.
105
+
106
+ Used as a broker callback, so this will run in the APIv2 protocol's thread.
107
+ """
108
+ pe_actions = self._legacy_command_mapper.map_equipment_load(load_info=load_info)
109
+ future = asyncio.run_coroutine_threadsafe(
110
+ self._dispatch_action_list(pe_actions), self._engine_loop
111
+ )
112
+ future.result()
113
+
114
+ async def _dispatch_action_list(self, actions: list[pe_actions.Action]) -> None:
115
+ for action in actions:
116
+ self.dispatch(action)
@@ -0,0 +1,530 @@
1
+ """Protocol run control and management."""
2
+ import asyncio
3
+ from typing import List, NamedTuple, Optional, Union
4
+
5
+ from abc import ABC, abstractmethod
6
+
7
+ import anyio
8
+
9
+ from opentrons.hardware_control import HardwareControlAPI
10
+ from opentrons import protocol_reader
11
+ from opentrons.legacy_broker import LegacyBroker
12
+ from opentrons.protocol_api import ParameterContext
13
+ from opentrons.protocol_api.core.legacy.load_info import LoadInfo
14
+ from opentrons.protocol_engine.commands.command import CommandStatus
15
+ from opentrons.protocol_engine.error_recovery_policy import ErrorRecoveryType
16
+ from opentrons.protocol_reader import (
17
+ ProtocolSource,
18
+ JsonProtocolConfig,
19
+ PythonProtocolConfig,
20
+ )
21
+ from opentrons.protocol_engine import (
22
+ ProtocolEngine,
23
+ StateSummary,
24
+ Command,
25
+ commands as pe_commands,
26
+ )
27
+ from opentrons.protocol_engine.types import CommandAnnotation
28
+ from opentrons.protocols.parse import PythonParseMode
29
+ from opentrons.util.async_helpers import asyncio_yield
30
+ from opentrons.util.broker import Broker
31
+
32
+ from .task_queue import TaskQueue
33
+ from .json_file_reader import JsonFileReader
34
+ from .json_translator import JsonTranslator
35
+ from .legacy_context_plugin import LegacyContextPlugin
36
+ from .python_protocol_wrappers import (
37
+ LEGACY_PYTHON_API_VERSION_CUTOFF,
38
+ LEGACY_JSON_SCHEMA_VERSION_CUTOFF,
39
+ PythonAndLegacyFileReader,
40
+ ProtocolContextCreator,
41
+ PythonProtocolExecutor,
42
+ )
43
+ from ..protocol_engine.errors import ProtocolCommandFailedError
44
+ from ..protocol_engine.types import (
45
+ PostRunHardwareState,
46
+ DeckConfigurationType,
47
+ RunTimeParameter,
48
+ PrimitiveRunTimeParamValuesType,
49
+ CSVRuntimeParamPaths,
50
+ )
51
+ from ..protocols.types import PythonProtocol
52
+
53
+
54
+ class RunResult(NamedTuple):
55
+ """Result data from a run, pulled from the ProtocolEngine."""
56
+
57
+ commands: List[Command]
58
+ state_summary: StateSummary
59
+ parameters: List[RunTimeParameter]
60
+ command_annotations: List[CommandAnnotation]
61
+
62
+
63
+ class AbstractRunner(ABC):
64
+ """An interface to manage and control a protocol run.
65
+
66
+ A Runner is primarily responsible for feeding a ProtocolEngine
67
+ with commands and control signals. These commands and signals are
68
+ generated by protocol files, hardware signals, or externally via
69
+ the HTTP robot-server.
70
+
71
+ A Runner controls a single run. Once the run is finished,
72
+ you will need a new Runner to do another run.
73
+ """
74
+
75
+ def __init__(self, protocol_engine: ProtocolEngine) -> None:
76
+ self._protocol_engine = protocol_engine
77
+ self._broker = LegacyBroker()
78
+
79
+ # TODO(mm, 2023-10-03): `LegacyBroker` is specific to Python protocols and JSON protocols ≤v5.
80
+ # We'll need to extend this in order to report progress from newer JSON protocols.
81
+ #
82
+ # TODO(mm, 2023-10-04): When we switch this to return a new `Broker` instead of a
83
+ # `LegacyBroker`, we should annotate the return type as a `ReadOnlyBroker`.
84
+ @property
85
+ def broker(self) -> LegacyBroker:
86
+ """Return a broker that you can subscribe to in order to monitor protocol progress.
87
+
88
+ Currently, this only returns messages for `PythonAndLegacyRunner`.
89
+ Otherwise, it's a no-op.
90
+ """
91
+ return self._broker
92
+
93
+ @property
94
+ def run_time_parameters(self) -> List[RunTimeParameter]:
95
+ """Parameter definitions defined by protocol, if any. Currently only for python protocols."""
96
+ return []
97
+
98
+ @property
99
+ def command_annotations(self) -> List[CommandAnnotation]:
100
+ """Command annotations defined by protocol, if any. Currently only for json protocols."""
101
+ return []
102
+
103
+ def was_started(self) -> bool:
104
+ """Whether the run has been started.
105
+
106
+ This value is latched; once it is True, it will never become False.
107
+ """
108
+ return self._protocol_engine.state_view.commands.has_been_played()
109
+
110
+ def play(self, deck_configuration: Optional[DeckConfigurationType] = None) -> None:
111
+ """Start or resume the run."""
112
+ # todo(mm, 2024-07-09): The deck configuration is set at the same time here for
113
+ # historical reasons. It's unsafe to change the deck configuration mid-run
114
+ # and we're relying on the caller to not do that.
115
+ self._protocol_engine.set_deck_configuration(deck_configuration)
116
+ self._protocol_engine.play()
117
+
118
+ def pause(self) -> None:
119
+ """Pause the run."""
120
+ self._protocol_engine.request_pause()
121
+
122
+ async def stop(self) -> None:
123
+ """Stop (cancel) the run."""
124
+ if self.was_started():
125
+ await self._protocol_engine.request_stop()
126
+ else:
127
+ await self._protocol_engine.finish(
128
+ drop_tips_after_run=False,
129
+ set_run_status=False,
130
+ post_run_hardware_state=PostRunHardwareState.STAY_ENGAGED_IN_PLACE,
131
+ )
132
+
133
+ def resume_from_recovery(self, reconcile_false_positive: bool) -> None:
134
+ """See `ProtocolEngine.resume_from_recovery()`."""
135
+ self._protocol_engine.resume_from_recovery(reconcile_false_positive)
136
+
137
+ @abstractmethod
138
+ async def run(
139
+ self,
140
+ deck_configuration: DeckConfigurationType,
141
+ protocol_source: Optional[ProtocolSource] = None,
142
+ run_time_param_values: Optional[PrimitiveRunTimeParamValuesType] = None,
143
+ ) -> RunResult:
144
+ """Run a given protocol to completion."""
145
+
146
+
147
+ class PythonAndLegacyRunner(AbstractRunner):
148
+ """Protocol runner implementation for Python protocols, and JSON protocols ≤v5."""
149
+
150
+ def __init__(
151
+ self,
152
+ protocol_engine: ProtocolEngine,
153
+ hardware_api: HardwareControlAPI,
154
+ task_queue: Optional[TaskQueue] = None,
155
+ python_and_legacy_file_reader: Optional[PythonAndLegacyFileReader] = None,
156
+ protocol_context_creator: Optional[ProtocolContextCreator] = None,
157
+ python_protocol_executor: Optional[PythonProtocolExecutor] = None,
158
+ post_run_hardware_state: PostRunHardwareState = PostRunHardwareState.HOME_AND_STAY_ENGAGED,
159
+ drop_tips_after_run: bool = True,
160
+ ) -> None:
161
+ """Initialize the PythonAndLegacyRunner with its dependencies."""
162
+ super().__init__(protocol_engine)
163
+ self._hardware_api = hardware_api
164
+ self._protocol_file_reader = (
165
+ python_and_legacy_file_reader or PythonAndLegacyFileReader()
166
+ )
167
+ self._protocol_context_creator = (
168
+ protocol_context_creator
169
+ or ProtocolContextCreator(
170
+ hardware_api=hardware_api,
171
+ protocol_engine=protocol_engine,
172
+ )
173
+ )
174
+ self._protocol_executor = python_protocol_executor or PythonProtocolExecutor()
175
+ # TODO(mc, 2022-01-11): replace task queue with specific implementations
176
+ # of runner interface
177
+ self._task_queue = task_queue or TaskQueue()
178
+ self._task_queue.set_cleanup_func(
179
+ func=protocol_engine.finish,
180
+ drop_tips_after_run=drop_tips_after_run,
181
+ post_run_hardware_state=post_run_hardware_state,
182
+ )
183
+ self._parameter_context: Optional[ParameterContext] = None
184
+
185
+ @property
186
+ def run_time_parameters(self) -> List[RunTimeParameter]:
187
+ """Parameter definitions defined by protocol, if any."""
188
+ if self._parameter_context is not None:
189
+ return self._parameter_context.export_parameters_for_analysis()
190
+ return []
191
+
192
+ async def load(
193
+ self,
194
+ protocol_source: ProtocolSource,
195
+ python_parse_mode: PythonParseMode,
196
+ run_time_param_values: Optional[PrimitiveRunTimeParamValuesType],
197
+ run_time_param_paths: Optional[CSVRuntimeParamPaths],
198
+ ) -> None:
199
+ """Load a Python or JSONv5(& older) ProtocolSource into managed ProtocolEngine."""
200
+ labware_definitions = await protocol_reader.extract_labware_definitions(
201
+ protocol_source=protocol_source
202
+ )
203
+ for definition in labware_definitions:
204
+ # Assume adding a labware definition is fast and there are not many labware
205
+ # definitions, so we don't need to yield here.
206
+ self._protocol_engine.add_labware_definition(definition)
207
+
208
+ # fixme(mm, 2022-12-23): This does I/O and compute-bound parsing that will block
209
+ # the event loop. Jira RSS-165.
210
+ protocol = self._protocol_file_reader.read(
211
+ protocol_source, labware_definitions, python_parse_mode
212
+ )
213
+ if isinstance(protocol, PythonProtocol):
214
+ self._parameter_context = ParameterContext(api_version=protocol.api_level)
215
+ run_time_parameters_with_overrides = (
216
+ self._protocol_executor.extract_run_parameters(
217
+ protocol=protocol,
218
+ parameter_context=self._parameter_context,
219
+ run_time_param_overrides=run_time_param_values,
220
+ run_time_param_file_overrides=run_time_param_paths,
221
+ )
222
+ )
223
+ else:
224
+ run_time_parameters_with_overrides = None
225
+ equipment_broker = None
226
+
227
+ if protocol.api_level < LEGACY_PYTHON_API_VERSION_CUTOFF:
228
+ equipment_broker = Broker[LoadInfo]()
229
+ self._protocol_engine.add_plugin(
230
+ LegacyContextPlugin(
231
+ engine_loop=asyncio.get_running_loop(),
232
+ broker=self._broker,
233
+ equipment_broker=equipment_broker,
234
+ )
235
+ )
236
+ self._hardware_api.should_taskify_movement_execution(taskify=True)
237
+ else:
238
+ self._hardware_api.should_taskify_movement_execution(taskify=False)
239
+
240
+ context = self._protocol_context_creator.create(
241
+ protocol=protocol,
242
+ broker=self._broker,
243
+ equipment_broker=equipment_broker,
244
+ )
245
+ initial_home_command = pe_commands.HomeCreate(
246
+ # this command homes all axes, including pipette plunger and gripper jaw
247
+ params=pe_commands.HomeParams(axes=None)
248
+ )
249
+
250
+ async def run_func() -> None:
251
+ await self._protocol_engine.add_and_execute_command(
252
+ request=initial_home_command
253
+ )
254
+ await self._protocol_executor.execute(
255
+ protocol=protocol,
256
+ context=context,
257
+ run_time_parameters_with_overrides=run_time_parameters_with_overrides,
258
+ )
259
+
260
+ self._task_queue.set_run_func(run_func)
261
+
262
+ async def run( # noqa: D102
263
+ self,
264
+ deck_configuration: DeckConfigurationType,
265
+ protocol_source: Optional[ProtocolSource] = None,
266
+ run_time_param_values: Optional[PrimitiveRunTimeParamValuesType] = None,
267
+ run_time_param_paths: Optional[CSVRuntimeParamPaths] = None,
268
+ python_parse_mode: PythonParseMode = PythonParseMode.NORMAL,
269
+ ) -> RunResult:
270
+ # TODO(mc, 2022-01-11): move load to runner creation, remove from `run`
271
+ # currently `protocol_source` arg is only used by tests & protocol analyzer
272
+ if protocol_source:
273
+ await self.load(
274
+ protocol_source=protocol_source,
275
+ python_parse_mode=python_parse_mode,
276
+ run_time_param_values=run_time_param_values,
277
+ run_time_param_paths=run_time_param_paths,
278
+ )
279
+
280
+ self.play(deck_configuration=deck_configuration)
281
+ self._task_queue.start()
282
+ await self._task_queue.join()
283
+
284
+ run_data = self._protocol_engine.state_view.get_summary()
285
+ commands = self._protocol_engine.state_view.commands.get_all()
286
+ parameters = self.run_time_parameters
287
+ return RunResult(
288
+ commands=commands,
289
+ state_summary=run_data,
290
+ parameters=parameters,
291
+ command_annotations=[],
292
+ )
293
+
294
+
295
+ class JsonRunner(AbstractRunner):
296
+ """Protocol runner implementation for json protocols."""
297
+
298
+ def __init__(
299
+ self,
300
+ protocol_engine: ProtocolEngine,
301
+ hardware_api: HardwareControlAPI,
302
+ task_queue: Optional[TaskQueue] = None,
303
+ json_file_reader: Optional[JsonFileReader] = None,
304
+ json_translator: Optional[JsonTranslator] = None,
305
+ post_run_hardware_state: PostRunHardwareState = PostRunHardwareState.HOME_AND_STAY_ENGAGED,
306
+ drop_tips_after_run: bool = True,
307
+ ) -> None:
308
+ """Initialize the JsonRunner with its dependencies."""
309
+ super().__init__(protocol_engine)
310
+ self._protocol_engine = protocol_engine
311
+ self._json_file_reader = json_file_reader or JsonFileReader()
312
+ self._json_translator = json_translator or JsonTranslator()
313
+ # TODO(mc, 2022-01-11): replace task queue with specific implementations
314
+ # of runner interface
315
+ self._task_queue = (
316
+ task_queue or TaskQueue()
317
+ ) # cleanup_func=protocol_engine.finish))
318
+ self._task_queue.set_cleanup_func(
319
+ func=protocol_engine.finish,
320
+ drop_tips_after_run=drop_tips_after_run,
321
+ post_run_hardware_state=post_run_hardware_state,
322
+ )
323
+
324
+ hardware_api.should_taskify_movement_execution(taskify=False)
325
+ self._queued_commands: List[pe_commands.CommandCreate] = []
326
+ self._command_annotations: List[CommandAnnotation] = []
327
+
328
+ @property
329
+ def command_annotations(self) -> List[CommandAnnotation]:
330
+ """Command annotations defined by protocol, if any."""
331
+ return self._command_annotations
332
+
333
+ async def load(self, protocol_source: ProtocolSource) -> None:
334
+ """Load a JSONv6+ ProtocolSource into managed ProtocolEngine."""
335
+ labware_definitions = await protocol_reader.extract_labware_definitions(
336
+ protocol_source=protocol_source
337
+ )
338
+ for definition in labware_definitions:
339
+ # Assume adding a labware definition is fast and there are not many labware
340
+ # definitions, so we don't need to yield here.
341
+ self._protocol_engine.add_labware_definition(definition)
342
+
343
+ protocol = await anyio.to_thread.run_sync(
344
+ self._json_file_reader.read,
345
+ protocol_source,
346
+ )
347
+
348
+ commands = await anyio.to_thread.run_sync(
349
+ self._json_translator.translate_commands,
350
+ protocol,
351
+ )
352
+
353
+ # Add commands and liquids to the ProtocolEngine.
354
+ #
355
+ # We yield on every iteration so that loading large protocols doesn't block the
356
+ # event loop. With a 24-step 10k-command protocol (See RQA-443), adding all the
357
+ # commands can take 3 to 7 seconds.
358
+ #
359
+ # It wouldn't be safe to do this in a worker thread because each addition
360
+ # invokes the ProtocolEngine's ChangeNotifier machinery, which is not
361
+ # thread-safe.
362
+ liquids = await anyio.to_thread.run_sync(
363
+ self._json_translator.translate_liquids, protocol
364
+ )
365
+ for liquid in liquids:
366
+ self._protocol_engine.add_liquid(
367
+ id=liquid.id,
368
+ name=liquid.displayName,
369
+ description=liquid.description,
370
+ color=liquid.displayColor,
371
+ )
372
+ await asyncio_yield()
373
+
374
+ self._command_annotations = await anyio.to_thread.run_sync(
375
+ self._json_translator.translate_command_annotations,
376
+ protocol,
377
+ )
378
+
379
+ initial_home_command = pe_commands.HomeCreate(
380
+ params=pe_commands.HomeParams(axes=None)
381
+ )
382
+ # this command homes all axes, including pipette plugner and gripper jaw
383
+ self._protocol_engine.add_command(request=initial_home_command)
384
+
385
+ self._queued_commands = commands
386
+
387
+ self._task_queue.set_run_func(func=self._add_and_execute_commands)
388
+
389
+ async def run( # noqa: D102
390
+ self,
391
+ deck_configuration: DeckConfigurationType,
392
+ protocol_source: Optional[ProtocolSource] = None,
393
+ run_time_param_values: Optional[PrimitiveRunTimeParamValuesType] = None,
394
+ ) -> RunResult:
395
+ # TODO(mc, 2022-01-11): move load to runner creation, remove from `run`
396
+ # currently `protocol_source` arg is only used by tests
397
+ if protocol_source:
398
+ await self.load(protocol_source)
399
+
400
+ self.play(deck_configuration=deck_configuration)
401
+ self._task_queue.start()
402
+ await self._task_queue.join()
403
+
404
+ run_data = self._protocol_engine.state_view.get_summary()
405
+ commands = self._protocol_engine.state_view.commands.get_all()
406
+ return RunResult(
407
+ commands=commands,
408
+ state_summary=run_data,
409
+ parameters=[],
410
+ command_annotations=self._command_annotations,
411
+ )
412
+
413
+ async def _add_and_execute_commands(self) -> None:
414
+ for command_request in self._queued_commands:
415
+ # todo(mm, 2024-07-05): This logic to handle the various command execution
416
+ # outcomes mirrors PAPI's ChildThreadTransport. Simplify or deduplicate it.
417
+ executed_command = (
418
+ await self._protocol_engine.add_and_execute_command_wait_for_recovery(
419
+ command_request
420
+ )
421
+ )
422
+ if executed_command.error is not None:
423
+ error_recovery_type = (
424
+ self._protocol_engine.state_view.commands.get_error_recovery_type(
425
+ executed_command.id
426
+ )
427
+ )
428
+ error_should_fail_run = (
429
+ error_recovery_type == ErrorRecoveryType.FAIL_RUN
430
+ )
431
+ if error_should_fail_run:
432
+ raise ProtocolCommandFailedError(
433
+ original_error=executed_command.error,
434
+ message=f"{executed_command.error.errorType}: {executed_command.error.detail}",
435
+ )
436
+ elif executed_command.status == CommandStatus.QUEUED:
437
+ # This can happen if another task stops the ProtocolEngine before
438
+ # the ProtocolEngine gets around to executing this command.
439
+ # See docs on add_and_execute_command_wait_for_recovery().
440
+ break
441
+
442
+
443
+ class LiveRunner(AbstractRunner):
444
+ """Protocol runner implementation for live http protocols."""
445
+
446
+ def __init__(
447
+ self,
448
+ protocol_engine: ProtocolEngine,
449
+ hardware_api: HardwareControlAPI,
450
+ task_queue: Optional[TaskQueue] = None,
451
+ ) -> None:
452
+ """Initialize the LiveRunner with its dependencies."""
453
+ super().__init__(protocol_engine)
454
+ self._protocol_engine = protocol_engine
455
+ # TODO(mc, 2022-01-11): replace task queue with specific implementations
456
+ # of runner interface
457
+ self._hardware_api = hardware_api
458
+ self._task_queue = task_queue or TaskQueue()
459
+ self._task_queue.set_cleanup_func(func=protocol_engine.finish)
460
+
461
+ self._hardware_api.should_taskify_movement_execution(taskify=False)
462
+
463
+ # TODO(tz, 6-10-2024): explore moving this method into the constructor.
464
+ def prepare(self) -> None:
465
+ """Set the task queue to wait until all commands are executed."""
466
+ self._task_queue.set_run_func(func=self._protocol_engine.wait_until_complete)
467
+
468
+ async def run( # noqa: D102
469
+ self,
470
+ deck_configuration: DeckConfigurationType,
471
+ protocol_source: Optional[ProtocolSource] = None,
472
+ run_time_param_values: Optional[PrimitiveRunTimeParamValuesType] = None,
473
+ ) -> RunResult:
474
+ assert protocol_source is None
475
+ await self._hardware_api.home()
476
+ self.play(deck_configuration=deck_configuration)
477
+ self._task_queue.start()
478
+ await self._task_queue.join()
479
+
480
+ run_data = self._protocol_engine.state_view.get_summary()
481
+ commands = self._protocol_engine.state_view.commands.get_all()
482
+ return RunResult(
483
+ commands=commands,
484
+ state_summary=run_data,
485
+ parameters=[],
486
+ command_annotations=[],
487
+ )
488
+
489
+
490
+ AnyRunner = Union[PythonAndLegacyRunner, JsonRunner, LiveRunner]
491
+
492
+
493
+ def create_protocol_runner(
494
+ protocol_engine: ProtocolEngine,
495
+ hardware_api: HardwareControlAPI,
496
+ protocol_config: Union[JsonProtocolConfig, PythonProtocolConfig],
497
+ task_queue: Optional[TaskQueue] = None,
498
+ json_file_reader: Optional[JsonFileReader] = None,
499
+ json_translator: Optional[JsonTranslator] = None,
500
+ python_and_legacy_file_reader: Optional[PythonAndLegacyFileReader] = None,
501
+ protocol_context_creator: Optional[ProtocolContextCreator] = None,
502
+ python_protocol_executor: Optional[PythonProtocolExecutor] = None,
503
+ post_run_hardware_state: PostRunHardwareState = PostRunHardwareState.HOME_AND_STAY_ENGAGED,
504
+ drop_tips_after_run: bool = True,
505
+ ) -> Union[JsonRunner, PythonAndLegacyRunner]:
506
+ """Create a protocol runner."""
507
+ if (
508
+ isinstance(protocol_config, JsonProtocolConfig)
509
+ and protocol_config.schema_version >= LEGACY_JSON_SCHEMA_VERSION_CUTOFF
510
+ ):
511
+ return JsonRunner(
512
+ protocol_engine=protocol_engine,
513
+ hardware_api=hardware_api,
514
+ json_file_reader=json_file_reader,
515
+ json_translator=json_translator,
516
+ task_queue=task_queue,
517
+ post_run_hardware_state=post_run_hardware_state,
518
+ drop_tips_after_run=drop_tips_after_run,
519
+ )
520
+ else:
521
+ return PythonAndLegacyRunner(
522
+ protocol_engine=protocol_engine,
523
+ hardware_api=hardware_api,
524
+ task_queue=task_queue,
525
+ python_and_legacy_file_reader=python_and_legacy_file_reader,
526
+ protocol_context_creator=protocol_context_creator,
527
+ python_protocol_executor=python_protocol_executor,
528
+ post_run_hardware_state=post_run_hardware_state,
529
+ drop_tips_after_run=drop_tips_after_run,
530
+ )