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,20 @@
1
+ """Mappings between API versions and overlap versions."""
2
+ from functools import lru_cache
3
+ from typing_extensions import Final
4
+ from opentrons.protocols.api_support.types import APIVersion
5
+
6
+ _OVERLAP_VERSION_MAP: Final = {
7
+ APIVersion(2, 0): "v0",
8
+ APIVersion(2, 19): "v1",
9
+ APIVersion(2, 20): "v3",
10
+ }
11
+
12
+
13
+ @lru_cache(1)
14
+ def overlap_for_api_version(api_version: APIVersion) -> str:
15
+ """Get the overlap version for a specific API version."""
16
+ defined = list(reversed(sorted(_OVERLAP_VERSION_MAP.keys())))
17
+ for version in defined:
18
+ if version <= api_version:
19
+ return _OVERLAP_VERSION_MAP[version]
20
+ return _OVERLAP_VERSION_MAP[APIVersion(2, 0)]
@@ -0,0 +1,358 @@
1
+ """A Protocol-Engine-friendly wrapper for opentrons.motion_planning.deck_conflict."""
2
+ from __future__ import annotations
3
+ import logging
4
+ from typing import (
5
+ Optional,
6
+ Tuple,
7
+ Union,
8
+ List,
9
+ )
10
+
11
+ from opentrons_shared_data.errors.exceptions import MotionPlanningFailureError
12
+ from opentrons.protocol_engine.errors import LocationIsStagingSlotError
13
+ from opentrons_shared_data.module import FLEX_TC_LID_COLLISION_ZONE
14
+
15
+ from opentrons.hardware_control import CriticalPoint
16
+ from opentrons.motion_planning import adjacent_slots_getters
17
+
18
+ from opentrons.protocol_engine import (
19
+ StateView,
20
+ DeckSlotLocation,
21
+ OnLabwareLocation,
22
+ DropTipWellLocation,
23
+ )
24
+ from opentrons.protocol_engine.types import StagingSlotLocation, WellLocationType
25
+ from opentrons.types import DeckSlotName, StagingSlotName, Point
26
+ from . import point_calculations
27
+
28
+
29
+ class PartialTipMovementNotAllowedError(MotionPlanningFailureError):
30
+ """Error raised when trying to perform a partial tip movement to an illegal location."""
31
+
32
+ def __init__(self, message: str) -> None:
33
+ super().__init__(
34
+ message=message,
35
+ )
36
+
37
+
38
+ class UnsuitableTiprackForPipetteMotion(MotionPlanningFailureError):
39
+ """Error raised when trying to perform a pipette movement to a tip rack, based on adapter status."""
40
+
41
+ def __init__(self, message: str) -> None:
42
+ super().__init__(
43
+ message=message,
44
+ )
45
+
46
+
47
+ _log = logging.getLogger(__name__)
48
+
49
+ _FLEX_TC_LID_BACK_LEFT_PT = Point(
50
+ x=FLEX_TC_LID_COLLISION_ZONE["back_left"]["x"],
51
+ y=FLEX_TC_LID_COLLISION_ZONE["back_left"]["y"],
52
+ z=FLEX_TC_LID_COLLISION_ZONE["back_left"]["z"],
53
+ )
54
+
55
+ _FLEX_TC_LID_FRONT_RIGHT_PT = Point(
56
+ x=FLEX_TC_LID_COLLISION_ZONE["front_right"]["x"],
57
+ y=FLEX_TC_LID_COLLISION_ZONE["front_right"]["y"],
58
+ z=FLEX_TC_LID_COLLISION_ZONE["front_right"]["z"],
59
+ )
60
+
61
+
62
+ def check_safe_for_pipette_movement( # noqa: C901
63
+ engine_state: StateView,
64
+ pipette_id: str,
65
+ labware_id: str,
66
+ well_name: str,
67
+ well_location: WellLocationType,
68
+ ) -> None:
69
+ """Check if the labware is safe to move to with a pipette in partial tip configuration.
70
+
71
+ Args:
72
+ engine_state: engine state view
73
+ pipette_id: ID of the pipette to be moved
74
+ labware_id: ID of the labware we are moving to
75
+ well_name: Name of the well to move to
76
+ well_location: exact location within the well to move to
77
+ """
78
+ # TODO (spp, 2023-02-06): remove this check after thorough testing.
79
+ # This function is capable of checking for movement conflict regardless of
80
+ # nozzle configuration.
81
+ if not engine_state.pipettes.get_is_partially_configured(pipette_id):
82
+ return
83
+
84
+ if isinstance(well_location, DropTipWellLocation):
85
+ # convert to WellLocation
86
+ well_location = engine_state.geometry.get_checked_tip_drop_location(
87
+ pipette_id=pipette_id,
88
+ labware_id=labware_id,
89
+ well_location=well_location,
90
+ partially_configured=True,
91
+ )
92
+ well_location_point = engine_state.geometry.get_well_position(
93
+ labware_id=labware_id,
94
+ well_name=well_name,
95
+ well_location=well_location,
96
+ pipette_id=pipette_id,
97
+ )
98
+ primary_nozzle = engine_state.pipettes.get_primary_nozzle(pipette_id)
99
+
100
+ destination_cp = _get_critical_point_to_use(engine_state, labware_id)
101
+ pipette_bounds_at_well_location = (
102
+ engine_state.pipettes.get_pipette_bounds_at_specified_move_to_position(
103
+ pipette_id=pipette_id,
104
+ destination_position=well_location_point,
105
+ critical_point=destination_cp,
106
+ )
107
+ )
108
+ if not _is_within_pipette_extents(
109
+ engine_state=engine_state,
110
+ pipette_id=pipette_id,
111
+ pipette_bounding_box_at_loc=pipette_bounds_at_well_location,
112
+ ):
113
+ raise PartialTipMovementNotAllowedError(
114
+ f"Requested motion with the {primary_nozzle} nozzle partial configuration"
115
+ f" is outside of robot bounds for the pipette."
116
+ )
117
+ ancestor = engine_state.geometry.get_ancestor_slot_name(labware_id)
118
+ if isinstance(ancestor, StagingSlotName):
119
+ raise LocationIsStagingSlotError(
120
+ "Cannot perform pipette actions on labware in Staging Area Slot."
121
+ )
122
+ labware_slot = ancestor
123
+
124
+ surrounding_slots = adjacent_slots_getters.get_surrounding_slots(
125
+ slot=labware_slot.as_int(), robot_type=engine_state.config.robot_type
126
+ )
127
+
128
+ if _will_collide_with_thermocycler_lid(
129
+ engine_state=engine_state,
130
+ pipette_bounds=pipette_bounds_at_well_location,
131
+ surrounding_regular_slots=surrounding_slots.regular_slots,
132
+ ):
133
+ raise PartialTipMovementNotAllowedError(
134
+ f"Moving to {engine_state.labware.get_display_name(labware_id)} in slot"
135
+ f" {labware_slot} with {primary_nozzle} nozzle partial configuration"
136
+ f" will result in collision with thermocycler lid in deck slot A1."
137
+ )
138
+
139
+ for regular_slot in surrounding_slots.regular_slots:
140
+ if _slot_has_potential_colliding_object(
141
+ engine_state=engine_state,
142
+ pipette_bounds=pipette_bounds_at_well_location,
143
+ surrounding_slot=regular_slot,
144
+ ):
145
+ raise PartialTipMovementNotAllowedError(
146
+ f"Moving to {engine_state.labware.get_display_name(labware_id)} in slot"
147
+ f" {labware_slot} with {primary_nozzle} nozzle partial configuration"
148
+ f" will result in collision with items in deck slot {regular_slot}."
149
+ )
150
+ for staging_slot in surrounding_slots.staging_slots:
151
+ if _slot_has_potential_colliding_object(
152
+ engine_state=engine_state,
153
+ pipette_bounds=pipette_bounds_at_well_location,
154
+ surrounding_slot=staging_slot,
155
+ ):
156
+ raise PartialTipMovementNotAllowedError(
157
+ f"Moving to {engine_state.labware.get_display_name(labware_id)} in slot"
158
+ f" {labware_slot} with {primary_nozzle} nozzle partial configuration"
159
+ f" will result in collision with items in staging slot {staging_slot}."
160
+ )
161
+
162
+
163
+ def _get_critical_point_to_use(
164
+ engine_state: StateView, labware_id: str
165
+ ) -> Optional[CriticalPoint]:
166
+ """Return the critical point to use when accessing the given labware."""
167
+ # TODO (spp, 2024-09-17): looks like Y_CENTER of column is the same as its XY_CENTER.
168
+ # I'm using this if-else ladder to be consistent with what we do in
169
+ # `MotionPlanning.get_movement_waypoints_to_well()`.
170
+ # We should probably use only XY_CENTER in both places.
171
+ if engine_state.labware.get_should_center_column_on_target_well(labware_id):
172
+ return CriticalPoint.Y_CENTER
173
+ elif engine_state.labware.get_should_center_pipette_on_target_well(labware_id):
174
+ return CriticalPoint.XY_CENTER
175
+ return None
176
+
177
+
178
+ def _slot_has_potential_colliding_object(
179
+ engine_state: StateView,
180
+ pipette_bounds: Tuple[Point, Point, Point, Point],
181
+ surrounding_slot: Union[DeckSlotName, StagingSlotName],
182
+ ) -> bool:
183
+ """Return the slot, if any, that has an item that the pipette might collide into."""
184
+ # Check if slot overlaps with pipette position
185
+ slot_pos = engine_state.addressable_areas.get_addressable_area_position(
186
+ addressable_area_name=surrounding_slot.id,
187
+ do_compatibility_check=False,
188
+ )
189
+ slot_bounds = engine_state.addressable_areas.get_addressable_area_bounding_box(
190
+ addressable_area_name=surrounding_slot.id,
191
+ do_compatibility_check=False,
192
+ )
193
+ slot_back_left_coords = Point(slot_pos.x, slot_pos.y + slot_bounds.y, slot_pos.z)
194
+ slot_front_right_coords = Point(slot_pos.x + slot_bounds.x, slot_pos.y, slot_pos.z)
195
+
196
+ # If slot overlaps with pipette bounds
197
+ if point_calculations.are_overlapping_rectangles(
198
+ rectangle1=(pipette_bounds[0], pipette_bounds[1]),
199
+ rectangle2=(slot_back_left_coords, slot_front_right_coords),
200
+ ):
201
+ # Check z-height of items in overlapping slot
202
+ if isinstance(surrounding_slot, DeckSlotName):
203
+ slot_highest_z = engine_state.geometry.get_highest_z_in_slot(
204
+ DeckSlotLocation(slotName=surrounding_slot)
205
+ )
206
+ else:
207
+ slot_highest_z = engine_state.geometry.get_highest_z_in_slot(
208
+ StagingSlotLocation(slotName=surrounding_slot)
209
+ )
210
+ return slot_highest_z >= pipette_bounds[0].z
211
+ return False
212
+
213
+
214
+ def _will_collide_with_thermocycler_lid(
215
+ engine_state: StateView,
216
+ pipette_bounds: Tuple[Point, Point, Point, Point],
217
+ surrounding_regular_slots: List[DeckSlotName],
218
+ ) -> bool:
219
+ """Return whether the pipette might collide with thermocycler's lid/clips on a Flex.
220
+
221
+ If any of the pipette's bounding vertices lie inside the no-go zone of the thermocycler-
222
+ which is the area that's to the left, back and below the thermocycler's lid's
223
+ protruding clips, then we will mark the movement for possible collision.
224
+
225
+ This could cause false raises for the case where an 8-channel is accessing the
226
+ thermocycler labware in a location such that the pipette is in the area between
227
+ the clips but not touching either clips. But that's a tradeoff we'll need to make
228
+ between a complicated check involving accurate positions of all entities involved
229
+ and a crude check that disallows all partial tip movements around the thermocycler.
230
+ """
231
+ # TODO (spp, 2024-02-27): Improvements:
232
+ # - make the check dynamic according to lid state:
233
+ # - if lid is open, check if pipette is in no-go zone
234
+ # - if lid is closed, use the closed lid height to check for conflict
235
+ if (
236
+ DeckSlotName.SLOT_A1 in surrounding_regular_slots
237
+ and engine_state.modules.is_flex_deck_with_thermocycler()
238
+ ):
239
+ return (
240
+ point_calculations.are_overlapping_rectangles(
241
+ rectangle1=(_FLEX_TC_LID_BACK_LEFT_PT, _FLEX_TC_LID_FRONT_RIGHT_PT),
242
+ rectangle2=(pipette_bounds[0], pipette_bounds[1]),
243
+ )
244
+ and pipette_bounds[0].z <= _FLEX_TC_LID_BACK_LEFT_PT.z
245
+ )
246
+
247
+ return False
248
+
249
+
250
+ def check_safe_for_tip_pickup_and_return(
251
+ engine_state: StateView,
252
+ pipette_id: str,
253
+ labware_id: str,
254
+ ) -> None:
255
+ """Check if the presence or absence of a tiprack adapter might cause any pipette movement issues.
256
+
257
+ A 96 channel pipette will pick up tips using cam action when it's configured
258
+ to use ALL nozzles. For this, the tiprack needs to be on the Flex 96 channel tiprack adapter
259
+ or similar or the tips will not be picked up.
260
+
261
+ On the other hand, if the pipette is configured with partial nozzle configuration,
262
+ it uses the usual pipette presses to pick the tips up, in which case, having the tiprack
263
+ on the Flex 96 channel tiprack adapter (or similar) will cause the pipette to
264
+ crash against the adapter posts.
265
+
266
+ In order to check if the 96-channel can move and pickup/drop tips safely, this method
267
+ checks for the height attribute of the tiprack adapter rather than checking for the
268
+ specific official adapter since users might create custom labware &/or definitions
269
+ compatible with the official adapter.
270
+ """
271
+ if not engine_state.pipettes.get_channels(pipette_id) == 96:
272
+ # Adapters only matter to 96 ch.
273
+ return
274
+
275
+ is_partial_config = engine_state.pipettes.get_is_partially_configured(pipette_id)
276
+ tiprack_name = engine_state.labware.get_display_name(labware_id)
277
+ tiprack_parent = engine_state.labware.get_location(labware_id)
278
+ if isinstance(tiprack_parent, OnLabwareLocation): # tiprack is on an adapter
279
+ is_96_ch_tiprack_adapter = engine_state.labware.get_has_quirk(
280
+ labware_id=tiprack_parent.labwareId, quirk="tiprackAdapterFor96Channel"
281
+ )
282
+ tiprack_height = engine_state.labware.get_dimensions(labware_id=labware_id).z
283
+ adapter_height = engine_state.labware.get_dimensions(
284
+ labware_id=tiprack_parent.labwareId
285
+ ).z
286
+ # todo(mm, 2025-07-31): This looks like it needs to be something like
287
+ # `tiprack_top_plane < adapter_top_plane` instead of `tiprack_height < adapter_height`.
288
+ # In other words, take into account the stacking offset between the tip rack
289
+ # and its adapter.
290
+ if is_partial_config and tiprack_height < adapter_height:
291
+ raise PartialTipMovementNotAllowedError(
292
+ f"{tiprack_name} cannot be on an adapter taller than the tip rack"
293
+ f" when picking up fewer than 96 tips."
294
+ )
295
+ elif not is_partial_config and not is_96_ch_tiprack_adapter:
296
+ raise UnsuitableTiprackForPipetteMotion(
297
+ f"{tiprack_name} must be on an Opentrons Flex 96 Tip Rack Adapter"
298
+ f" in order to pick up or return all 96 tips simultaneously."
299
+ )
300
+
301
+ elif (
302
+ not is_partial_config
303
+ ): # tiprack is not on adapter and pipette is in full config
304
+ raise UnsuitableTiprackForPipetteMotion(
305
+ f"{tiprack_name} must be on an Opentrons Flex 96 Tip Rack Adapter"
306
+ f" in order to pick up or return all 96 tips simultaneously."
307
+ )
308
+
309
+
310
+ def _is_within_pipette_extents(
311
+ engine_state: StateView,
312
+ pipette_id: str,
313
+ pipette_bounding_box_at_loc: Tuple[Point, Point, Point, Point],
314
+ ) -> bool:
315
+ """Whether a given point is within the extents of a configured pipette on the specified robot."""
316
+ channels = engine_state.pipettes.get_channels(pipette_id)
317
+ robot_extents = engine_state.geometry.absolute_deck_extents
318
+ (
319
+ pip_back_left_bound,
320
+ pip_front_right_bound,
321
+ pip_back_right_bound,
322
+ pip_front_left_bound,
323
+ ) = pipette_bounding_box_at_loc
324
+
325
+ # Given the padding values accounted for against the deck extents,
326
+ # a pipette is within extents when all of the following are true:
327
+
328
+ # Each corner slot full pickup case:
329
+ # A1: Front right nozzle is within the rear and left-side padding limits
330
+ # D1: Back right nozzle is within the front and left-side padding limits
331
+ # A3 Front left nozzle is within the rear and right-side padding limits
332
+ # D3: Back left nozzle is within the front and right-side padding limits
333
+ # Thermocycler Column A2: Front right nozzle is within padding limits
334
+
335
+ if channels == 96:
336
+ return (
337
+ pip_front_right_bound.y
338
+ <= robot_extents.deck_extents.y + robot_extents.padding_rear
339
+ and pip_front_right_bound.x >= robot_extents.padding_left_side
340
+ and pip_back_right_bound.y >= robot_extents.padding_front
341
+ and pip_back_right_bound.x >= robot_extents.padding_left_side
342
+ and pip_front_left_bound.y
343
+ <= robot_extents.deck_extents.y + robot_extents.padding_rear
344
+ and pip_front_left_bound.x
345
+ <= robot_extents.deck_extents.x + robot_extents.padding_right_side
346
+ and pip_back_left_bound.y >= robot_extents.padding_front
347
+ and pip_back_left_bound.x
348
+ <= robot_extents.deck_extents.x + robot_extents.padding_right_side
349
+ )
350
+ # For 8ch pipettes we only check the rear and front extents
351
+ return (
352
+ pip_front_right_bound.y
353
+ <= robot_extents.deck_extents.y + robot_extents.padding_rear
354
+ and pip_back_right_bound.y >= robot_extents.padding_front
355
+ and pip_front_left_bound.y
356
+ <= robot_extents.deck_extents.y + robot_extents.padding_rear
357
+ and pip_back_left_bound.y >= robot_extents.padding_front
358
+ )
@@ -0,0 +1,64 @@
1
+ from typing import Tuple
2
+
3
+ from opentrons.types import Point
4
+
5
+
6
+ def get_relative_offset(
7
+ point: Point,
8
+ size: Tuple[float, float, float],
9
+ x_ratio: float,
10
+ y_ratio: float,
11
+ z_ratio: float,
12
+ ) -> Point:
13
+ """Gets a relative offset for a deck coordinate based on percentage of the radius of each axis."""
14
+ x_size, y_size, z_size = size
15
+
16
+ x_offset = x_size / 2.0 * x_ratio
17
+ y_offset = y_size / 2.0 * y_ratio
18
+ z_offset = z_size / 2.0 * z_ratio
19
+
20
+ return Point(
21
+ x=point.x + x_offset,
22
+ y=point.y + y_offset,
23
+ z=point.z + z_offset,
24
+ )
25
+
26
+
27
+ def are_overlapping_rectangles(
28
+ rectangle1: Tuple[Point, Point],
29
+ rectangle2: Tuple[Point, Point],
30
+ ) -> bool:
31
+ """Return whether the two provided rectangles are overlapping in 2D space.
32
+
33
+ The rectangles are assumed to be coplanar and represented by tuples of
34
+ the back-left and front right vertices (in that order) of the respective rectangles.
35
+ The z-coordinate of each point will be ignored.
36
+
37
+ We determine if the rectangles overlap by comparing projections of the sides of
38
+ the rectangles on each of the 2 axes (x & y). If the projections on each axis overlap,
39
+ then we can conclude that the rectangles overlap.
40
+
41
+ The projection on an axis overlaps if the distance between the first projected point
42
+ and the last projected point is less than the sum of the lengths of the projected sides
43
+ of the two rectangles. For example, if we have two rectangles with vertices:
44
+ Rect1 -> BL: (x1, y1), FR: (x2, y2)
45
+ Rect2 -> BL: (x3, y3), FR: (x4, y4)
46
+
47
+ Then for the two rectangles to be overlapping, they should satisfy:
48
+ max(x1, x2, x3, x4) - min(x1, x2, x3, x4) < (x2 - x1) + (x4 - x3)
49
+ AND
50
+ max(y1, y2, y3, y4) - min(y1, y2, y3, y4) < (y2 - y1) + (y4 - y3)
51
+ """
52
+ x_coordinates = [rectangle1[0].x, rectangle1[1].x, rectangle2[0].x, rectangle2[1].x]
53
+ x_length_rect1 = abs(rectangle1[1].x - rectangle1[0].x)
54
+ x_length_rect2 = abs(rectangle2[1].x - rectangle2[0].x)
55
+ overlapping_in_x = (
56
+ abs(max(x_coordinates) - min(x_coordinates)) < x_length_rect1 + x_length_rect2
57
+ )
58
+ y_coordinates = [rectangle1[0].y, rectangle1[1].y, rectangle2[0].y, rectangle2[1].y]
59
+ y_length_rect1 = abs(rectangle1[1].y - rectangle1[0].y)
60
+ y_length_rect2 = abs(rectangle2[1].y - rectangle2[0].y)
61
+ overlapping_in_y = (
62
+ abs(max(y_coordinates) - min(y_coordinates)) < y_length_rect1 + y_length_rect2
63
+ )
64
+ return overlapping_in_x and overlapping_in_y