opentrons 8.6.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (601) hide show
  1. opentrons/__init__.py +150 -0
  2. opentrons/_version.py +34 -0
  3. opentrons/calibration_storage/__init__.py +54 -0
  4. opentrons/calibration_storage/deck_configuration.py +62 -0
  5. opentrons/calibration_storage/encoder_decoder.py +31 -0
  6. opentrons/calibration_storage/file_operators.py +142 -0
  7. opentrons/calibration_storage/helpers.py +103 -0
  8. opentrons/calibration_storage/ot2/__init__.py +34 -0
  9. opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
  10. opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
  11. opentrons/calibration_storage/ot2/models/__init__.py +0 -0
  12. opentrons/calibration_storage/ot2/models/v1.py +149 -0
  13. opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
  14. opentrons/calibration_storage/ot2/tip_length.py +281 -0
  15. opentrons/calibration_storage/ot3/__init__.py +31 -0
  16. opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
  17. opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
  18. opentrons/calibration_storage/ot3/models/__init__.py +0 -0
  19. opentrons/calibration_storage/ot3/models/v1.py +122 -0
  20. opentrons/calibration_storage/ot3/module_offset.py +138 -0
  21. opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
  22. opentrons/calibration_storage/types.py +45 -0
  23. opentrons/cli/__init__.py +21 -0
  24. opentrons/cli/__main__.py +5 -0
  25. opentrons/cli/analyze.py +557 -0
  26. opentrons/config/__init__.py +631 -0
  27. opentrons/config/advanced_settings.py +871 -0
  28. opentrons/config/defaults_ot2.py +214 -0
  29. opentrons/config/defaults_ot3.py +499 -0
  30. opentrons/config/feature_flags.py +86 -0
  31. opentrons/config/gripper_config.py +55 -0
  32. opentrons/config/reset.py +203 -0
  33. opentrons/config/robot_configs.py +187 -0
  34. opentrons/config/types.py +183 -0
  35. opentrons/drivers/__init__.py +0 -0
  36. opentrons/drivers/absorbance_reader/__init__.py +11 -0
  37. opentrons/drivers/absorbance_reader/abstract.py +72 -0
  38. opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
  39. opentrons/drivers/absorbance_reader/driver.py +81 -0
  40. opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
  41. opentrons/drivers/absorbance_reader/simulator.py +84 -0
  42. opentrons/drivers/asyncio/__init__.py +0 -0
  43. opentrons/drivers/asyncio/communication/__init__.py +22 -0
  44. opentrons/drivers/asyncio/communication/async_serial.py +187 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +557 -0
  47. opentrons/drivers/command_builder.py +102 -0
  48. opentrons/drivers/flex_stacker/__init__.py +13 -0
  49. opentrons/drivers/flex_stacker/abstract.py +214 -0
  50. opentrons/drivers/flex_stacker/driver.py +768 -0
  51. opentrons/drivers/flex_stacker/errors.py +68 -0
  52. opentrons/drivers/flex_stacker/simulator.py +309 -0
  53. opentrons/drivers/flex_stacker/types.py +367 -0
  54. opentrons/drivers/flex_stacker/utils.py +19 -0
  55. opentrons/drivers/heater_shaker/__init__.py +5 -0
  56. opentrons/drivers/heater_shaker/abstract.py +76 -0
  57. opentrons/drivers/heater_shaker/driver.py +204 -0
  58. opentrons/drivers/heater_shaker/simulator.py +94 -0
  59. opentrons/drivers/mag_deck/__init__.py +6 -0
  60. opentrons/drivers/mag_deck/abstract.py +44 -0
  61. opentrons/drivers/mag_deck/driver.py +208 -0
  62. opentrons/drivers/mag_deck/simulator.py +63 -0
  63. opentrons/drivers/rpi_drivers/__init__.py +33 -0
  64. opentrons/drivers/rpi_drivers/dev_types.py +94 -0
  65. opentrons/drivers/rpi_drivers/gpio.py +282 -0
  66. opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
  67. opentrons/drivers/rpi_drivers/interfaces.py +15 -0
  68. opentrons/drivers/rpi_drivers/types.py +364 -0
  69. opentrons/drivers/rpi_drivers/usb.py +102 -0
  70. opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
  71. opentrons/drivers/serial_communication.py +151 -0
  72. opentrons/drivers/smoothie_drivers/__init__.py +4 -0
  73. opentrons/drivers/smoothie_drivers/connection.py +51 -0
  74. opentrons/drivers/smoothie_drivers/constants.py +121 -0
  75. opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
  76. opentrons/drivers/smoothie_drivers/errors.py +49 -0
  77. opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
  78. opentrons/drivers/smoothie_drivers/simulator.py +99 -0
  79. opentrons/drivers/smoothie_drivers/types.py +16 -0
  80. opentrons/drivers/temp_deck/__init__.py +10 -0
  81. opentrons/drivers/temp_deck/abstract.py +54 -0
  82. opentrons/drivers/temp_deck/driver.py +197 -0
  83. opentrons/drivers/temp_deck/simulator.py +57 -0
  84. opentrons/drivers/thermocycler/__init__.py +12 -0
  85. opentrons/drivers/thermocycler/abstract.py +99 -0
  86. opentrons/drivers/thermocycler/driver.py +395 -0
  87. opentrons/drivers/thermocycler/simulator.py +126 -0
  88. opentrons/drivers/types.py +107 -0
  89. opentrons/drivers/utils.py +222 -0
  90. opentrons/execute.py +742 -0
  91. opentrons/hardware_control/__init__.py +65 -0
  92. opentrons/hardware_control/__main__.py +77 -0
  93. opentrons/hardware_control/adapters.py +98 -0
  94. opentrons/hardware_control/api.py +1347 -0
  95. opentrons/hardware_control/backends/__init__.py +7 -0
  96. opentrons/hardware_control/backends/controller.py +400 -0
  97. opentrons/hardware_control/backends/errors.py +9 -0
  98. opentrons/hardware_control/backends/estop_state.py +164 -0
  99. opentrons/hardware_control/backends/flex_protocol.py +497 -0
  100. opentrons/hardware_control/backends/ot3controller.py +1930 -0
  101. opentrons/hardware_control/backends/ot3simulator.py +900 -0
  102. opentrons/hardware_control/backends/ot3utils.py +664 -0
  103. opentrons/hardware_control/backends/simulator.py +442 -0
  104. opentrons/hardware_control/backends/status_bar_state.py +240 -0
  105. opentrons/hardware_control/backends/subsystem_manager.py +431 -0
  106. opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
  107. opentrons/hardware_control/backends/types.py +14 -0
  108. opentrons/hardware_control/constants.py +6 -0
  109. opentrons/hardware_control/dev_types.py +125 -0
  110. opentrons/hardware_control/emulation/__init__.py +0 -0
  111. opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
  112. opentrons/hardware_control/emulation/app.py +56 -0
  113. opentrons/hardware_control/emulation/connection_handler.py +38 -0
  114. opentrons/hardware_control/emulation/heater_shaker.py +150 -0
  115. opentrons/hardware_control/emulation/magdeck.py +60 -0
  116. opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
  117. opentrons/hardware_control/emulation/module_server/client.py +78 -0
  118. opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
  119. opentrons/hardware_control/emulation/module_server/models.py +31 -0
  120. opentrons/hardware_control/emulation/module_server/server.py +110 -0
  121. opentrons/hardware_control/emulation/parser.py +74 -0
  122. opentrons/hardware_control/emulation/proxy.py +241 -0
  123. opentrons/hardware_control/emulation/run_emulator.py +68 -0
  124. opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
  125. opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
  126. opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
  127. opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
  128. opentrons/hardware_control/emulation/settings.py +119 -0
  129. opentrons/hardware_control/emulation/simulations.py +133 -0
  130. opentrons/hardware_control/emulation/smoothie.py +192 -0
  131. opentrons/hardware_control/emulation/tempdeck.py +69 -0
  132. opentrons/hardware_control/emulation/thermocycler.py +128 -0
  133. opentrons/hardware_control/emulation/types.py +10 -0
  134. opentrons/hardware_control/emulation/util.py +38 -0
  135. opentrons/hardware_control/errors.py +43 -0
  136. opentrons/hardware_control/execution_manager.py +164 -0
  137. opentrons/hardware_control/instruments/__init__.py +5 -0
  138. opentrons/hardware_control/instruments/instrument_abc.py +39 -0
  139. opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
  140. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
  141. opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
  142. opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
  143. opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
  144. opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
  145. opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
  146. opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
  147. opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
  148. opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
  149. opentrons/hardware_control/module_control.py +332 -0
  150. opentrons/hardware_control/modules/__init__.py +69 -0
  151. opentrons/hardware_control/modules/absorbance_reader.py +373 -0
  152. opentrons/hardware_control/modules/errors.py +7 -0
  153. opentrons/hardware_control/modules/flex_stacker.py +948 -0
  154. opentrons/hardware_control/modules/heater_shaker.py +426 -0
  155. opentrons/hardware_control/modules/lid_temp_status.py +35 -0
  156. opentrons/hardware_control/modules/magdeck.py +233 -0
  157. opentrons/hardware_control/modules/mod_abc.py +245 -0
  158. opentrons/hardware_control/modules/module_calibration.py +93 -0
  159. opentrons/hardware_control/modules/plate_temp_status.py +61 -0
  160. opentrons/hardware_control/modules/tempdeck.py +299 -0
  161. opentrons/hardware_control/modules/thermocycler.py +731 -0
  162. opentrons/hardware_control/modules/types.py +417 -0
  163. opentrons/hardware_control/modules/update.py +255 -0
  164. opentrons/hardware_control/modules/utils.py +73 -0
  165. opentrons/hardware_control/motion_utilities.py +318 -0
  166. opentrons/hardware_control/nozzle_manager.py +422 -0
  167. opentrons/hardware_control/ot3_calibration.py +1171 -0
  168. opentrons/hardware_control/ot3api.py +3227 -0
  169. opentrons/hardware_control/pause_manager.py +31 -0
  170. opentrons/hardware_control/poller.py +112 -0
  171. opentrons/hardware_control/protocols/__init__.py +106 -0
  172. opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
  173. opentrons/hardware_control/protocols/calibratable.py +45 -0
  174. opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
  175. opentrons/hardware_control/protocols/configurable.py +48 -0
  176. opentrons/hardware_control/protocols/event_sourcer.py +18 -0
  177. opentrons/hardware_control/protocols/execution_controllable.py +33 -0
  178. opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
  179. opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
  180. opentrons/hardware_control/protocols/gripper_controller.py +55 -0
  181. opentrons/hardware_control/protocols/hardware_manager.py +51 -0
  182. opentrons/hardware_control/protocols/identifiable.py +16 -0
  183. opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
  184. opentrons/hardware_control/protocols/liquid_handler.py +266 -0
  185. opentrons/hardware_control/protocols/module_provider.py +16 -0
  186. opentrons/hardware_control/protocols/motion_controller.py +243 -0
  187. opentrons/hardware_control/protocols/position_estimator.py +45 -0
  188. opentrons/hardware_control/protocols/simulatable.py +10 -0
  189. opentrons/hardware_control/protocols/stoppable.py +9 -0
  190. opentrons/hardware_control/protocols/types.py +27 -0
  191. opentrons/hardware_control/robot_calibration.py +224 -0
  192. opentrons/hardware_control/scripts/README.md +28 -0
  193. opentrons/hardware_control/scripts/__init__.py +1 -0
  194. opentrons/hardware_control/scripts/gripper_control.py +208 -0
  195. opentrons/hardware_control/scripts/ot3gripper +7 -0
  196. opentrons/hardware_control/scripts/ot3repl +7 -0
  197. opentrons/hardware_control/scripts/repl.py +187 -0
  198. opentrons/hardware_control/scripts/tc_control.py +97 -0
  199. opentrons/hardware_control/scripts/update_module_fw.py +274 -0
  200. opentrons/hardware_control/simulator_setup.py +260 -0
  201. opentrons/hardware_control/thread_manager.py +431 -0
  202. opentrons/hardware_control/threaded_async_lock.py +97 -0
  203. opentrons/hardware_control/types.py +792 -0
  204. opentrons/hardware_control/util.py +234 -0
  205. opentrons/legacy_broker.py +53 -0
  206. opentrons/legacy_commands/__init__.py +1 -0
  207. opentrons/legacy_commands/commands.py +483 -0
  208. opentrons/legacy_commands/helpers.py +153 -0
  209. opentrons/legacy_commands/module_commands.py +276 -0
  210. opentrons/legacy_commands/protocol_commands.py +54 -0
  211. opentrons/legacy_commands/publisher.py +155 -0
  212. opentrons/legacy_commands/robot_commands.py +51 -0
  213. opentrons/legacy_commands/types.py +1186 -0
  214. opentrons/motion_planning/__init__.py +32 -0
  215. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  216. opentrons/motion_planning/deck_conflict.py +501 -0
  217. opentrons/motion_planning/errors.py +35 -0
  218. opentrons/motion_planning/types.py +42 -0
  219. opentrons/motion_planning/waypoints.py +218 -0
  220. opentrons/ordered_set.py +138 -0
  221. opentrons/protocol_api/__init__.py +105 -0
  222. opentrons/protocol_api/_liquid.py +157 -0
  223. opentrons/protocol_api/_liquid_properties.py +814 -0
  224. opentrons/protocol_api/_nozzle_layout.py +31 -0
  225. opentrons/protocol_api/_parameter_context.py +300 -0
  226. opentrons/protocol_api/_parameters.py +31 -0
  227. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  228. opentrons/protocol_api/_types.py +43 -0
  229. opentrons/protocol_api/config.py +23 -0
  230. opentrons/protocol_api/core/__init__.py +23 -0
  231. opentrons/protocol_api/core/common.py +33 -0
  232. opentrons/protocol_api/core/core_map.py +74 -0
  233. opentrons/protocol_api/core/engine/__init__.py +22 -0
  234. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  235. opentrons/protocol_api/core/engine/deck_conflict.py +400 -0
  236. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  237. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  238. opentrons/protocol_api/core/engine/labware.py +238 -0
  239. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  240. opentrons/protocol_api/core/engine/module_core.py +1027 -0
  241. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  242. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  243. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  244. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  245. opentrons/protocol_api/core/engine/robot.py +139 -0
  246. opentrons/protocol_api/core/engine/stringify.py +74 -0
  247. opentrons/protocol_api/core/engine/transfer_components_executor.py +1006 -0
  248. opentrons/protocol_api/core/engine/well.py +241 -0
  249. opentrons/protocol_api/core/instrument.py +459 -0
  250. opentrons/protocol_api/core/labware.py +151 -0
  251. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  252. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  253. opentrons/protocol_api/core/legacy/deck.py +369 -0
  254. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  255. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  256. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  257. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  258. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  259. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  260. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  261. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  262. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  263. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  265. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  266. opentrons/protocol_api/core/module.py +484 -0
  267. opentrons/protocol_api/core/protocol.py +311 -0
  268. opentrons/protocol_api/core/robot.py +51 -0
  269. opentrons/protocol_api/core/well.py +116 -0
  270. opentrons/protocol_api/core/well_grid.py +45 -0
  271. opentrons/protocol_api/create_protocol_context.py +177 -0
  272. opentrons/protocol_api/deck.py +223 -0
  273. opentrons/protocol_api/disposal_locations.py +244 -0
  274. opentrons/protocol_api/instrument_context.py +3272 -0
  275. opentrons/protocol_api/labware.py +1579 -0
  276. opentrons/protocol_api/module_contexts.py +1447 -0
  277. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  278. opentrons/protocol_api/protocol_context.py +1688 -0
  279. opentrons/protocol_api/robot_context.py +303 -0
  280. opentrons/protocol_api/validation.py +761 -0
  281. opentrons/protocol_engine/__init__.py +155 -0
  282. opentrons/protocol_engine/actions/__init__.py +65 -0
  283. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  284. opentrons/protocol_engine/actions/action_handler.py +13 -0
  285. opentrons/protocol_engine/actions/actions.py +302 -0
  286. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  287. opentrons/protocol_engine/clients/__init__.py +5 -0
  288. opentrons/protocol_engine/clients/sync_client.py +174 -0
  289. opentrons/protocol_engine/clients/transports.py +197 -0
  290. opentrons/protocol_engine/commands/__init__.py +757 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  296. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  297. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  298. opentrons/protocol_engine/commands/aspirate.py +244 -0
  299. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  300. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  301. opentrons/protocol_engine/commands/blow_out.py +146 -0
  302. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  303. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  306. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  307. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  308. opentrons/protocol_engine/commands/command.py +308 -0
  309. opentrons/protocol_engine/commands/command_unions.py +974 -0
  310. opentrons/protocol_engine/commands/comment.py +57 -0
  311. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  312. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  313. opentrons/protocol_engine/commands/custom.py +67 -0
  314. opentrons/protocol_engine/commands/dispense.py +194 -0
  315. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  316. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  317. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  318. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  319. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  320. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  321. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  322. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  323. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  324. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  325. opentrons/protocol_engine/commands/flex_stacker/store.py +339 -0
  326. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  327. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  328. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  329. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  330. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  331. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  333. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  334. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  336. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  337. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  338. opentrons/protocol_engine/commands/home.py +100 -0
  339. opentrons/protocol_engine/commands/identify_module.py +86 -0
  340. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  341. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  342. opentrons/protocol_engine/commands/load_labware.py +210 -0
  343. opentrons/protocol_engine/commands/load_lid.py +154 -0
  344. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  345. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  346. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  347. opentrons/protocol_engine/commands/load_module.py +223 -0
  348. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  349. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  350. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  351. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  352. opentrons/protocol_engine/commands/move_labware.py +546 -0
  353. opentrons/protocol_engine/commands/move_relative.py +102 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  355. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  356. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  357. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  358. opentrons/protocol_engine/commands/movement_common.py +338 -0
  359. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  360. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  361. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  362. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  363. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  364. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  365. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  366. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  367. opentrons/protocol_engine/commands/robot/common.py +18 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  369. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  370. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  371. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  372. opentrons/protocol_engine/commands/save_position.py +109 -0
  373. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  374. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  375. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  376. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  377. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  378. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  379. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  380. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  381. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  384. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  386. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  388. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  390. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  391. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  392. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  401. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  402. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  403. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  404. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  405. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  406. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  407. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  408. opentrons/protocol_engine/engine_support.py +28 -0
  409. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  410. opentrons/protocol_engine/errors/__init__.py +191 -0
  411. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  412. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  413. opentrons/protocol_engine/execution/__init__.py +50 -0
  414. opentrons/protocol_engine/execution/command_executor.py +216 -0
  415. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  416. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  417. opentrons/protocol_engine/execution/equipment.py +819 -0
  418. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  419. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  420. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  421. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  422. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  423. opentrons/protocol_engine/execution/movement.py +350 -0
  424. opentrons/protocol_engine/execution/pipetting.py +607 -0
  425. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  426. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  427. opentrons/protocol_engine/execution/run_control.py +33 -0
  428. opentrons/protocol_engine/execution/status_bar.py +34 -0
  429. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  430. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  431. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  432. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  433. opentrons/protocol_engine/notes/__init__.py +17 -0
  434. opentrons/protocol_engine/notes/notes.py +59 -0
  435. opentrons/protocol_engine/plugins.py +104 -0
  436. opentrons/protocol_engine/protocol_engine.py +683 -0
  437. opentrons/protocol_engine/resources/__init__.py +26 -0
  438. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  439. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  440. opentrons/protocol_engine/resources/file_provider.py +161 -0
  441. opentrons/protocol_engine/resources/fixture_validation.py +68 -0
  442. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  443. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  444. opentrons/protocol_engine/resources/model_utils.py +32 -0
  445. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  446. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  447. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  448. opentrons/protocol_engine/slot_standardization.py +128 -0
  449. opentrons/protocol_engine/state/__init__.py +1 -0
  450. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  451. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  452. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  453. opentrons/protocol_engine/state/_move_types.py +83 -0
  454. opentrons/protocol_engine/state/_well_math.py +193 -0
  455. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  456. opentrons/protocol_engine/state/command_history.py +309 -0
  457. opentrons/protocol_engine/state/commands.py +1164 -0
  458. opentrons/protocol_engine/state/config.py +39 -0
  459. opentrons/protocol_engine/state/files.py +57 -0
  460. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  461. opentrons/protocol_engine/state/geometry.py +2408 -0
  462. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  463. opentrons/protocol_engine/state/labware.py +1432 -0
  464. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  465. opentrons/protocol_engine/state/liquids.py +73 -0
  466. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  467. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  468. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  469. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  471. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  472. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  473. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  474. opentrons/protocol_engine/state/modules.py +1515 -0
  475. opentrons/protocol_engine/state/motion.py +373 -0
  476. opentrons/protocol_engine/state/pipettes.py +905 -0
  477. opentrons/protocol_engine/state/state.py +421 -0
  478. opentrons/protocol_engine/state/state_summary.py +36 -0
  479. opentrons/protocol_engine/state/tips.py +420 -0
  480. opentrons/protocol_engine/state/update_types.py +904 -0
  481. opentrons/protocol_engine/state/wells.py +290 -0
  482. opentrons/protocol_engine/types/__init__.py +310 -0
  483. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  484. opentrons/protocol_engine/types/command_annotations.py +53 -0
  485. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  486. opentrons/protocol_engine/types/execution.py +96 -0
  487. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  488. opentrons/protocol_engine/types/instrument.py +47 -0
  489. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  490. opentrons/protocol_engine/types/labware.py +131 -0
  491. opentrons/protocol_engine/types/labware_movement.py +22 -0
  492. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  493. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  494. opentrons/protocol_engine/types/liquid.py +40 -0
  495. opentrons/protocol_engine/types/liquid_class.py +59 -0
  496. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  497. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  498. opentrons/protocol_engine/types/location.py +194 -0
  499. opentrons/protocol_engine/types/module.py +310 -0
  500. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  501. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  502. opentrons/protocol_engine/types/tip.py +18 -0
  503. opentrons/protocol_engine/types/util.py +21 -0
  504. opentrons/protocol_engine/types/well_position.py +124 -0
  505. opentrons/protocol_reader/__init__.py +37 -0
  506. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  507. opentrons/protocol_reader/file_format_validator.py +152 -0
  508. opentrons/protocol_reader/file_hasher.py +27 -0
  509. opentrons/protocol_reader/file_identifier.py +284 -0
  510. opentrons/protocol_reader/file_reader_writer.py +90 -0
  511. opentrons/protocol_reader/input_file.py +16 -0
  512. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  513. opentrons/protocol_reader/protocol_reader.py +188 -0
  514. opentrons/protocol_reader/protocol_source.py +124 -0
  515. opentrons/protocol_reader/role_analyzer.py +86 -0
  516. opentrons/protocol_runner/__init__.py +26 -0
  517. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  518. opentrons/protocol_runner/json_file_reader.py +55 -0
  519. opentrons/protocol_runner/json_translator.py +314 -0
  520. opentrons/protocol_runner/legacy_command_mapper.py +852 -0
  521. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  522. opentrons/protocol_runner/protocol_runner.py +530 -0
  523. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  524. opentrons/protocol_runner/run_orchestrator.py +496 -0
  525. opentrons/protocol_runner/task_queue.py +95 -0
  526. opentrons/protocols/__init__.py +6 -0
  527. opentrons/protocols/advanced_control/__init__.py +0 -0
  528. opentrons/protocols/advanced_control/common.py +38 -0
  529. opentrons/protocols/advanced_control/mix.py +60 -0
  530. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  531. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  532. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  533. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  534. opentrons/protocols/api_support/__init__.py +0 -0
  535. opentrons/protocols/api_support/constants.py +8 -0
  536. opentrons/protocols/api_support/deck_type.py +110 -0
  537. opentrons/protocols/api_support/definitions.py +18 -0
  538. opentrons/protocols/api_support/instrument.py +151 -0
  539. opentrons/protocols/api_support/labware_like.py +233 -0
  540. opentrons/protocols/api_support/tip_tracker.py +175 -0
  541. opentrons/protocols/api_support/types.py +32 -0
  542. opentrons/protocols/api_support/util.py +403 -0
  543. opentrons/protocols/bundle.py +89 -0
  544. opentrons/protocols/duration/__init__.py +4 -0
  545. opentrons/protocols/duration/errors.py +5 -0
  546. opentrons/protocols/duration/estimator.py +628 -0
  547. opentrons/protocols/execution/__init__.py +0 -0
  548. opentrons/protocols/execution/dev_types.py +181 -0
  549. opentrons/protocols/execution/errors.py +40 -0
  550. opentrons/protocols/execution/execute.py +84 -0
  551. opentrons/protocols/execution/execute_json_v3.py +275 -0
  552. opentrons/protocols/execution/execute_json_v4.py +359 -0
  553. opentrons/protocols/execution/execute_json_v5.py +28 -0
  554. opentrons/protocols/execution/execute_python.py +169 -0
  555. opentrons/protocols/execution/json_dispatchers.py +87 -0
  556. opentrons/protocols/execution/types.py +7 -0
  557. opentrons/protocols/geometry/__init__.py +0 -0
  558. opentrons/protocols/geometry/planning.py +297 -0
  559. opentrons/protocols/labware.py +312 -0
  560. opentrons/protocols/models/__init__.py +0 -0
  561. opentrons/protocols/models/json_protocol.py +679 -0
  562. opentrons/protocols/parameters/__init__.py +0 -0
  563. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  564. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  565. opentrons/protocols/parameters/exceptions.py +34 -0
  566. opentrons/protocols/parameters/parameter_definition.py +272 -0
  567. opentrons/protocols/parameters/types.py +17 -0
  568. opentrons/protocols/parameters/validation.py +267 -0
  569. opentrons/protocols/parse.py +671 -0
  570. opentrons/protocols/types.py +159 -0
  571. opentrons/py.typed +0 -0
  572. opentrons/resources/scripts/lpc21isp +0 -0
  573. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  574. opentrons/simulate.py +1065 -0
  575. opentrons/system/__init__.py +6 -0
  576. opentrons/system/camera.py +51 -0
  577. opentrons/system/log_control.py +59 -0
  578. opentrons/system/nmcli.py +856 -0
  579. opentrons/system/resin.py +24 -0
  580. opentrons/system/smoothie_update.py +15 -0
  581. opentrons/system/wifi.py +204 -0
  582. opentrons/tools/__init__.py +0 -0
  583. opentrons/tools/args_handler.py +22 -0
  584. opentrons/tools/write_pipette_memory.py +157 -0
  585. opentrons/types.py +618 -0
  586. opentrons/util/__init__.py +1 -0
  587. opentrons/util/async_helpers.py +166 -0
  588. opentrons/util/broker.py +84 -0
  589. opentrons/util/change_notifier.py +47 -0
  590. opentrons/util/entrypoint_util.py +278 -0
  591. opentrons/util/get_union_elements.py +26 -0
  592. opentrons/util/helpers.py +6 -0
  593. opentrons/util/linal.py +178 -0
  594. opentrons/util/logging_config.py +265 -0
  595. opentrons/util/logging_queue_handler.py +61 -0
  596. opentrons/util/performance_helpers.py +157 -0
  597. opentrons-8.6.0.dist-info/METADATA +37 -0
  598. opentrons-8.6.0.dist-info/RECORD +601 -0
  599. opentrons-8.6.0.dist-info/WHEEL +4 -0
  600. opentrons-8.6.0.dist-info/entry_points.txt +3 -0
  601. opentrons-8.6.0.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,32 @@
