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,731 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+ from typing import Callable, Optional, List, Dict, Mapping, Union, cast
6
+ from opentrons.drivers.rpi_drivers.types import USBPort
7
+ from opentrons.drivers.types import ThermocyclerLidStatus, Temperature, PlateTemperature
8
+ from opentrons.hardware_control.modules.lid_temp_status import LidTemperatureStatus
9
+ from opentrons.hardware_control.modules.plate_temp_status import PlateTemperatureStatus
10
+ from opentrons.hardware_control.modules.types import (
11
+ ModuleDisconnectedCallback,
12
+ TemperatureStatus,
13
+ )
14
+ from opentrons.hardware_control.poller import Reader, Poller
15
+
16
+ from ..execution_manager import ExecutionManager
17
+ from . import types, update, mod_abc
18
+ from opentrons.drivers.thermocycler import (
19
+ AbstractThermocyclerDriver,
20
+ SimulatingDriver,
21
+ ThermocyclerDriverV2,
22
+ ThermocyclerDriverFactory,
23
+ )
24
+
25
+
26
+ log = logging.getLogger(__name__)
27
+
28
+ POLLING_FREQUENCY_SEC = 1.0
29
+ SIM_POLLING_FREQUENCY_SEC = POLLING_FREQUENCY_SEC / 50.0
30
+
31
+ V1_MODULE_STRING = "thermocyclerModuleV1"
32
+ V2_MODULE_STRING = "thermocyclerModuleV2"
33
+
34
+ DFU_PID = "df11"
35
+
36
+ _TC_PLATE_LIFT_OPEN_DEGREES = 20
37
+ _TC_PLATE_LIFT_RETURN_DEGREES = 23
38
+
39
+
40
+ class ThermocyclerError(Exception):
41
+ pass
42
+
43
+
44
+ def _temperature_is_holding(status: Optional[TemperatureStatus]) -> bool:
45
+ if status in (TemperatureStatus.HOLDING, TemperatureStatus.IDLE):
46
+ return True
47
+
48
+ if status == TemperatureStatus.ERROR:
49
+ raise ThermocyclerError("Error occurred while waiting for temperature")
50
+
51
+ return False
52
+
53
+
54
+ class Thermocycler(mod_abc.AbstractModule):
55
+ """Hardware control interface for an attached Thermocycler."""
56
+
57
+ MODULE_TYPE = types.ModuleType.THERMOCYCLER
58
+
59
+ @classmethod
60
+ async def build(
61
+ cls,
62
+ port: str,
63
+ usb_port: USBPort,
64
+ hw_control_loop: asyncio.AbstractEventLoop,
65
+ execution_manager: Optional[ExecutionManager] = None,
66
+ poll_interval_seconds: Optional[float] = None,
67
+ simulating: bool = False,
68
+ sim_model: Optional[str] = None,
69
+ sim_serial_number: Optional[str] = None,
70
+ disconnected_callback: ModuleDisconnectedCallback = None,
71
+ ) -> "Thermocycler":
72
+ """
73
+ Build and connect to a Thermocycler
74
+
75
+ Args:
76
+ port: The port to connect to
77
+ usb_port: USB Port
78
+ hw_control_loop: The event loop running in the hardware control thread.
79
+ execution_manager: Execution manager.
80
+ poll_interval_seconds: Poll interval override.
81
+ simulating: whether to build a simulating driver
82
+ loop: Loop
83
+ sim_model: The model name used by simulator
84
+ disconnected_callback: Callback to inform the module controller that the device was disconnected
85
+
86
+ Returns:
87
+ Thermocycler instance.
88
+ """
89
+ driver: AbstractThermocyclerDriver
90
+ if not simulating:
91
+ driver = await ThermocyclerDriverFactory.create(
92
+ port=port, loop=hw_control_loop
93
+ )
94
+ poll_interval_seconds = poll_interval_seconds or POLLING_FREQUENCY_SEC
95
+ else:
96
+ driver = SimulatingDriver(model=sim_model, serial_number=sim_serial_number)
97
+ poll_interval_seconds = poll_interval_seconds or SIM_POLLING_FREQUENCY_SEC
98
+
99
+ reader = ThermocyclerReader(driver=driver)
100
+ poller = Poller(reader=reader, interval=poll_interval_seconds)
101
+ module = cls(
102
+ port=port,
103
+ usb_port=usb_port,
104
+ driver=driver,
105
+ reader=reader,
106
+ poller=poller,
107
+ device_info=await driver.get_device_info(),
108
+ hw_control_loop=hw_control_loop,
109
+ execution_manager=execution_manager,
110
+ disconnected_callback=disconnected_callback,
111
+ )
112
+
113
+ try:
114
+ await poller.start()
115
+ except Exception:
116
+ log.exception(f"First read of Thermocycler on port {port} failed")
117
+
118
+ return module
119
+
120
+ def __init__(
121
+ self,
122
+ port: str,
123
+ usb_port: USBPort,
124
+ driver: AbstractThermocyclerDriver,
125
+ reader: ThermocyclerReader,
126
+ poller: Poller,
127
+ device_info: Dict[str, str],
128
+ hw_control_loop: asyncio.AbstractEventLoop,
129
+ execution_manager: Optional[ExecutionManager] = None,
130
+ disconnected_callback: ModuleDisconnectedCallback = None,
131
+ ) -> None:
132
+ """
133
+ Constructor
134
+
135
+ Args:
136
+ port: The port the thermocycler is connected to.
137
+ usb_port: The USB port.
138
+ driver: The thermocycler driver.
139
+ reader: An interface to read data from the Thermocycler.
140
+ poller: A poll controller for reads.
141
+ device_info: The thermocycler device info.
142
+ hw_control_loop: The event loop running in the hardware control thread.
143
+ execution_manager: The hardware execution manager.
144
+ disconnected_callback: Callback to inform the module controller that the device was disconnected
145
+ """
146
+ self._driver = driver
147
+ super().__init__(
148
+ port=port,
149
+ usb_port=usb_port,
150
+ hw_control_loop=hw_control_loop,
151
+ execution_manager=execution_manager,
152
+ disconnected_callback=disconnected_callback,
153
+ )
154
+ self._device_info = device_info
155
+ self._reader = reader
156
+ self._poller = poller
157
+ self._total_cycle_count: Optional[int] = None
158
+ self._current_cycle_index: Optional[int] = None
159
+ self._total_step_count: Optional[int] = None
160
+ self._current_step_index: Optional[int] = None
161
+ self._error: Optional[str] = None
162
+ self._reader.register_error_handler(self._enter_error_state)
163
+
164
+ async def cleanup(self) -> None:
165
+ """Stop the poller task."""
166
+ await self._poller.stop()
167
+ await self._driver.disconnect()
168
+
169
+ @classmethod
170
+ def name(cls) -> str:
171
+ return "thermocycler"
172
+
173
+ def firmware_prefix(self) -> str:
174
+ """The prefix used for looking up firmware"""
175
+ if self.model() == V1_MODULE_STRING:
176
+ return "thermocycler"
177
+ else:
178
+ return "thermocycler-gen2"
179
+
180
+ def model(self) -> str:
181
+ if isinstance(self._driver, SimulatingDriver):
182
+ return self._driver.model()
183
+ elif isinstance(self._driver, ThermocyclerDriverV2):
184
+ return V2_MODULE_STRING
185
+ else:
186
+ # Real module that is not a V2
187
+ return V1_MODULE_STRING
188
+
189
+ def bootloader(self) -> types.UploadFunction:
190
+ if self.model() == V2_MODULE_STRING:
191
+ return update.upload_via_dfu
192
+ else:
193
+ return update.upload_via_bossa
194
+
195
+ def _clear_cycle_counters(self) -> None:
196
+ """Clear the cycle counters."""
197
+ self._total_cycle_count = None
198
+ self._current_cycle_index = None
199
+ self._total_step_count = None
200
+ self._current_step_index = None
201
+
202
+ async def deactivate_lid(self, must_be_running: bool = True) -> None:
203
+ """Deactivate the lid heating pad"""
204
+ if must_be_running:
205
+ await self.wait_for_is_running()
206
+ await self._driver.deactivate_lid()
207
+ await self._reader.read_lid_temperature()
208
+
209
+ async def deactivate_block(self, must_be_running: bool = True) -> None:
210
+ """Deactivate the block peltiers"""
211
+ if must_be_running:
212
+ await self.wait_for_is_running()
213
+ self._clear_cycle_counters()
214
+ await self._driver.deactivate_block()
215
+ await self._reader.read_block_temperature()
216
+
217
+ async def deactivate(self, must_be_running: bool = True) -> None:
218
+ """Deactivate the block peltiers and lid heating pad"""
219
+ if must_be_running:
220
+ await self.wait_for_is_running()
221
+ self._clear_cycle_counters()
222
+ await self._driver.deactivate_all()
223
+ await self._reader.read()
224
+
225
+ async def open(self) -> str:
226
+ """Open the lid if it is closed"""
227
+ await self.wait_for_is_running()
228
+ await self._driver.open_lid()
229
+ await self._wait_for_lid_status(ThermocyclerLidStatus.OPEN)
230
+ return ThermocyclerLidStatus.OPEN
231
+
232
+ async def close(self) -> str:
233
+ """Close the lid if it is open"""
234
+ await self.wait_for_is_running()
235
+ await self._driver.close_lid()
236
+ await self._wait_for_lid_status(ThermocyclerLidStatus.CLOSED)
237
+ return ThermocyclerLidStatus.CLOSED
238
+
239
+ async def lift_plate(self) -> str:
240
+ """If the lid is open, lift the plate.
241
+
242
+ Note that this should always be preceded by an `open` call. If the
243
+ lid is not open, the Thermocycler will respond with an error message.
244
+
245
+ Returns: Thermocycler lid status after running the command.
246
+ """
247
+ await self.wait_for_is_running()
248
+ await self._driver.lift_plate()
249
+ await self._wait_for_lid_status(ThermocyclerLidStatus.OPEN)
250
+ return ThermocyclerLidStatus.OPEN
251
+
252
+ async def raise_plate(self) -> None:
253
+ """Move lid an extra bit."""
254
+ if not self.lid_status == ThermocyclerLidStatus.OPEN:
255
+ raise RuntimeError("Lid must be open")
256
+ await self.wait_for_is_running()
257
+ await self._driver.jog_lid(_TC_PLATE_LIFT_OPEN_DEGREES)
258
+ # There is NO WAIT for the updated lid stats, because it will always
259
+ # remain at "open"
260
+
261
+ async def return_from_raise_plate(self) -> None:
262
+ """Return lid back to normal open position."""
263
+ await self.wait_for_is_running()
264
+ await self._driver.jog_lid(-_TC_PLATE_LIFT_RETURN_DEGREES)
265
+ await self.open()
266
+ await self._wait_for_lid_status(ThermocyclerLidStatus.OPEN)
267
+
268
+ async def set_temperature(
269
+ self,
270
+ temperature: float,
271
+ hold_time_seconds: Optional[float] = None,
272
+ hold_time_minutes: Optional[float] = None,
273
+ ramp_rate: Optional[float] = None,
274
+ volume: Optional[float] = None,
275
+ ) -> None:
276
+ """
277
+ Set the temperature and wait.
278
+
279
+ If hold time is set this function will return after
280
+ the hold time expires.
281
+
282
+ Otherwise it will return when the target temperature is reached.
283
+
284
+ Args:
285
+ temperature: The target temperature.
286
+ hold_time_seconds: Optional number of seconds to wait.
287
+ hold_time_minutes: Optional number of minutes to wait.
288
+ ramp_rate: Optional ramp rate.
289
+ volume: Optional volume.
290
+
291
+ Returns: None
292
+ """
293
+ await self.wait_for_is_running()
294
+ await self._set_temperature_no_pause(
295
+ temperature=temperature,
296
+ hold_time_seconds=hold_time_seconds,
297
+ hold_time_minutes=hold_time_minutes,
298
+ ramp_rate=ramp_rate,
299
+ volume=volume,
300
+ )
301
+
302
+ async def _set_temperature_no_pause(
303
+ self,
304
+ temperature: float,
305
+ hold_time_seconds: Optional[float],
306
+ hold_time_minutes: Optional[float],
307
+ ramp_rate: Optional[float],
308
+ volume: Optional[float],
309
+ ) -> None:
310
+ seconds = hold_time_seconds if hold_time_seconds is not None else 0
311
+ minutes = hold_time_minutes if hold_time_minutes is not None else 0
312
+ total_seconds = seconds + (minutes * 60)
313
+ hold_time = total_seconds if total_seconds > 0 else 0
314
+
315
+ if ramp_rate is not None:
316
+ await self._driver.set_ramp_rate(ramp_rate=ramp_rate)
317
+
318
+ await self._driver.set_plate_temperature(
319
+ temp=temperature, hold_time=hold_time, volume=volume
320
+ )
321
+
322
+ task = self._loop.create_task(self._wait_for_block_target())
323
+ self.make_cancellable(task)
324
+ await task
325
+
326
+ async def wait_for_block_target(self) -> None:
327
+ """
328
+ Wait for thermocycler to reach given temperature.
329
+
330
+ Will return when the target temperature is reached.
331
+
332
+ Args:
333
+ temperature: The target temperature.
334
+
335
+ Returns: None
336
+ """
337
+ await self.wait_for_is_running()
338
+ task = self._loop.create_task(self._wait_for_block_target())
339
+ self.make_cancellable(task)
340
+ await task
341
+
342
+ async def cycle_temperatures(
343
+ self,
344
+ steps: List[types.ThermocyclerStep],
345
+ repetitions: int,
346
+ volume: Optional[float] = None,
347
+ ) -> None:
348
+ """
349
+ Begin a set temperature cycle.
350
+
351
+ Args:
352
+ steps: The set temperature steps.
353
+ repetitions: Number of repetitions.
354
+ volume: Optional volume.
355
+
356
+ Returns: None
357
+ """
358
+ await self.wait_for_is_running()
359
+ self._total_cycle_count = repetitions
360
+ self._total_step_count = len(steps)
361
+
362
+ task = self._loop.create_task(self._execute_cycles(steps, repetitions, volume))
363
+ self.make_cancellable(task)
364
+ await task
365
+
366
+ async def execute_profile(
367
+ self,
368
+ profile: List[Union[types.ThermocyclerCycle, types.ThermocyclerStep]],
369
+ volume: Optional[float] = None,
370
+ ) -> None:
371
+ """Begin a set temperature profile, with both repeating and non-repeating steps.
372
+
373
+ Args:
374
+ profile: The temperature profile to follow.
375
+ volume: Optional volume
376
+
377
+ Returns: None
378
+ """
379
+ await self.wait_for_is_running()
380
+ self._total_cycle_count = 0
381
+ self._total_step_count = 0
382
+ self._current_cycle_index = 0
383
+ self._current_step_index = 0
384
+ for step_or_cycle in profile:
385
+ if "steps" in step_or_cycle:
386
+ # basically https://github.com/python/mypy/issues/14766
387
+ this_cycle = cast(types.ThermocyclerCycle, step_or_cycle)
388
+ self._total_cycle_count += this_cycle["repetitions"]
389
+ self._total_step_count += (
390
+ len(this_cycle["steps"]) * this_cycle["repetitions"]
391
+ )
392
+ else:
393
+ self._total_step_count += 1
394
+ self._total_cycle_count += 1
395
+ task = self._loop.create_task(self._execute_profile(profile, volume))
396
+ self.make_cancellable(task)
397
+ await task
398
+
399
+ async def set_lid_temperature(self, temperature: float) -> None:
400
+ """Set the lid temperature in degrees Celsius"""
401
+ await self.wait_for_is_running()
402
+ await self._driver.set_lid_temperature(temp=temperature)
403
+
404
+ task = self._loop.create_task(self._wait_for_lid_target())
405
+ self.make_cancellable(task)
406
+ await task
407
+
408
+ async def wait_for_lid_target(self) -> None:
409
+ """Set the lid temperature in degrees Celsius"""
410
+ await self.wait_for_is_running()
411
+
412
+ task = self._loop.create_task(self._wait_for_lid_target())
413
+ self.make_cancellable(task)
414
+ await task
415
+
416
+ # TODO(mc, 2022-04-25): de-duplicate with `set_temperature`
417
+ async def set_target_block_temperature(
418
+ self,
419
+ celsius: float,
420
+ hold_time_seconds: Optional[float] = None,
421
+ volume: Optional[float] = None,
422
+ ) -> None:
423
+ """Set the Thermocycler's target block temperature.
424
+
425
+ Does not wait for the target temperature to be reached.
426
+
427
+ Args:
428
+ celsius: The target block temperature, in degrees celsius.
429
+ """
430
+ await self.wait_for_is_running()
431
+ await self._driver.set_plate_temperature(
432
+ temp=celsius,
433
+ hold_time=hold_time_seconds,
434
+ volume=volume,
435
+ )
436
+ await self._reader.read_block_temperature()
437
+
438
+ # TODO(mc, 2022-04-26): de-duplicate with `set_lid_temperature`
439
+ async def set_target_lid_temperature(self, celsius: float) -> None:
440
+ """Set the Thermocycler's target lid temperature.
441
+
442
+ Does not wait for the target temperature to be reached.
443
+
444
+ Args:
445
+ celsius: The target lid temperature, in degrees celsius.
446
+ """
447
+ await self.wait_for_is_running()
448
+ await self._driver.set_lid_temperature(temp=celsius)
449
+ await self._reader.read_lid_temperature()
450
+
451
+ async def _wait_for_lid_target(self) -> None:
452
+ """
453
+ This method only exits if lid target temperature has been reached.
454
+
455
+ Subject to change without a version bump.
456
+ """
457
+ await self._reader.read_lid_temperature()
458
+
459
+ while not _temperature_is_holding(self.lid_temp_status):
460
+ await self._poller.wait_next_poll()
461
+
462
+ async def _wait_for_block_target(self) -> None:
463
+ """
464
+ This method only exits if set temperature has been reached.
465
+
466
+ Subject to change without a version bump.
467
+ """
468
+ await self._reader.read_block_temperature()
469
+
470
+ while not _temperature_is_holding(self.status):
471
+ await self._poller.wait_next_poll()
472
+
473
+ while self.hold_time is not None and self.hold_time > 0:
474
+ await self._poller.wait_next_poll()
475
+
476
+ async def _wait_for_lid_status(self, status: ThermocyclerLidStatus) -> None:
477
+ """Wait for lid status to be status."""
478
+ await self._reader.read_lid_status()
479
+
480
+ while self.lid_status != status:
481
+ await self._poller.wait_next_poll()
482
+
483
+ @property
484
+ def lid_target(self) -> Optional[float]:
485
+ return self._reader.lid_temperature.target
486
+
487
+ @property
488
+ def lid_temp(self) -> float:
489
+ return self._reader.lid_temperature.current
490
+
491
+ @property
492
+ def lid_status(self) -> ThermocyclerLidStatus:
493
+ return self._reader.lid_status
494
+
495
+ @property
496
+ def lid_temp_status(self) -> TemperatureStatus:
497
+ return self._reader.lid_temperature_status
498
+
499
+ # TODO(mc, 2022-10-13): remove
500
+ @property
501
+ def ramp_rate(self) -> Optional[float]:
502
+ """Not supported."""
503
+ return None
504
+
505
+ @property
506
+ def hold_time(self) -> Optional[float]:
507
+ return self._reader.block_temperature.hold
508
+
509
+ @property
510
+ def temperature(self) -> Optional[float]:
511
+ return self._reader.block_temperature.current
512
+
513
+ @property
514
+ def target(self) -> Optional[float]:
515
+ return self._reader.block_temperature.target
516
+
517
+ @property
518
+ def status(self) -> TemperatureStatus:
519
+ return (
520
+ self._reader.block_temperature_status
521
+ if self._error is None
522
+ else TemperatureStatus.ERROR
523
+ )
524
+
525
+ @property
526
+ def device_info(self) -> Mapping[str, str]:
527
+ return self._device_info
528
+
529
+ @property
530
+ def total_cycle_count(self) -> Optional[int]:
531
+ return self._total_cycle_count
532
+
533
+ @property
534
+ def current_cycle_index(self) -> Optional[int]:
535
+ return self._current_cycle_index
536
+
537
+ @property
538
+ def total_step_count(self) -> Optional[int]:
539
+ return self._total_step_count
540
+
541
+ @property
542
+ def current_step_index(self) -> Optional[int]:
543
+ return self._current_step_index
544
+
545
+ @property
546
+ def live_data(self) -> types.LiveData:
547
+ data: types.ThermocyclerData = {
548
+ "lid": self.lid_status,
549
+ "lidTarget": self.lid_target,
550
+ "lidTemp": self.lid_temp,
551
+ "lidTempStatus": self.lid_temp_status,
552
+ "currentTemp": self.temperature,
553
+ "targetTemp": self.target,
554
+ "holdTime": self.hold_time,
555
+ "rampRate": self.ramp_rate,
556
+ "currentCycleIndex": self.current_cycle_index,
557
+ "totalCycleCount": self.total_cycle_count,
558
+ "currentStepIndex": self.current_step_index,
559
+ "totalStepCount": self.total_step_count,
560
+ }
561
+ return {
562
+ "status": self.status,
563
+ "data": data,
564
+ }
565
+
566
+ @property
567
+ def is_simulated(self) -> bool:
568
+ return isinstance(self._driver, SimulatingDriver)
569
+
570
+ async def prep_for_update(self) -> str:
571
+ await self._poller.stop()
572
+ await self._driver.enter_programming_mode()
573
+
574
+ if self.model() == V2_MODULE_STRING:
575
+ # TC2 has three unique "devices" over DFU
576
+ new_port = await update.find_dfu_device(
577
+ pid=DFU_PID, expected_device_count=3
578
+ )
579
+ else:
580
+ new_port = await update.find_bootloader_port()
581
+
582
+ return new_port or self.port
583
+
584
+ async def _execute_cycle_step(
585
+ self, step: types.ThermocyclerStep, volume: Optional[float]
586
+ ) -> None:
587
+ """
588
+ Execute a thermocycler step.
589
+
590
+ Args:
591
+ step: The set temperature parameters.
592
+ volume: The volume
593
+
594
+ Returns: None
595
+ """
596
+ temperature = step.get("temperature")
597
+ hold_time_minutes = step.get("hold_time_minutes", None)
598
+ hold_time_seconds = step.get("hold_time_seconds", None)
599
+ await self._set_temperature_no_pause(
600
+ temperature=temperature, # type: ignore
601
+ hold_time_minutes=hold_time_minutes,
602
+ hold_time_seconds=hold_time_seconds,
603
+ ramp_rate=None,
604
+ volume=volume,
605
+ )
606
+
607
+ async def _execute_cycles(
608
+ self,
609
+ steps: List[types.ThermocyclerStep],
610
+ repetitions: int,
611
+ volume: Optional[float],
612
+ ) -> None:
613
+ """
614
+ Execute cycles.
615
+
616
+ Args:
617
+ steps: The set temperature steps.
618
+ repetitions: The number of repetitions
619
+ volume: The optional volume.
620
+
621
+ Returns: None
622
+ """
623
+ for rep in range(repetitions):
624
+ self._current_cycle_index = rep + 1 # science starts at 1
625
+ for step_idx, step in enumerate(steps):
626
+ self._current_step_index = step_idx + 1 # science starts at 1
627
+ await self._execute_cycle_step(step, volume)
628
+
629
+ async def _execute_profile(
630
+ self,
631
+ profile: List[Union[types.ThermocyclerCycle, types.ThermocyclerStep]],
632
+ volume: Optional[float],
633
+ ) -> None:
634
+ """
635
+ Execute profiles.
636
+
637
+ Profiles command a thermocycler pattern that can contain multiple cycles and out-of-cycle steps.
638
+ """
639
+ self._current_cycle_index = 0
640
+ self._current_step_index = 0
641
+ for step_or_cycle in profile:
642
+ self._current_cycle_index += 1
643
+ if "repetitions" in step_or_cycle:
644
+ # basically https://github.com/python/mypy/issues/14766
645
+ this_cycle = cast(types.ThermocyclerCycle, step_or_cycle)
646
+ for rep in range(this_cycle["repetitions"]):
647
+ for step in this_cycle["steps"]:
648
+ self._current_step_index += 1
649
+ await self._execute_cycle_step(step, volume)
650
+ else:
651
+ await self._execute_cycle_step(step_or_cycle, volume)
652
+
653
+ # TODO(mc, 2022-10-13): why does this exist?
654
+ # Do the driver and poller really need to be disconnected?
655
+ # Could we accomplish the same thing by latching the error state
656
+ # and allowing the driver and poller to continue?
657
+ def _enter_error_state(self, error: Exception) -> None:
658
+ """Enter into an error state.
659
+
660
+ The Thermocycler will not be accessible in this state.
661
+
662
+ Args:
663
+ cause: The cause of the exception.
664
+
665
+ Returns:
666
+ None
667
+ """
668
+ self._error = str(error)
669
+ log.error(
670
+ f"Thermocycler has encountered an unrecoverable error: {self._error}. "
671
+ f"Please refer to support article at "
672
+ f"https://support.opentrons.com/en/articles/3469797-thermocycler-module"
673
+ f" for troubleshooting."
674
+ )
675
+ asyncio.run_coroutine_threadsafe(self.cleanup(), self._loop)
676
+
677
+
678
+ class ThermocyclerReader(Reader):
679
+ """Read data from the thermocycler.
680
+
681
+ Args:
682
+ driver: A connected Thermocycler driver.
683
+ """
684
+
685
+ lid_status: ThermocyclerLidStatus
686
+ lid_temperature: Temperature
687
+ block_temperature: PlateTemperature
688
+
689
+ def __init__(
690
+ self,
691
+ driver: AbstractThermocyclerDriver,
692
+ ) -> None:
693
+ self.lid_status = ThermocyclerLidStatus.UNKNOWN
694
+ self.lid_temperature = Temperature(current=25.0, target=None)
695
+ self.block_temperature = PlateTemperature(current=25.0, target=None, hold=None)
696
+ self._lid_temperature_status = LidTemperatureStatus()
697
+ self._block_temperature_status = PlateTemperatureStatus()
698
+ self._driver = driver
699
+ self._handle_error: Optional[Callable[[Exception], None]] = None
700
+
701
+ @property
702
+ def block_temperature_status(self) -> TemperatureStatus:
703
+ return self._block_temperature_status.status
704
+
705
+ @property
706
+ def lid_temperature_status(self) -> TemperatureStatus:
707
+ return self._lid_temperature_status.status
708
+
709
+ def on_error(self, exception: Exception) -> None:
710
+ if self._handle_error is not None:
711
+ self._handle_error(exception)
712
+
713
+ def register_error_handler(self, handle_error: Callable[[Exception], None]) -> None:
714
+ self._handle_error = handle_error
715
+
716
+ async def read(self) -> None:
717
+ """Poll the thermocycler."""
718
+ await self.read_lid_status()
719
+ await self.read_lid_temperature()
720
+ await self.read_block_temperature()
721
+
722
+ async def read_lid_status(self) -> None:
723
+ self.lid_status = await self._driver.get_lid_status()
724
+
725
+ async def read_block_temperature(self) -> None:
726
+ self.block_temperature = await self._driver.get_plate_temperature()
727
+ self._block_temperature_status.update(self.block_temperature)
728
+
729
+ async def read_lid_temperature(self) -> None:
730
+ self.lid_temperature = await self._driver.get_lid_temperature()
731
+ self._lid_temperature_status.update(self.lid_temperature)