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,547 @@
1
+ """ opentrons.protocol_api.module_geometry: classes and functions for modules
2
+ as deck objects
3
+
4
+ This module provides things like :py:class:`ModuleGeometry` and
5
+ :py:func:`load_module` to create and manipulate module objects as geometric
6
+ objects on the deck (as opposed to calling commands on them, which is handled
7
+ by :py:mod:`.module_contexts`)
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import logging
12
+ from enum import Enum
13
+ from typing import TYPE_CHECKING, Optional
14
+
15
+ import numpy as np
16
+ from numpy.typing import NDArray
17
+
18
+ from opentrons_shared_data import module
19
+ from opentrons_shared_data.module.types import ModuleDefinitionV3
20
+ from opentrons_shared_data.module import OLD_TC_GEN2_LABWARE_OFFSET
21
+
22
+ from opentrons.types import Location, Point, LocationLabware
23
+ from opentrons.motion_planning.adjacent_slots_getters import (
24
+ get_north_south_slots,
25
+ get_east_west_slots,
26
+ get_adjacent_slots,
27
+ )
28
+
29
+ from opentrons.drivers.types import ThermocyclerLidStatus
30
+ from opentrons.hardware_control.modules.types import (
31
+ ModuleModel,
32
+ ModuleType,
33
+ module_model_from_string,
34
+ ThermocyclerModuleModel,
35
+ )
36
+
37
+ if TYPE_CHECKING:
38
+ from opentrons.protocol_api.labware import Labware
39
+
40
+
41
+ _log = logging.getLogger(__name__)
42
+
43
+
44
+ class ThermocyclerConfiguration(str, Enum):
45
+ FULL = "full"
46
+ SEMI = "semi"
47
+
48
+
49
+ class NoSuchModuleError(ValueError):
50
+ """An error raised if a requested model does not match a known module."""
51
+
52
+
53
+ class PipetteMovementRestrictedByHeaterShakerError(Exception):
54
+ """Error raised when trying to move to labware restricted by Heater-Shaker."""
55
+
56
+
57
+ # TODO (spp, 2022-05-09): add tests
58
+ class ModuleGeometry:
59
+ """
60
+ This class represents an active peripheral, such as an Opentrons Magnetic
61
+ Module, Temperature Module or Thermocycler Module. It defines the physical
62
+ geometry of the device (primarily the offset that modifies the position of
63
+ the labware mounted on top of it).
64
+ """
65
+
66
+ @property
67
+ def separate_calibration(self) -> bool:
68
+ _log.warning(
69
+ "ModuleGeometry.separate_calibrations is a deprecated internal property."
70
+ " It has no longer has meaning, but will always return `True`"
71
+ )
72
+ return True
73
+
74
+ def __init__(
75
+ self,
76
+ display_name: str,
77
+ model: ModuleModel,
78
+ module_type: ModuleType,
79
+ offset: Point,
80
+ overall_height: float,
81
+ height_over_labware: float,
82
+ parent: Location,
83
+ ) -> None:
84
+ """
85
+ Create a Module for tracking the position of a module.
86
+
87
+ Note that modules do not currently have a concept of calibration apart
88
+ from calibration of labware on top of the module. The practical result
89
+ of this is that if the module parent :py:class:`.Location` is
90
+ incorrect, then a correct calibration of one labware on the deck would
91
+ be incorrect on the module, and vice-versa. Currently, the way around
92
+ this would be to correct the :py:class:`.Location` so that the
93
+ calibrated labware is targeted accurately in both positions.
94
+
95
+ :param display_name: A human-readable display name of only the module
96
+ (for instance, "Thermocycler Module" - not
97
+ including parents or location)
98
+ :param model: The model of module this represents
99
+ :param offset: The offset from the slot origin at which labware loaded
100
+ on this module should be placed
101
+ :param overall_height: The height of the module without labware
102
+ :param height_over_labware: The height of this module over the top of
103
+ the labware
104
+ :param parent: A location representing location of the front left of
105
+ the outside of the module (usually the front-left corner
106
+ of a slot on the deck).
107
+ :type parent: :py:class:`.Location`
108
+ """
109
+ self._parent = parent
110
+ self._module_type = module_type
111
+
112
+ self._display_name = display_name
113
+ self._model = model
114
+ self._offset = offset
115
+ self._height = overall_height + self._parent.point.z
116
+ self._over_labware = height_over_labware
117
+ self._labware: Optional[Labware] = None
118
+ self._location = Location(point=self._offset + self._parent.point, labware=self)
119
+
120
+ def add_labware(self, labware: Labware) -> Labware:
121
+ if self._labware is not None:
122
+ raise RuntimeError(f"{self._labware} is already on this module")
123
+ self._labware = labware
124
+ return self._labware
125
+
126
+ def reset_labware(self) -> None:
127
+ self._labware = None
128
+
129
+ @property
130
+ def display_name(self) -> str:
131
+ return self._display_name
132
+
133
+ @property
134
+ def model(self) -> ModuleModel:
135
+ return self._model
136
+
137
+ @property
138
+ def load_name(self) -> str:
139
+ # Mypy (at the time of writing, v0.910) incorrectly types self.model.value as
140
+ # Any. It seems to have trouble with it being a union of enums.
141
+ assert isinstance(self.model.value, str)
142
+ return self.model.value
143
+
144
+ @property
145
+ def module_type(self) -> ModuleType:
146
+ """The Moduletype"""
147
+ return self._module_type
148
+
149
+ @property
150
+ def parent(self) -> LocationLabware:
151
+ return self._parent.labware.object
152
+
153
+ @property
154
+ def labware(self) -> Optional[Labware]:
155
+ return self._labware
156
+
157
+ @property
158
+ def location(self) -> Location:
159
+ """
160
+ :return: a :py:class:`.Location` representing the top of the module
161
+ """
162
+ return self._location
163
+
164
+ @property
165
+ def labware_offset(self) -> Point:
166
+ """
167
+ :return: a :py:class:`.Point` representing the transformation
168
+ between the critical point of the module and the critical
169
+ point of its contained labware
170
+ """
171
+ return self._offset
172
+
173
+ @property
174
+ def highest_z(self) -> float:
175
+ if self.labware:
176
+ return self.labware.highest_z + self._over_labware
177
+ else:
178
+ return self._height
179
+
180
+ def __repr__(self) -> str:
181
+ location = f" on {self.parent}" if isinstance(self.parent, str) else ""
182
+ return f"{self._display_name}{location}"
183
+
184
+
185
+ class ThermocyclerGeometry(ModuleGeometry):
186
+ def __init__(
187
+ self,
188
+ display_name: str,
189
+ model: ModuleModel,
190
+ module_type: ModuleType,
191
+ offset: Point,
192
+ overall_height: float,
193
+ height_over_labware: float,
194
+ lid_height: float,
195
+ parent: Location,
196
+ configuration: ThermocyclerConfiguration = ThermocyclerConfiguration.FULL,
197
+ ) -> None:
198
+ """
199
+ Create a Module for tracking the position of a module.
200
+
201
+ Note that modules do not currently have a concept of calibration apart
202
+ from calibration of labware on top of the module. The practical result
203
+ of this is that if the module parent :py:class:`.Location` is
204
+ incorrect, then a correct calibration of one labware on the deck would
205
+ be incorrect on the module, and vice-versa. Currently, the way around
206
+ this would be to correct the :py:class:`.Location` so that the
207
+ calibrated labware is targeted accurately in both positions.
208
+
209
+ :param display_name: A human-readable display name of only the module
210
+ (for instance, "Thermocycler Module" - not
211
+ including parents or location)
212
+ :param model: The model of module this represents
213
+ :param offset: The offset from the slot origin at which labware loaded
214
+ on this module should be placed
215
+ :param overall_height: The height of the module without labware
216
+ :param height_over_labware: The height of this module over the top of
217
+ the labware
218
+ :param parent: A location representing location of the front left of
219
+ the outside of the module (usually the front-left corner
220
+ of a slot on the deck).
221
+ :type parent: :py:class:`.Location`
222
+ :param configuration: Used to specify the slot configuration of
223
+ the Thermocycler. It should by of type
224
+ :py:class:`.ThermocyclerConfiguration` and can
225
+ either be FULL or SEMI.
226
+ """
227
+ super().__init__(
228
+ display_name,
229
+ model,
230
+ module_type,
231
+ offset,
232
+ overall_height,
233
+ height_over_labware,
234
+ parent,
235
+ )
236
+ self._lid_height = lid_height
237
+ self._lid_status = ThermocyclerLidStatus.OPEN # Needs to reflect true status
238
+ self._configuration = configuration
239
+ if self.is_semi_configuration:
240
+ self._offset = self._offset + Point(-23.28, 0, 0)
241
+
242
+ @property
243
+ def highest_z(self) -> float:
244
+ # TODO: BC 2019-08-27 this highest_z value represents the distance
245
+ # from the top of the open TC chassis to the base. Once we have a
246
+ # more robust collision detection system in place, the collision
247
+ # model for the TC should change based on it's lid_status
248
+ # (open or closed). A prerequisite for that check will be
249
+ # path-specific highest z calculations, as opposed to the current
250
+ # global check on instrument.move_to. For example: a move from slot 1
251
+ # to slot 3 should only check the highest z of all deck items between
252
+ # the source and destination in the x,y plane.
253
+ return super().highest_z
254
+
255
+ @property
256
+ def lid_status(self) -> ThermocyclerLidStatus:
257
+ return self._lid_status
258
+
259
+ @lid_status.setter
260
+ def lid_status(self, status: ThermocyclerLidStatus) -> None:
261
+ self._lid_status = status
262
+
263
+ @property
264
+ def is_semi_configuration(self) -> bool:
265
+ return bool(self._configuration == ThermocyclerConfiguration.SEMI)
266
+
267
+ # TODO(mc, 2022-11-16): this method causes bugs and should not be used;
268
+ # Thermocycler `configuration="semi"` does not work properly and should be removed
269
+ # https://opentrons.atlassian.net/browse/RSS-106
270
+ def labware_accessor(self, labware: Labware) -> Labware:
271
+ from opentrons.protocol_api.labware import Labware
272
+ from opentrons.protocol_api.core.legacy.legacy_labware_core import (
273
+ LegacyLabwareCore,
274
+ )
275
+
276
+ definition = labware._core.get_definition()
277
+
278
+ # For type checking. This should always pass because
279
+ # opentrons.protocol_api.core.legacy should only load labware with schema 2.
280
+ assert definition["schemaVersion"] == 2
281
+
282
+ # Block first three columns from being accessed
283
+ definition["ordering"] = definition["ordering"][2::]
284
+ return Labware(
285
+ core=LegacyLabwareCore(definition, super().location),
286
+ api_version=labware.api_version,
287
+ protocol_core=None, # type: ignore[arg-type]
288
+ core_map=None, # type: ignore[arg-type]
289
+ )
290
+
291
+ def add_labware(self, labware: Labware) -> Labware:
292
+ if self._labware is not None:
293
+ raise RuntimeError(f"{self._labware} is already on this module")
294
+ if self.lid_status == "closed":
295
+ raise RuntimeError("Cannot place labware in closed module")
296
+ if self.is_semi_configuration:
297
+ self._labware = self.labware_accessor(labware)
298
+ else:
299
+ self._labware = labware
300
+ return self._labware
301
+
302
+ def flag_unsafe_move(
303
+ self,
304
+ to_loc: Location,
305
+ from_loc: Location,
306
+ lid_position: Optional[str],
307
+ ) -> None:
308
+ to_lw, to_well = to_loc.labware.get_parent_labware_and_well()
309
+ from_lw, from_well = from_loc.labware.get_parent_labware_and_well()
310
+
311
+ if (
312
+ self.labware is not None
313
+ and (self.labware == to_lw or self.labware == from_lw)
314
+ and lid_position != "open"
315
+ ):
316
+ raise RuntimeError(
317
+ "Cannot move to labware loaded in Thermocycler"
318
+ " when lid is not fully open."
319
+ )
320
+
321
+
322
+ class HeaterShakerGeometry(ModuleGeometry):
323
+ """Class holding the state of a Heater-Shaker's physical geometry."""
324
+
325
+ def flag_unsafe_move(
326
+ self,
327
+ to_slot: int,
328
+ is_tiprack: bool,
329
+ is_using_multichannel: bool,
330
+ is_labware_latch_closed: bool,
331
+ is_plate_shaking: bool,
332
+ ) -> None:
333
+ """Raise error if unsafe to move pipette due to Heater-Shaker placement."""
334
+ assert isinstance(self.parent, str), "Could not determine module slot location"
335
+
336
+ heater_shaker_slot = int(self.parent)
337
+ dest_east_west = to_slot in get_east_west_slots(heater_shaker_slot)
338
+ dest_north_south = to_slot in get_north_south_slots(heater_shaker_slot)
339
+ dest_heater_shaker = to_slot == heater_shaker_slot
340
+
341
+ # If Heater-Shaker is running, can't move to or around it
342
+ if (
343
+ any([dest_east_west, dest_north_south, dest_heater_shaker])
344
+ and is_plate_shaking
345
+ ):
346
+ raise PipetteMovementRestrictedByHeaterShakerError(
347
+ "Cannot move pipette to Heater-Shaker or adjacent slot while module is shaking"
348
+ )
349
+
350
+ # If Heater-Shaker's latch is open, can't move to it or east and west of it
351
+ elif (dest_east_west or dest_heater_shaker) and not is_labware_latch_closed:
352
+ raise PipetteMovementRestrictedByHeaterShakerError(
353
+ "Cannot move pipette to Heater-Shaker or adjacent slot to the left or right while labware latch is open"
354
+ )
355
+
356
+ elif is_using_multichannel:
357
+ # Can't go to east/west slot under any circumstances if pipette is multi-channel
358
+ if dest_east_west:
359
+ raise PipetteMovementRestrictedByHeaterShakerError(
360
+ "Cannot move 8-Channel pipette to slot adjacent to the left or right of Heater-Shaker"
361
+ )
362
+ # Can only go north/south if the labware is a tip rack
363
+ elif dest_north_south and not is_tiprack:
364
+ raise PipetteMovementRestrictedByHeaterShakerError(
365
+ "Cannot move 8-Channel pipette to non-tip-rack labware directly in front of or behind a Heater-Shaker"
366
+ )
367
+
368
+ def is_pipette_blocking_shake_movement(
369
+ self, pipette_location: Optional[Location]
370
+ ) -> bool:
371
+ """Check whether pipette is parked adjacent to Heater-Shaker.
372
+
373
+ Returns True if pipette's last known location was in a slot adjacent to or
374
+ on the Heater-Shaker. Also returns True if last location is not known or is
375
+ not associated with a slot.
376
+ """
377
+ if pipette_location is None:
378
+ # If we don't know the pipette's latest location then let's be extra
379
+ # cautious and call it blocking
380
+ return True
381
+
382
+ pipette_location_slot = pipette_location.labware.first_parent()
383
+ if pipette_location_slot is None:
384
+ # If a location is not associated w/ a slot (e.g., if it has labware=None)
385
+ # then we don't know if it's close to the h/s, so, we will be cautious
386
+ # and call it blocking
387
+ return True
388
+
389
+ heater_shaker_slot = self.parent
390
+
391
+ assert isinstance(
392
+ heater_shaker_slot, str
393
+ ), "Could not determine module slot location"
394
+
395
+ return heater_shaker_slot == pipette_location_slot or int(
396
+ pipette_location_slot
397
+ ) in get_adjacent_slots(int(heater_shaker_slot))
398
+
399
+ def is_pipette_blocking_latch_movement(
400
+ self, pipette_location: Optional[Location]
401
+ ) -> bool:
402
+ """Check whether pipette is parked left or right of Heater-Shaker.
403
+
404
+ Returns True is pipette's last known location was on the Heater-Shaker
405
+ or in a slot adjacent to its left or right. Also returns True if last
406
+ location is not known or is not associated with a slot.
407
+ """
408
+ if pipette_location is None:
409
+ # If we don't know the pipette's latest location then let's be extra
410
+ # cautious and call it blocking
411
+ return True
412
+
413
+ pipette_location_slot = pipette_location.labware.first_parent()
414
+ if pipette_location_slot is None:
415
+ # If a location is not associated w/ a slot (e.g., if it has labware=None)
416
+ # then we don't know if it's close to the h/s, so, we will be cautious
417
+ # and call it blocking
418
+ return True
419
+
420
+ heater_shaker_slot = self.parent
421
+
422
+ assert isinstance(
423
+ heater_shaker_slot, str
424
+ ), "Could not determine module slot location"
425
+
426
+ return heater_shaker_slot == pipette_location_slot or int(
427
+ pipette_location_slot
428
+ ) in get_east_west_slots(int(heater_shaker_slot))
429
+
430
+
431
+ def create_geometry(
432
+ definition: ModuleDefinitionV3,
433
+ parent: Location,
434
+ configuration: Optional[str],
435
+ ) -> ModuleGeometry:
436
+ """Create a module geometry object from the module's definition and location.
437
+
438
+ The definition should be schema checked before being passed to this
439
+ function; all definitions passed here are assumed to be valid.
440
+ """
441
+ module_type = ModuleType(definition["moduleType"])
442
+ module_model = module_model_from_string(definition["model"])
443
+ overall_height = definition["dimensions"]["bareOverallHeight"]
444
+ height_over_labware = definition["dimensions"]["overLabwareHeight"]
445
+ display_name = definition["displayName"]
446
+
447
+ if module_model == ThermocyclerModuleModel.THERMOCYCLER_V2:
448
+ pre_transform: NDArray[np.double] = np.array(
449
+ (
450
+ OLD_TC_GEN2_LABWARE_OFFSET["x"],
451
+ OLD_TC_GEN2_LABWARE_OFFSET["y"],
452
+ OLD_TC_GEN2_LABWARE_OFFSET["z"],
453
+ 1,
454
+ )
455
+ )
456
+ else:
457
+ pre_transform = np.array(
458
+ (
459
+ definition["labwareOffset"]["x"],
460
+ definition["labwareOffset"]["y"],
461
+ definition["labwareOffset"]["z"],
462
+ 1,
463
+ )
464
+ )
465
+ if not parent.labware.is_slot:
466
+ par = ""
467
+ _log.warning(
468
+ f"module location parent labware was {parent.labware} which is"
469
+ "not a slot name; slot transforms will not be loaded"
470
+ )
471
+ else:
472
+ par = str(parent.labware.object)
473
+
474
+ # This ModuleGeometry class is only used in Python Protocol API versions <=2.13,
475
+ # which only support the OT-2, so we can ignore OT-3s and hard-code "ot2_standard."
476
+ # We also assume that "ot2_short_trash" has the same transforms as "ot2_standard."
477
+ xforms_ser = (
478
+ definition["slotTransforms"]
479
+ .get("ot2_standard", {})
480
+ .get(
481
+ par,
482
+ {"labwareOffset": [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]},
483
+ )
484
+ )
485
+ xform_ser = xforms_ser["labwareOffset"]
486
+
487
+ # apply the slot transform if any
488
+ xform: NDArray[np.double] = np.array(xform_ser)
489
+ xformed = np.dot(xform, pre_transform)
490
+ labware_offset = Point(xformed[0], xformed[1], xformed[2])
491
+
492
+ if module_type == ModuleType.MAGNETIC or module_type == ModuleType.TEMPERATURE:
493
+ return ModuleGeometry(
494
+ parent=parent,
495
+ offset=labware_offset,
496
+ overall_height=overall_height,
497
+ height_over_labware=height_over_labware,
498
+ model=module_model,
499
+ module_type=module_type,
500
+ display_name=display_name,
501
+ )
502
+ elif module_type == ModuleType.THERMOCYCLER:
503
+ return ThermocyclerGeometry(
504
+ parent=parent,
505
+ offset=labware_offset,
506
+ overall_height=overall_height,
507
+ height_over_labware=height_over_labware,
508
+ model=module_model,
509
+ module_type=module_type,
510
+ display_name=display_name,
511
+ lid_height=definition["dimensions"]["lidHeight"],
512
+ configuration=(
513
+ ThermocyclerConfiguration(configuration)
514
+ if configuration is not None
515
+ else ThermocyclerConfiguration.FULL
516
+ ),
517
+ )
518
+ elif module_type == ModuleType.HEATER_SHAKER:
519
+ return HeaterShakerGeometry(
520
+ parent=parent,
521
+ offset=labware_offset,
522
+ overall_height=overall_height,
523
+ height_over_labware=height_over_labware,
524
+ model=module_model,
525
+ module_type=module_type,
526
+ display_name=display_name,
527
+ )
528
+ else:
529
+ raise AssertionError(f"Module type {module_type} is invalid")
530
+
531
+
532
+ def load_definition(model: str) -> ModuleDefinitionV3:
533
+ """Load the geometry definition of a given module by model."""
534
+ try:
535
+ return module.load_definition("3", model)
536
+ except module.ModuleNotFoundError:
537
+ raise NoSuchModuleError(f'Could not find a module with model "{model}"')
538
+
539
+
540
+ def models_compatible(
541
+ requested_model: ModuleModel, candidate_definition: ModuleDefinitionV3
542
+ ) -> bool:
543
+ """Check if a requested model is compatible with a given definition."""
544
+ return (
545
+ requested_model.value == candidate_definition["model"]
546
+ or requested_model.value in candidate_definition["compatibleWith"]
547
+ )
@@ -0,0 +1,148 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional, cast, TYPE_CHECKING
4
+
5
+ from opentrons.types import Point
6
+ from opentrons_shared_data.labware.types import (
7
+ WellDefinition2 as WellDefinition,
8
+ CircularWellDefinition2 as CircularWellDefinition,
9
+ RectangularWellDefinition2 as RectangularWellDefinition,
10
+ )
11
+
12
+ if TYPE_CHECKING:
13
+ from .legacy_labware_core import LegacyLabwareCore
14
+
15
+
16
+ class WellGeometry:
17
+ def __init__(
18
+ self,
19
+ well_props: WellDefinition,
20
+ parent_point: Point,
21
+ parent_object: LegacyLabwareCore,
22
+ ):
23
+ """
24
+ Construct a well geometry object.
25
+
26
+ :param well_props: Properties from the labware definition
27
+ :param parent_point: The coordinate of parent labware
28
+ :param parent_object: The parent labware
29
+ """
30
+
31
+ self._position = (
32
+ Point(
33
+ well_props["x"], well_props["y"], well_props["z"] + well_props["depth"]
34
+ )
35
+ + parent_point
36
+ )
37
+
38
+ if not parent_object:
39
+ raise ValueError("Wells must have a parent")
40
+
41
+ self._parent = parent_object
42
+
43
+ self._length: Optional[float] = None
44
+ self._width: Optional[float] = None
45
+ self._diameter: Optional[float] = None
46
+
47
+ shape = well_props["shape"]
48
+ if shape == "rectangular":
49
+ rect_props = cast(RectangularWellDefinition, well_props)
50
+ self._length = rect_props["xDimension"]
51
+ self._width = rect_props["yDimension"]
52
+ self._x_size = self._length
53
+ self._y_size = self._width
54
+ elif shape == "circular":
55
+ circular_props = cast(CircularWellDefinition, well_props)
56
+ self._diameter = circular_props["diameter"]
57
+ self._x_size = self._y_size = self._diameter
58
+ else:
59
+ raise ValueError(f'Shape "{shape}" is not a supported well shape')
60
+
61
+ self._max_volume = well_props["totalLiquidVolume"]
62
+ self._depth = well_props["depth"]
63
+
64
+ @property
65
+ def parent(self) -> LegacyLabwareCore:
66
+ return self._parent
67
+
68
+ @property
69
+ def position(self) -> Point:
70
+ return self._position
71
+
72
+ @property
73
+ def diameter(self) -> Optional[float]:
74
+ return self._diameter
75
+
76
+ @property
77
+ def length(self) -> Optional[float]:
78
+ return self._length
79
+
80
+ @property
81
+ def width(self) -> Optional[float]:
82
+ return self._width
83
+
84
+ @property
85
+ def depth(self) -> float:
86
+ return self._depth
87
+
88
+ def top(self, z: float = 0.0) -> Point:
89
+ return self._position + Point(0, 0, z)
90
+
91
+ def bottom(self, z: float = 0.0) -> Point:
92
+ top = self.top()
93
+ bottom_z = top.z - self._depth + z
94
+ return Point(x=top.x, y=top.y, z=bottom_z)
95
+
96
+ def center(self) -> Point:
97
+ top = self.top()
98
+ center_z = top.z - (self._depth / 2.0)
99
+ return Point(x=top.x, y=top.y, z=center_z)
100
+
101
+ @property
102
+ def max_volume(self) -> float:
103
+ return self._max_volume
104
+
105
+ def from_center_cartesian(self, x: float, y: float, z: float) -> Point:
106
+ """
107
+ Specifies an arbitrary point in deck coordinates based
108
+ on percentages of the radius in each axis. For example, to specify the
109
+ back-right corner of a well at 1/4 of the well depth from the bottom,
110
+ the call would be `from_center_cartesian(1, 1, -0.5)`.
111
+
112
+ No checks are performed to ensure that the resulting position will be
113
+ inside of the well.
114
+
115
+ To use this point in a liquid handling command, you must create a
116
+ location object using the well such as,
117
+
118
+ .. code-block:: python
119
+
120
+ from opentrons import types
121
+
122
+ # Cannot be passed into a liquid handling function
123
+ point = well.from_center_cartesian(1, 1, -0.5)
124
+
125
+ # Can be passed into a liquid handling function
126
+ location = types.Location(
127
+ well.from_center_cartesian(1, 1, -0.5), well)
128
+
129
+ :param x: a float in the range [-1.0, 1.0] for a percentage of half of
130
+ the radius/length in the X axis
131
+ :param y: a float in the range [-1.0, 1.0] for a percentage of half of
132
+ the radius/width in the Y axis
133
+ :param z: a float in the range [-1.0, 1.0] for a percentage of half of
134
+ the height above/below the center
135
+
136
+ :return: a Point representing the specified location in absolute deck
137
+ coordinates
138
+ """
139
+ center = self.center()
140
+ x_size = self._x_size
141
+ y_size = self._y_size
142
+ z_size = self._depth
143
+
144
+ return Point(
145
+ x=center.x + (x * (x_size / 2.0)),
146
+ y=center.y + (y * (y_size / 2.0)),
147
+ z=center.z + (z * (z_size / 2.0)),
148
+ )