1
+ """Motion planning module."""
2
+
3
+ from .waypoints import (
4
+ DEFAULT_GENERAL_ARC_Z_MARGIN,
5
+ DEFAULT_IN_LABWARE_ARC_Z_MARGIN,
6
+ MINIMUM_Z_MARGIN,
7
+ get_waypoints,
8
+ get_gripper_labware_movement_waypoints,
9
+ get_gripper_labware_placement_waypoints,
10
+ )
11
+
12
+ from .types import Waypoint, MoveType
13
+
14
+ from .errors import (
15
+ MotionPlanningError,
16
+ DestinationOutOfBoundsError,
17
+ ArcOutOfBoundsError,
18
+ )
19
+
20
+ __all__ = [
21
+ "DEFAULT_GENERAL_ARC_Z_MARGIN",
22
+ "DEFAULT_IN_LABWARE_ARC_Z_MARGIN",
23
+ "MINIMUM_Z_MARGIN",
24
+ "Waypoint",
25
+ "MoveType",
26
+ "MotionPlanningError",
27
+ "DestinationOutOfBoundsError",
28
+ "ArcOutOfBoundsError",
29
+ "get_waypoints",
30
+ "get_gripper_labware_movement_waypoints",
31
+ "get_gripper_labware_placement_waypoints",
32
+ ]
@@ -0,0 +1,168 @@
1
+ """Getters for specific adjacent slots."""
2
+ from dataclasses import dataclass
3
+ from typing import Optional, List, Dict, Union
4
+
5
+ from opentrons_shared_data.robot.types import RobotType
6
+
7
+ from opentrons.types import DeckSlotName, StagingSlotName
8
+
9
+
10
+ def get_north_slot(slot: int) -> Optional[int]:
11
+ """Get slot north of the given slot."""
12
+ if slot in [10, 11, 12]:
13
+ return None
14
+ else:
15
+ return slot + 3
16
+
17
+
18
+ def get_south_slot(slot: int) -> Optional[int]:
19
+ """Get slot south of the given slot."""
20
+ if slot in [1, 2, 3]:
21
+ return None
22
+ else:
23
+ return slot - 3
24
+
25
+
26
+ def get_east_slot(slot: int) -> Optional[int]:
27
+ """Get slot east of the given slot."""
28
+ if slot in [3, 6, 9, 12]:
29
+ return None
30
+ else:
31
+ return slot + 1
32
+
33
+
34
+ def get_west_slot(slot: int) -> Optional[int]:
35
+ """Get slot west of the given slot."""
36
+ if slot in [1, 4, 7, 10]:
37
+ return None
38
+ else:
39
+ return slot - 1
40
+
41
+
42
+ def get_north_west_slot(slot: int) -> Optional[int]:
43
+ """Get the slot that's north-west of the given slot."""
44
+ if slot in [1, 4, 7, 10, 11, 12]:
45
+ return None
46
+ else:
47
+ north_slot = get_north_slot(slot)
48
+ return north_slot - 1 if north_slot else None
49
+
50
+
51
+ def get_north_east_slot(slot: int) -> Optional[int]:
52
+ """Get the slot that's north-east of the given slot."""
53
+ if slot in [3, 6, 9, 10, 11, 12]:
54
+ return None
55
+ else:
56
+ north_slot = get_north_slot(slot)
57
+ return north_slot + 1 if north_slot else None
58
+
59
+
60
+ def get_south_west_slot(slot: int) -> Optional[int]:
61
+ """Get the slot that's south-west of the given slot."""
62
+ if slot in [1, 2, 3, 4, 7, 10]:
63
+ return None
64
+ else:
65
+ south_slot = get_south_slot(slot)
66
+ return south_slot - 1 if south_slot else None
67
+
68
+
69
+ def get_south_east_slot(slot: int) -> Optional[int]:
70
+ """Get the slot that's south-east of the given slot."""
71
+ if slot in [1, 2, 3, 6, 9, 12]:
72
+ return None
73
+ else:
74
+ south_slot = get_south_slot(slot)
75
+ return south_slot + 1 if south_slot else None
76
+
77
+
78
+ @dataclass
79
+ class _MixedTypeSlots:
80
+ regular_slots: List[DeckSlotName]
81
+ staging_slots: List[StagingSlotName]
82
+
83
+
84
+ def get_surrounding_slots(slot: int, robot_type: RobotType) -> _MixedTypeSlots:
85
+ """Get all the surrounding slots, i.e., adjacent slots as well as corner slots."""
86
+ corner_slots: List[Union[int, None]] = [
87
+ get_north_east_slot(slot),
88
+ get_north_west_slot(slot),
89
+ get_south_east_slot(slot),
90
+ get_south_west_slot(slot),
91
+ ]
92
+
93
+ surrounding_regular_slots_int = get_adjacent_slots(slot) + [
94
+ maybe_slot for maybe_slot in corner_slots if maybe_slot is not None
95
+ ]
96
+ surrounding_regular_slots = [
97
+ DeckSlotName.from_primitive(slot_int).to_equivalent_for_robot_type(robot_type)
98
+ for slot_int in surrounding_regular_slots_int
99
+ ]
100
+ surrounding_staging_slots = _SURROUNDING_STAGING_SLOTS_MAP.get(
101
+ DeckSlotName.from_primitive(slot).to_equivalent_for_robot_type(robot_type), []
102
+ )
103
+ return _MixedTypeSlots(
104
+ regular_slots=surrounding_regular_slots, staging_slots=surrounding_staging_slots
105
+ )
106
+
107
+
108
+ _WEST_OF_STAGING_SLOT_MAP: Dict[StagingSlotName, DeckSlotName] = {
109
+ StagingSlotName.SLOT_A4: DeckSlotName.SLOT_A3,
110
+ StagingSlotName.SLOT_B4: DeckSlotName.SLOT_B3,
111
+ StagingSlotName.SLOT_C4: DeckSlotName.SLOT_C3,
112
+ StagingSlotName.SLOT_D4: DeckSlotName.SLOT_D3,
113
+ }
114
+
115
+ _EAST_OF_FLEX_COLUMN_3_MAP: Dict[DeckSlotName, StagingSlotName] = {
116
+ deck_slot: staging_slot
117
+ for staging_slot, deck_slot in _WEST_OF_STAGING_SLOT_MAP.items()
118
+ }
119
+
120
+
121
+ _SURROUNDING_STAGING_SLOTS_MAP: Dict[DeckSlotName, List[StagingSlotName]] = {
122
+ DeckSlotName.SLOT_D3: [StagingSlotName.SLOT_C4, StagingSlotName.SLOT_D4],
123
+ DeckSlotName.SLOT_C3: [
124
+ StagingSlotName.SLOT_B4,
125
+ StagingSlotName.SLOT_C4,
126
+ StagingSlotName.SLOT_D4,
127
+ ],
128
+ DeckSlotName.SLOT_B3: [
129
+ StagingSlotName.SLOT_A4,
130
+ StagingSlotName.SLOT_B4,
131
+ StagingSlotName.SLOT_C4,
132
+ ],
133
+ DeckSlotName.SLOT_A3: [StagingSlotName.SLOT_A4, StagingSlotName.SLOT_B4],
134
+ }
135
+
136
+
137
+ def get_west_of_staging_slot(staging_slot: StagingSlotName) -> DeckSlotName:
138
+ """Get slot west of a staging slot."""
139
+ return _WEST_OF_STAGING_SLOT_MAP[staging_slot]
140
+
141
+
142
+ def get_adjacent_staging_slot(deck_slot: DeckSlotName) -> Optional[StagingSlotName]:
143
+ """Get the adjacent staging slot if the deck slot is in the third column."""
144
+ return _EAST_OF_FLEX_COLUMN_3_MAP.get(deck_slot)
145
+
146
+
147
+ def get_surrounding_staging_slots(deck_slot: DeckSlotName) -> List[StagingSlotName]:
148
+ """Get the staging slots surrounding the given deck slot."""
149
+ return _SURROUNDING_STAGING_SLOTS_MAP.get(deck_slot, [])
150
+
151
+
152
+ def get_east_west_slots(slot: int) -> List[int]:
153
+ """Get slots east & west of the given slot."""
154
+ east = get_east_slot(slot)
155
+ west = get_west_slot(slot)
156
+ return [maybe_slot for maybe_slot in [east, west] if maybe_slot is not None]
157
+
158
+
159
+ def get_north_south_slots(slot: int) -> List[int]:
160
+ """Get slots north & south of the given slot."""
161
+ north = get_north_slot(slot)
162
+ south = get_south_slot(slot)
163
+ return [maybe_slot for maybe_slot in [north, south] if maybe_slot is not None]
164
+
165
+
166
+ def get_adjacent_slots(slot: int) -> List[int]:
167
+ """Get slots on the east, west, north and south of the given slot."""
168
+ return get_east_west_slots(slot) + get_north_south_slots(slot)
@@ -0,0 +1,501 @@
1
+ """Check a deck layout for conflicts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import List, Mapping, NamedTuple, Optional, Set, Union
7
+ from typing_extensions import Final
8
+
9
+ from opentrons_shared_data.labware.types import LabwareUri
10
+ from opentrons_shared_data.robot.types import RobotType
11
+ from opentrons.motion_planning.adjacent_slots_getters import (
12
+ get_east_west_slots,
13
+ get_south_slot,
14
+ get_adjacent_slots,
15
+ get_adjacent_staging_slot,
16
+ )
17
+
18
+ from opentrons.types import DeckSlotName, StagingSlotName
19
+
20
+ _FIXED_TRASH_SLOT: Final[Set[DeckSlotName]] = {
21
+ DeckSlotName.FIXED_TRASH,
22
+ DeckSlotName.SLOT_A3,
23
+ }
24
+
25
+
26
+ # The maximum height allowed for items adjacent to a Heater-Shaker in the x-direction.
27
+ # This value selected to avoid interference with the Heater-Shaker's labware latch.
28
+ # For background, see: https://github.com/Opentrons/opentrons/issues/10316
29
+ #
30
+ # TODO(mc, 2022-06-16): move this constant to the module definition
31
+ HS_MAX_X_ADJACENT_ITEM_HEIGHT = 53.0
32
+
33
+
34
+ # URIs of labware that are allowed to exceed HS_MAX_X_ADJACENT_ITEM_HEIGHT.
35
+ # These labware do not take up the full width of the slot
36
+ # in the area that would interfere with the labware latch.
37
+ # For background, see: https://github.com/Opentrons/opentrons/issues/10316
38
+ #
39
+ # TODO(mc, 2022-06-16): move this constant to the module definition
40
+ HS_ALLOWED_ADJACENT_TALL_LABWARE = [
41
+ LabwareUri("opentrons/opentrons_96_filtertiprack_10ul/1"),
42
+ LabwareUri("opentrons/opentrons_96_filtertiprack_200ul/1"),
43
+ LabwareUri("opentrons/opentrons_96_filtertiprack_20ul/1"),
44
+ LabwareUri("opentrons/opentrons_96_tiprack_10ul/1"),
45
+ LabwareUri("opentrons/opentrons_96_tiprack_20ul/1"),
46
+ LabwareUri("opentrons/opentrons_96_tiprack_300ul/1"),
47
+ ]
48
+
49
+
50
+ @dataclass
51
+ class Labware:
52
+ """A normal labware that directly occupies a slot.
53
+
54
+ Do not use this to represent a labware that's loaded atop a module.
55
+ Use one of the module types, instead.
56
+ """
57
+
58
+ name_for_errors: str
59
+ highest_z: float
60
+ uri: LabwareUri
61
+ is_fixed_trash: bool
62
+
63
+
64
+ @dataclass
65
+ class TrashBin:
66
+ """A non-labware trash bin (loaded via api level 2.16 and above)."""
67
+
68
+ name_for_errors: str
69
+ highest_z: float
70
+
71
+
72
+ @dataclass
73
+ class _Module:
74
+ name_for_errors: str
75
+ highest_z_including_labware: float
76
+
77
+
78
+ @dataclass
79
+ class HeaterShakerModule(_Module):
80
+ """A Heater-Shaker module."""
81
+
82
+
83
+ @dataclass
84
+ class MagneticBlockModule(_Module):
85
+ """A Magnetic Block module."""
86
+
87
+
88
+ @dataclass
89
+ class ThermocyclerModule(_Module):
90
+ """A Thermocycler module."""
91
+
92
+ is_semi_configuration: bool
93
+ """Whether this Thermocycler is loaded in its "semi" configuration.
94
+
95
+ In this configuration, it's offset to the left, so it takes up fewer deck slots.
96
+ """
97
+
98
+
99
+ @dataclass
100
+ class OtherModule(_Module):
101
+ """A module that's not a Heater-Shaker or Thermocycler or stacker."""
102
+
103
+
104
+ @dataclass
105
+ class FlexStackerModule(_Module):
106
+ """A stacker where nothing else is known to be in the "location" in column 3 that it lives."""
107
+
108
+
109
+ @dataclass
110
+ class FlexStackerModuleKindaButSomethingElseReally(_Module):
111
+ """A stacker where something else is also in the "location" in column 3 that it lives."""
112
+
113
+ original_item: "DeckItem"
114
+
115
+
116
+ DeckItem = Union[
117
+ Labware,
118
+ HeaterShakerModule,
119
+ MagneticBlockModule,
120
+ ThermocyclerModule,
121
+ OtherModule,
122
+ TrashBin,
123
+ FlexStackerModule,
124
+ FlexStackerModuleKindaButSomethingElseReally,
125
+ ]
126
+
127
+
128
+ class _NothingAllowed(NamedTuple):
129
+ """Nothing is allowed in this slot."""
130
+
131
+ location: Union[DeckSlotName, StagingSlotName]
132
+ source_item: DeckItem
133
+ source_location: Union[DeckSlotName, StagingSlotName]
134
+
135
+ def is_allowed(self, item: DeckItem) -> bool:
136
+ return False
137
+
138
+
139
+ class _NothingButStackerAllowed(NamedTuple):
140
+ """Nothing (in the Odyssean sense) is allowed in this slot."""
141
+
142
+ location: Union[DeckSlotName, StagingSlotName]
143
+ source_item: DeckItem
144
+ source_location: Union[DeckSlotName, StagingSlotName]
145
+
146
+ def is_allowed(self, item: DeckItem) -> bool:
147
+ if isinstance(item, FlexStackerModule):
148
+ return True
149
+ return False
150
+
151
+
152
+ class _MaxHeight(NamedTuple):
153
+ """Nothing over a certain height is allowed in this slot."""
154
+
155
+ location: DeckSlotName
156
+ source_item: DeckItem
157
+ source_location: DeckSlotName
158
+ max_height: float
159
+ allowed_labware: List[LabwareUri]
160
+
161
+ def is_allowed(self, item: DeckItem) -> bool:
162
+ if isinstance(item, Labware):
163
+ if item.uri in self.allowed_labware:
164
+ return True
165
+ else:
166
+ return item.highest_z < self.max_height
167
+ elif isinstance(item, _Module):
168
+ return item.highest_z_including_labware < self.max_height
169
+ elif isinstance(item, TrashBin):
170
+ return item.highest_z < self.max_height
171
+
172
+
173
+ class _NoModule(NamedTuple):
174
+ """No module of any kind is allowed in this slot."""
175
+
176
+ location: DeckSlotName
177
+ source_item: DeckItem
178
+ source_location: DeckSlotName
179
+
180
+ def is_allowed(self, item: DeckItem) -> bool:
181
+ return not isinstance(item, _Module)
182
+
183
+
184
+ class _NoHeaterShakerModule(NamedTuple):
185
+ """No Heater-Shaker module is allowed in this slot."""
186
+
187
+ location: DeckSlotName
188
+ source_item: DeckItem
189
+ source_location: DeckSlotName
190
+
191
+ def is_allowed(self, item: DeckItem) -> bool:
192
+ return not isinstance(item, HeaterShakerModule)
193
+
194
+
195
+ _DeckRestriction = Union[
196
+ _NothingAllowed,
197
+ _MaxHeight,
198
+ _NoModule,
199
+ _NoHeaterShakerModule,
200
+ _NothingButStackerAllowed,
201
+ ]
202
+ """A restriction on what is allowed in a given slot."""
203
+
204
+
205
+ class DeckConflictError(ValueError):
206
+ """Adding an item to the deck would cause a conflict."""
207
+
208
+
209
+ # TODO(mm, 2023-02-16): Taking a single int as the deck location doesn't make sense for
210
+ # things that don't fit into a single deck slot, like the Thermocycler.
211
+ # Refactor this interface to take a more symbolic location.
212
+ def check(
213
+ existing_items: Mapping[Union[DeckSlotName, StagingSlotName], DeckItem],
214
+ new_item: DeckItem,
215
+ new_location: Union[DeckSlotName, StagingSlotName],
216
+ robot_type: RobotType,
217
+ ) -> None:
218
+ """Check a deck layout for conflicts.
219
+
220
+ Args:
221
+ existing_items: Existing items on the deck, assumed to be valid.
222
+ new_item: New item to add to the deck.
223
+ new_location: Location where the new item will be added.
224
+ robot_type: The type of the robot to choose the restriction rules.
225
+
226
+ Raises:
227
+ DeckConflictError: Adding this item should not be allowed.
228
+ """
229
+ restrictions: List[_DeckRestriction] = []
230
+ # build restrictions driven by existing items
231
+ for location, item in existing_items.items():
232
+ restrictions += _create_restrictions(
233
+ item=item, location=location, robot_type=robot_type
234
+ )
235
+
236
+ # check new item against existing restrictions
237
+ for r in restrictions:
238
+ if r.location == new_location and not r.is_allowed(new_item):
239
+ raise DeckConflictError(
240
+ _create_deck_conflict_error_message(restriction=r, new_item=new_item)
241
+ )
242
+
243
+ # check new restrictions required by new item
244
+ # do not interfere with existing items
245
+ new_restrictions = _create_restrictions(
246
+ item=new_item, location=new_location, robot_type=robot_type
247
+ )
248
+
249
+ for r in new_restrictions:
250
+ existing_item = existing_items.get(r.location)
251
+ if existing_item is not None and not r.is_allowed(existing_item):
252
+ raise DeckConflictError(
253
+ _create_deck_conflict_error_message(
254
+ restriction=r,
255
+ existing_item=existing_item,
256
+ )
257
+ )
258
+
259
+
260
+ def _create_ot2_restrictions( # noqa: C901
261
+ item: DeckItem, location: Union[DeckSlotName, StagingSlotName]
262
+ ) -> List[_DeckRestriction]:
263
+ restrictions: List[_DeckRestriction] = []
264
+ if isinstance(location, StagingSlotName):
265
+ raise DeckConflictError(f"OT-2 does not support staging slots ({location.id}).")
266
+
267
+ if location not in _FIXED_TRASH_SLOT:
268
+ # Disallow a different item from overlapping this item in this deck slot.
269
+ restrictions.append(
270
+ _NothingAllowed(
271
+ location=location,
272
+ source_item=item,
273
+ source_location=location,
274
+ )
275
+ )
276
+
277
+ if _is_ot2_fixed_trash(item):
278
+ # A Heater-Shaker can't safely be placed just south of the fixed trash,
279
+ # because the fixed trash blocks access to the screw that locks the
280
+ # Heater-Shaker onto the deck.
281
+ location_south_of_fixed_trash = get_south_slot(location.as_int())
282
+ if location_south_of_fixed_trash is not None:
283
+ restrictions.append(
284
+ _NoHeaterShakerModule(
285
+ location=DeckSlotName.from_primitive(location_south_of_fixed_trash),
286
+ source_item=item,
287
+ source_location=location,
288
+ )
289
+ )
290
+
291
+ if isinstance(item, ThermocyclerModule):
292
+ for covered_location in _ot2_slots_covered_by_thermocycler(item):
293
+ restrictions.append(
294
+ _NothingAllowed(
295
+ location=covered_location,
296
+ source_item=item,
297
+ source_location=location,
298
+ )
299
+ )
300
+
301
+ if isinstance(item, HeaterShakerModule):
302
+ for hs_covered_location in get_adjacent_slots(location.as_int()):
303
+ restrictions.append(
304
+ _NoModule(
305
+ location=DeckSlotName.from_primitive(hs_covered_location),
306
+ source_item=item,
307
+ source_location=location,
308
+ )
309
+ )
310
+
311
+ for hs_covered_location in get_east_west_slots(location.as_int()):
312
+ restrictions.append(
313
+ _MaxHeight(
314
+ location=DeckSlotName.from_primitive(hs_covered_location),
315
+ source_item=item,
316
+ source_location=location,
317
+ max_height=HS_MAX_X_ADJACENT_ITEM_HEIGHT,
318
+ allowed_labware=HS_ALLOWED_ADJACENT_TALL_LABWARE,
319
+ )
320
+ )
321
+
322
+ return restrictions
323
+
324
+
325
+ def _create_flex_restrictions( # noqa: C901
326
+ item: DeckItem, location: Union[DeckSlotName, StagingSlotName]
327
+ ) -> List[_DeckRestriction]:
328
+ restrictions: List[_DeckRestriction] = []
329
+
330
+ if isinstance(item, (HeaterShakerModule, OtherModule)):
331
+ if isinstance(location, StagingSlotName):
332
+ raise DeckConflictError(
333
+ "Cannot have a module loaded on a staging area slot."
334
+ )
335
+ adjacent_staging_slot = get_adjacent_staging_slot(location)
336
+ if adjacent_staging_slot is not None:
337
+ # You can't have anything on a staging area slot next to a heater-shaker or
338
+ # temperature module because the module caddy physically blocks you from having
339
+ # that staging area slot installed in the first place.
340
+ restrictions.append(
341
+ _NothingAllowed(
342
+ location=adjacent_staging_slot,
343
+ source_item=item,
344
+ source_location=location,
345
+ )
346
+ )
347
+ restrictions.append(
348
+ _NothingAllowed(
349
+ location=location,
350
+ source_item=item,
351
+ source_location=location,
352
+ )
353
+ )
354
+ elif isinstance(item, FlexStackerModule):
355
+ if location not in _flex_slots_allowing_stacker():
356
+ raise DeckConflictError("Cannot place a Flex Stacker outside of column 3.")
357
+ # this is a typing assertion; the check above guarantees this is true
358
+ assert isinstance(location, DeckSlotName)
359
+ adjacent_staging_slot = get_adjacent_staging_slot(location)
360
+ # this is a typing assertion; the check above guarantees this isn't none
361
+ assert adjacent_staging_slot is not None
362
+ # nothing goes in the staging slot in the row the stacker is in, because the stacker is in the
363
+ # way (different from blocking you because of the design of the caddy).
364
+ restrictions.append(
365
+ _NothingAllowed(
366
+ location=adjacent_staging_slot,
367
+ source_item=item,
368
+ source_location=location,
369
+ )
370
+ )
371
+ # note that the stacker does NOT block use of the "slot" that it is "loaded in" because
372
+ # it is actually loaded in that cutout, and you can put a deck slot on top just fine
373
+ elif isinstance(item, FlexStackerModuleKindaButSomethingElseReally):
374
+ if location not in _flex_slots_allowing_stacker():
375
+ raise DeckConflictError("Cannot place a Flex Stacker outside of column 3.")
376
+ # this is a typing assertion; the check above guarantees this is true
377
+ assert isinstance(location, DeckSlotName)
378
+ adjacent_staging_slot = get_adjacent_staging_slot(location)
379
+ assert adjacent_staging_slot is not None
380
+ # nothing goes in the staging slot in the row the stacker is in, because the stacker is in the
381
+ # way (different from blocking you because of the design of the caddy).
382
+ restrictions.append(
383
+ _NothingAllowed(
384
+ location=adjacent_staging_slot,
385
+ source_item=item,
386
+ source_location=location,
387
+ )
388
+ )
389
+ # while the stacker on its own doesn't block use of the "slot" that it is "loaded in",
390
+ # the kind of "flex stacker" that actually means "you loaded a labware in column 3 where a
391
+ # stacker is sort of also "loaded" in column 3" does
392
+ restrictions.append(
393
+ _NothingAllowed(
394
+ location=location,
395
+ source_item=item.original_item,
396
+ source_location=location,
397
+ )
398
+ )
399
+
400
+ elif isinstance(item, ThermocyclerModule):
401
+ for covered_location in _flex_slots_covered_by_thermocycler():
402
+ restrictions.append(
403
+ _NothingAllowed(
404
+ location=covered_location,
405
+ source_item=item,
406
+ source_location=location,
407
+ )
408
+ )
409
+ restrictions.append(
410
+ _NothingAllowed(
411
+ location=location,
412
+ source_item=item,
413
+ source_location=location,
414
+ )
415
+ )
416
+ elif location in _flex_slots_allowing_stacker():
417
+ restrictions.append(
418
+ _NothingButStackerAllowed(
419
+ location=location,
420
+ source_item=item,
421
+ source_location=location,
422
+ )
423
+ )
424
+ else:
425
+ restrictions.append(
426
+ _NothingAllowed(
427
+ location=location, source_item=item, source_location=location
428
+ )
429
+ )
430
+
431
+ return restrictions
432
+
433
+
434
+ def _create_restrictions(
435
+ item: DeckItem, location: Union[DeckSlotName, StagingSlotName], robot_type: str
436
+ ) -> List[_DeckRestriction]:
437
+
438
+ if robot_type == "OT-2 Standard":
439
+ return _create_ot2_restrictions(item, location)
440
+ else:
441
+ return _create_flex_restrictions(item, location)
442
+
443
+
444
+ def _create_deck_conflict_error_message(
445
+ restriction: _DeckRestriction,
446
+ new_item: Optional[DeckItem] = None,
447
+ existing_item: Optional[DeckItem] = None,
448
+ ) -> str:
449
+ assert (
450
+ new_item is not None or existing_item is not None
451
+ ), "Conflict error expects either new_item or existing_item"
452
+
453
+ if new_item is not None:
454
+ message = (
455
+ f"{restriction.source_item.name_for_errors}"
456
+ f" in slot {restriction.source_location}"
457
+ f" prevents {new_item.name_for_errors}"
458
+ f" from using slot {restriction.location}."
459
+ )
460
+
461
+ elif existing_item is not None:
462
+ message = (
463
+ f"{existing_item.name_for_errors} in slot {restriction.location}"
464
+ f" prevents {restriction.source_item.name_for_errors}"
465
+ f" from using slot {restriction.source_location}."
466
+ )
467
+
468
+ return message
469
+
470
+
471
+ def _ot2_slots_covered_by_thermocycler(
472
+ thermocycler: ThermocyclerModule,
473
+ ) -> Set[DeckSlotName]:
474
+ if thermocycler.is_semi_configuration:
475
+ return {DeckSlotName.SLOT_7, DeckSlotName.SLOT_10}
476
+ else:
477
+ return {
478
+ DeckSlotName.SLOT_7,
479
+ DeckSlotName.SLOT_10,
480
+ DeckSlotName.SLOT_8,
481
+ DeckSlotName.SLOT_11,
482
+ }
483
+
484
+
485
+ def _flex_slots_covered_by_thermocycler() -> Set[DeckSlotName]:
486
+ return {DeckSlotName.SLOT_B1, DeckSlotName.SLOT_A1}
487
+
488
+
489
+ def _flex_slots_allowing_stacker() -> Set[DeckSlotName]:
490
+ return {
491
+ DeckSlotName.SLOT_A3,
492
+ DeckSlotName.SLOT_B3,
493
+ DeckSlotName.SLOT_C3,
494
+ DeckSlotName.SLOT_D3,
495
+ }
496
+
497
+
498
+ def _is_ot2_fixed_trash(item: DeckItem) -> bool:
499
+ return (isinstance(item, Labware) and item.is_fixed_trash) or isinstance(
500
+ item, TrashBin
501
+ )