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,699 @@
1
+ """Basic addressable area data state and store."""
2
+
3
+ from dataclasses import dataclass
4
+ from functools import cached_property
5
+ from typing import Dict, List, Optional, Set
6
+
7
+ from opentrons_shared_data.robot.types import RobotType, RobotDefinition
8
+ from opentrons_shared_data.deck.types import (
9
+ DeckDefinitionV5,
10
+ SlotDefV3,
11
+ CutoutFixture,
12
+ )
13
+
14
+ from opentrons.types import Point, DeckSlotName
15
+
16
+ from ..errors import (
17
+ IncompatibleAddressableAreaError,
18
+ AreaNotInDeckConfigurationError,
19
+ SlotDoesNotExistError,
20
+ AddressableAreaDoesNotExistError,
21
+ CutoutDoesNotExistError,
22
+ )
23
+ from ..resources import deck_configuration_provider
24
+ from ..types import (
25
+ AddressableArea,
26
+ PotentialCutoutFixture,
27
+ DeckConfigurationType,
28
+ Dimensions,
29
+ )
30
+ from ..actions.get_state_update import get_state_updates
31
+ from ..actions import (
32
+ Action,
33
+ SetDeckConfigurationAction,
34
+ AddAddressableAreaAction,
35
+ )
36
+ from . import update_types
37
+ from .config import Config
38
+ from ._abstract_store import HasState, HandlesActions
39
+
40
+
41
+ @dataclass
42
+ class AddressableAreaState:
43
+ """State of all loaded addressable area resources."""
44
+
45
+ loaded_addressable_areas_by_name: Dict[str, AddressableArea]
46
+ """The addressable areas that have been loaded so far.
47
+
48
+ When `use_simulated_deck_config` is `False`, these are the addressable areas that the
49
+ deck configuration provided.
50
+
51
+ When `use_simulated_deck_config` is `True`, these are the addressable areas that have been
52
+ referenced by the protocol so far.
53
+ """
54
+
55
+ potential_cutout_fixtures_by_cutout_id: Dict[str, Set[PotentialCutoutFixture]]
56
+
57
+ deck_definition: DeckDefinitionV5
58
+
59
+ deck_configuration: Optional[DeckConfigurationType]
60
+ """The host robot's full deck configuration.
61
+
62
+ If `use_simulated_deck_config` is `True`, this is meaningless and this value is undefined.
63
+ In practice it will probably be `None` or `[]`.
64
+
65
+ If `use_simulated_deck_config` is `False`, this will be non-`None`.
66
+ """
67
+
68
+ robot_type: RobotType
69
+
70
+ use_simulated_deck_config: bool
71
+ """See `Config.use_simulated_deck_config`."""
72
+
73
+ """Information about the current robot model."""
74
+ robot_definition: RobotDefinition
75
+
76
+
77
+ _OT2_ORDERED_SLOTS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
78
+ _FLEX_ORDERED_SLOTS = [
79
+ "D1",
80
+ "D2",
81
+ "D3",
82
+ "C1",
83
+ "C2",
84
+ "C3",
85
+ "B1",
86
+ "B2",
87
+ "B3",
88
+ "A1",
89
+ "A2",
90
+ "A3",
91
+ ]
92
+ _FLEX_ORDERED_STAGING_SLOTS = ["D4", "C4", "B4", "A4"]
93
+
94
+
95
+ def _get_conflicting_addressable_areas_error_string(
96
+ potential_cutout_fixtures: Set[PotentialCutoutFixture],
97
+ loaded_addressable_areas: Dict[str, AddressableArea],
98
+ deck_definition: DeckDefinitionV5,
99
+ ) -> str:
100
+ loaded_areas_on_cutout = set()
101
+ for fixture in potential_cutout_fixtures:
102
+ loaded_areas_on_cutout.update(
103
+ deck_configuration_provider.get_provided_addressable_area_names(
104
+ fixture.cutout_fixture_id,
105
+ fixture.cutout_id,
106
+ deck_definition,
107
+ )
108
+ )
109
+ loaded_areas_on_cutout.intersection_update(loaded_addressable_areas)
110
+ display_names = {
111
+ loaded_addressable_areas[area].display_name for area in loaded_areas_on_cutout
112
+ }
113
+ return ", ".join(display_names)
114
+
115
+
116
+ class AddressableAreaStore(HasState[AddressableAreaState], HandlesActions):
117
+ """Addressable area state container."""
118
+
119
+ _state: AddressableAreaState
120
+
121
+ def __init__(
122
+ self,
123
+ deck_configuration: DeckConfigurationType,
124
+ config: Config,
125
+ deck_definition: DeckDefinitionV5,
126
+ robot_definition: RobotDefinition,
127
+ ) -> None:
128
+ """Initialize an addressable area store and its state."""
129
+ if config.use_simulated_deck_config:
130
+ loaded_addressable_areas_by_name = {}
131
+ else:
132
+ loaded_addressable_areas_by_name = (
133
+ self._get_addressable_areas_from_deck_configuration(
134
+ deck_configuration,
135
+ deck_definition,
136
+ )
137
+ )
138
+
139
+ self._state = AddressableAreaState(
140
+ deck_configuration=deck_configuration,
141
+ loaded_addressable_areas_by_name=loaded_addressable_areas_by_name,
142
+ potential_cutout_fixtures_by_cutout_id={},
143
+ deck_definition=deck_definition,
144
+ robot_type=config.robot_type,
145
+ use_simulated_deck_config=config.use_simulated_deck_config,
146
+ robot_definition=robot_definition,
147
+ )
148
+
149
+ def handle_action(self, action: Action) -> None:
150
+ """Modify state in reaction to an action."""
151
+ for state_update in get_state_updates(action):
152
+ if state_update.addressable_area_used != update_types.NO_CHANGE:
153
+ self._add_addressable_area(
154
+ state_update.addressable_area_used.addressable_area_name
155
+ )
156
+
157
+ if isinstance(action, AddAddressableAreaAction):
158
+ self._add_addressable_area(action.addressable_area_name)
159
+ elif isinstance(action, SetDeckConfigurationAction):
160
+ current_state = self._state
161
+ if (
162
+ action.deck_configuration is not None
163
+ and not self._state.use_simulated_deck_config
164
+ ):
165
+ self._state.deck_configuration = action.deck_configuration
166
+ self._state.loaded_addressable_areas_by_name = (
167
+ self._get_addressable_areas_from_deck_configuration(
168
+ deck_config=action.deck_configuration,
169
+ deck_definition=current_state.deck_definition,
170
+ )
171
+ )
172
+
173
+ @staticmethod
174
+ def _get_addressable_areas_from_deck_configuration(
175
+ deck_config: DeckConfigurationType, deck_definition: DeckDefinitionV5
176
+ ) -> Dict[str, AddressableArea]:
177
+ """Return all addressable areas provided by the given deck configuration."""
178
+ addressable_areas = []
179
+ for cutout_id, cutout_fixture_id, opentrons_module_serial_number in deck_config:
180
+ provided_addressable_areas = (
181
+ deck_configuration_provider.get_provided_addressable_area_names(
182
+ cutout_fixture_id, cutout_id, deck_definition
183
+ )
184
+ )
185
+ cutout_position = deck_configuration_provider.get_cutout_position(
186
+ cutout_id, deck_definition
187
+ )
188
+ for addressable_area_name in provided_addressable_areas:
189
+ addressable_areas.append(
190
+ deck_configuration_provider.get_addressable_area_from_name(
191
+ addressable_area_name=addressable_area_name,
192
+ cutout_position=cutout_position,
193
+ deck_definition=deck_definition,
194
+ )
195
+ )
196
+ return {area.area_name: area for area in addressable_areas}
197
+
198
+ def _add_addressable_area(self, addressable_area_name: str) -> None:
199
+ if addressable_area_name not in self._state.loaded_addressable_areas_by_name:
200
+ cutout_id = self._validate_addressable_area_for_simulation(
201
+ addressable_area_name
202
+ )
203
+
204
+ cutout_position = deck_configuration_provider.get_cutout_position(
205
+ cutout_id, self._state.deck_definition
206
+ )
207
+ addressable_area = (
208
+ deck_configuration_provider.get_addressable_area_from_name(
209
+ addressable_area_name=addressable_area_name,
210
+ cutout_position=cutout_position,
211
+ deck_definition=self._state.deck_definition,
212
+ )
213
+ )
214
+ self._state.loaded_addressable_areas_by_name[
215
+ addressable_area.area_name
216
+ ] = addressable_area
217
+
218
+ def _validate_addressable_area_for_simulation(
219
+ self, addressable_area_name: str
220
+ ) -> str:
221
+ """Given an addressable area name, validate it can exist on the deck and return cutout id associated with it."""
222
+ (
223
+ cutout_id,
224
+ potential_fixtures,
225
+ ) = deck_configuration_provider.get_potential_cutout_fixtures(
226
+ addressable_area_name, self._state.deck_definition
227
+ )
228
+
229
+ if cutout_id in self._state.potential_cutout_fixtures_by_cutout_id:
230
+ # Get the existing potential cutout fixtures for the addressable area already loaded on this cutout
231
+ existing_potential_fixtures = (
232
+ self._state.potential_cutout_fixtures_by_cutout_id[cutout_id]
233
+ )
234
+ # Get common cutout fixture that supplies existing addressable areas and the one being loaded
235
+ remaining_fixtures = existing_potential_fixtures.intersection(
236
+ set(potential_fixtures)
237
+ )
238
+
239
+ self._state.potential_cutout_fixtures_by_cutout_id[
240
+ cutout_id
241
+ ] = remaining_fixtures
242
+ else:
243
+ self._state.potential_cutout_fixtures_by_cutout_id[cutout_id] = set(
244
+ potential_fixtures
245
+ )
246
+
247
+ return cutout_id
248
+
249
+
250
+ class AddressableAreaView:
251
+ """Read-only addressable area state view."""
252
+
253
+ _state: AddressableAreaState
254
+
255
+ def __init__(self, state: AddressableAreaState) -> None:
256
+ """Initialize the computed view of addressable area state.
257
+
258
+ Arguments:
259
+ state: Addressable area state dataclass used for all calculations.
260
+ """
261
+ self._state = state
262
+
263
+ @cached_property
264
+ def deck_definition(self) -> DeckDefinitionV5:
265
+ """The full deck definition."""
266
+ return self._state.deck_definition
267
+
268
+ @cached_property
269
+ def deck_extents(self) -> Point:
270
+ """The maximum space on the deck."""
271
+ extents = self._state.robot_definition["extents"]
272
+ return Point(x=extents[0], y=extents[1], z=extents[2])
273
+
274
+ @cached_property
275
+ def mount_offsets(self) -> Dict[str, Point]:
276
+ """The left and right mount offsets of the robot."""
277
+ left_offset = self._state.robot_definition["mountOffsets"]["left"]
278
+ right_offset = self._state.robot_definition["mountOffsets"]["right"]
279
+ return {
280
+ "left": Point(x=left_offset[0], y=left_offset[1], z=left_offset[2]),
281
+ "right": Point(x=right_offset[0], y=right_offset[1], z=right_offset[2]),
282
+ }
283
+
284
+ @cached_property
285
+ def padding_offsets(self) -> Dict[str, float]:
286
+ """The padding offsets to be applied to the deck extents of the robot."""
287
+ rear_offset = self._state.robot_definition["paddingOffsets"]["rear"]
288
+ front_offset = self._state.robot_definition["paddingOffsets"]["front"]
289
+ left_side_offset = self._state.robot_definition["paddingOffsets"]["leftSide"]
290
+ right_side_offset = self._state.robot_definition["paddingOffsets"]["rightSide"]
291
+ return {
292
+ "rear": rear_offset,
293
+ "front": front_offset,
294
+ "left_side": left_side_offset,
295
+ "right_side": right_side_offset,
296
+ }
297
+
298
+ def get_addressable_area(self, addressable_area_name: str) -> AddressableArea:
299
+ """Get addressable area."""
300
+ if not self._state.use_simulated_deck_config:
301
+ return self._get_loaded_addressable_area(addressable_area_name)
302
+ else:
303
+ return self._get_addressable_area_from_deck_data(
304
+ addressable_area_name=addressable_area_name,
305
+ do_compatibility_check=True,
306
+ )
307
+
308
+ def get_all(self) -> List[str]:
309
+ """Get a list of all loaded addressable area names."""
310
+ return list(self._state.loaded_addressable_areas_by_name)
311
+
312
+ def get_all_cutout_fixtures(self) -> Optional[List[str]]:
313
+ """Get the names of all fixtures present in the host robot's deck configuration.
314
+
315
+ If `use_simulated_deck_config` is `True` (see `Config`), we don't have a
316
+ meaningful concrete layout of fixtures, so this will return `None`.
317
+ """
318
+ if self._state.use_simulated_deck_config:
319
+ return None
320
+ else:
321
+ assert self._state.deck_configuration is not None
322
+ return [
323
+ cutout_fixture_id
324
+ for _, cutout_fixture_id, _serial in self._state.deck_configuration
325
+ ]
326
+
327
+ def _get_loaded_addressable_area(
328
+ self, addressable_area_name: str
329
+ ) -> AddressableArea:
330
+ """Get an addressable area that has been loaded into state. Will raise error if it does not exist."""
331
+ try:
332
+ return self._state.loaded_addressable_areas_by_name[addressable_area_name]
333
+ except KeyError:
334
+ raise AreaNotInDeckConfigurationError(
335
+ f"{addressable_area_name} not provided by deck configuration."
336
+ )
337
+
338
+ def _check_if_area_is_compatible_with_potential_fixtures(
339
+ self,
340
+ area_name: str,
341
+ cutout_id: str,
342
+ potential_fixtures: Set[PotentialCutoutFixture],
343
+ ) -> None:
344
+ if cutout_id in self._state.potential_cutout_fixtures_by_cutout_id:
345
+ if not self._state.potential_cutout_fixtures_by_cutout_id[
346
+ cutout_id
347
+ ].intersection(potential_fixtures):
348
+ loaded_areas_on_cutout = (
349
+ _get_conflicting_addressable_areas_error_string(
350
+ self._state.potential_cutout_fixtures_by_cutout_id[cutout_id],
351
+ self._state.loaded_addressable_areas_by_name,
352
+ self._state.deck_definition,
353
+ )
354
+ )
355
+ area_display_name = (
356
+ deck_configuration_provider.get_addressable_area_display_name(
357
+ area_name, self._state.deck_definition
358
+ )
359
+ )
360
+ raise IncompatibleAddressableAreaError(
361
+ f"Cannot use {area_display_name}, not compatible with one or more of"
362
+ f" the following fixtures: {loaded_areas_on_cutout}"
363
+ )
364
+
365
+ def _get_addressable_area_from_deck_data(
366
+ self,
367
+ addressable_area_name: str,
368
+ do_compatibility_check: bool,
369
+ ) -> AddressableArea:
370
+ """Get an addressable area that may not have been already loaded for a simulated run.
371
+
372
+ Since this may be the first time this addressable area has been called, and it might not exist in the store
373
+ yet (and if not won't until the result completes), we have to check if it is theoretically possible and then
374
+ get the area data from the deck configuration provider.
375
+ """
376
+ if addressable_area_name in self._state.loaded_addressable_areas_by_name:
377
+ return self._state.loaded_addressable_areas_by_name[addressable_area_name]
378
+
379
+ (
380
+ cutout_id,
381
+ potential_fixtures,
382
+ ) = deck_configuration_provider.get_potential_cutout_fixtures(
383
+ addressable_area_name, self._state.deck_definition
384
+ )
385
+
386
+ if do_compatibility_check:
387
+ self._check_if_area_is_compatible_with_potential_fixtures(
388
+ addressable_area_name, cutout_id, potential_fixtures
389
+ )
390
+
391
+ cutout_position = deck_configuration_provider.get_cutout_position(
392
+ cutout_id, self._state.deck_definition
393
+ )
394
+ return deck_configuration_provider.get_addressable_area_from_name(
395
+ addressable_area_name=addressable_area_name,
396
+ cutout_position=cutout_position,
397
+ deck_definition=self._state.deck_definition,
398
+ )
399
+
400
+ def get_addressable_area_base_slot(
401
+ self, addressable_area_name: str
402
+ ) -> DeckSlotName:
403
+ """Get the base slot the addressable area is associated with."""
404
+ addressable_area = self.get_addressable_area(addressable_area_name)
405
+ return addressable_area.base_slot
406
+
407
+ def get_addressable_area_position(
408
+ self,
409
+ addressable_area_name: str,
410
+ do_compatibility_check: bool = True,
411
+ ) -> Point:
412
+ """Get the position of an addressable area.
413
+
414
+ This does not require the addressable area to be in the deck configuration.
415
+ This is primarily used to support legacy fixed trash labware without
416
+ modifying the deck layout to remove the similar, but functionally different,
417
+ trashBinAdapter cutout fixture.
418
+
419
+ Besides that instance, for movement purposes, this should only be called for
420
+ areas that have been pre-validated, otherwise there could be the risk of collision.
421
+ """
422
+ addressable_area = self._get_addressable_area_from_deck_data(
423
+ addressable_area_name=addressable_area_name,
424
+ do_compatibility_check=False, # This should probably not default to false
425
+ )
426
+ position = addressable_area.position
427
+ return Point(x=position.x, y=position.y, z=position.z)
428
+
429
+ def get_addressable_area_offsets_from_cutout(
430
+ self,
431
+ addressable_area_name: str,
432
+ ) -> Point:
433
+ """Get the offset form cutout fixture of an addressable area."""
434
+ for addressable_area in self._state.deck_definition["locations"][
435
+ "addressableAreas"
436
+ ]:
437
+ if addressable_area["id"] == addressable_area_name:
438
+ area_offset = addressable_area["offsetFromCutoutFixture"]
439
+ position = Point(
440
+ x=area_offset[0],
441
+ y=area_offset[1],
442
+ z=area_offset[2],
443
+ )
444
+ return Point(x=position.x, y=position.y, z=position.z)
445
+ raise ValueError(
446
+ f"No matching addressable area named {addressable_area_name} identified."
447
+ )
448
+
449
+ def get_addressable_area_bounding_box(
450
+ self,
451
+ addressable_area_name: str,
452
+ do_compatibility_check: bool = True,
453
+ ) -> Dimensions:
454
+ """Get the bounding box of an addressable area.
455
+
456
+ This does not require the addressable area to be in the deck configuration.
457
+ For movement purposes, this should only be called for
458
+ areas that have been pre-validated, otherwise there could be the risk of collision.
459
+ """
460
+ addressable_area = self._get_addressable_area_from_deck_data(
461
+ addressable_area_name=addressable_area_name,
462
+ do_compatibility_check=do_compatibility_check,
463
+ )
464
+ return addressable_area.bounding_box
465
+
466
+ def get_addressable_area_move_to_location(
467
+ self, addressable_area_name: str
468
+ ) -> Point:
469
+ """Get the move-to position (top center) for an addressable area."""
470
+ addressable_area = self.get_addressable_area(addressable_area_name)
471
+ position = addressable_area.position
472
+ bounding_box = addressable_area.bounding_box
473
+ return Point(
474
+ x=position.x + bounding_box.x / 2,
475
+ y=position.y + bounding_box.y / 2,
476
+ z=position.z + bounding_box.z,
477
+ )
478
+
479
+ def get_addressable_area_center(self, addressable_area_name: str) -> Point:
480
+ """Get the (x, y, z) position of the center of the area."""
481
+ addressable_area = self.get_addressable_area(addressable_area_name)
482
+ position = addressable_area.position
483
+ bounding_box = addressable_area.bounding_box
484
+ return Point(
485
+ x=position.x + bounding_box.x / 2,
486
+ y=position.y + bounding_box.y / 2,
487
+ z=position.z,
488
+ )
489
+
490
+ def get_cutout_id_by_deck_slot_name(self, slot_name: DeckSlotName) -> str:
491
+ """Get the Cutout ID of a given Deck Slot by Deck Slot Name."""
492
+ return deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name)
493
+
494
+ def get_fixture_by_deck_slot_name(
495
+ self, slot_name: DeckSlotName
496
+ ) -> Optional[CutoutFixture]:
497
+ """Get the Cutout Fixture currently loaded where a specific Deck Slot would be."""
498
+ deck_config = self._state.deck_configuration
499
+ if deck_config:
500
+ slot_cutout_id = (
501
+ deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name)
502
+ )
503
+ slot_cutout_fixture = None
504
+ # This will only ever be one under current assumptions
505
+ for (
506
+ cutout_id,
507
+ cutout_fixture_id,
508
+ opentrons_module_serial_number,
509
+ ) in deck_config:
510
+ if cutout_id == slot_cutout_id:
511
+ slot_cutout_fixture = (
512
+ deck_configuration_provider.get_cutout_fixture(
513
+ cutout_fixture_id, self._state.deck_definition
514
+ )
515
+ )
516
+ return slot_cutout_fixture
517
+ if slot_cutout_fixture is None:
518
+ # If this happens, it's a bug. Either DECK_SLOT_TO_CUTOUT_MAP
519
+ # is missing an entry for the slot, or the deck configuration is missing
520
+ # an entry for the cutout.
521
+ raise CutoutDoesNotExistError(
522
+ f"No Cutout was found in the Deck that matched provided slot {slot_name}."
523
+ )
524
+ return None
525
+
526
+ def get_fixture_height(self, cutout_fixture_name: str) -> float:
527
+ """Get the z height of a cutout fixture."""
528
+ cutout_fixture = deck_configuration_provider.get_cutout_fixture(
529
+ cutout_fixture_name, self._state.deck_definition
530
+ )
531
+ return cutout_fixture["height"]
532
+
533
+ def get_fixture_serial_from_deck_configuration_by_deck_slot(
534
+ self, slot_name: DeckSlotName
535
+ ) -> Optional[str]:
536
+ """Get the serial number provided by the deck configuration for a Fixture at a given location."""
537
+ deck_config = self._state.deck_configuration
538
+ if deck_config:
539
+ slot_cutout_id = (
540
+ deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name)
541
+ )
542
+ # This will only ever be one under current assumptions
543
+ for (
544
+ cutout_id,
545
+ cutout_fixture_id,
546
+ opentrons_module_serial_number,
547
+ ) in deck_config:
548
+ if cutout_id == slot_cutout_id:
549
+ return opentrons_module_serial_number
550
+ return None
551
+
552
+ def get_serial_number_by_cutout_id(self, slot_cutout_id: str) -> str | None:
553
+ """Gets serial number from deck at a given cutout ID if one exists."""
554
+ deck_config = self._state.deck_configuration
555
+ if deck_config:
556
+ for (
557
+ cutout_id,
558
+ cutout_fixture_id,
559
+ opentrons_module_serial_number,
560
+ ) in deck_config:
561
+ if cutout_id == slot_cutout_id:
562
+ return opentrons_module_serial_number
563
+ return None
564
+
565
+ def get_fixture_serial_from_deck_configuration_by_addressable_area(
566
+ self, addressable_area_name: str
567
+ ) -> Optional[str]:
568
+ """Get the serial number provided by the deck configuration for a Fixture that provides a given addressable area."""
569
+ deck_config = self._state.deck_configuration
570
+ if deck_config:
571
+ potential_fixtures = (
572
+ deck_configuration_provider.get_potential_cutout_fixtures(
573
+ addressable_area_name, self._state.deck_definition
574
+ )
575
+ )
576
+ slot_cutout_id = potential_fixtures[0]
577
+ fixture_ids = [
578
+ fixture.cutout_fixture_id for fixture in potential_fixtures[1]
579
+ ]
580
+ # This will only ever be one under current assumptions
581
+ for (
582
+ cutout_id,
583
+ cutout_fixture_id,
584
+ opentrons_module_serial_number,
585
+ ) in deck_config:
586
+ if cutout_id == slot_cutout_id and cutout_fixture_id in fixture_ids:
587
+ return opentrons_module_serial_number
588
+ return None
589
+
590
+ def get_slot_definition(self, slot_id: str) -> SlotDefV3:
591
+ """Get the definition of a slot in the deck.
592
+
593
+ This does not require that the slot exist in deck configuration.
594
+ """
595
+ try:
596
+ addressable_area = self._get_addressable_area_from_deck_data(
597
+ addressable_area_name=slot_id,
598
+ do_compatibility_check=True, # From the description of get_slot_definition, this might have to be False.
599
+ )
600
+ except AddressableAreaDoesNotExistError:
601
+ raise SlotDoesNotExistError(
602
+ f"Slot ID {slot_id} does not exist in deck {self._state.deck_definition['otId']}"
603
+ )
604
+ position = addressable_area.position
605
+ bounding_box = addressable_area.bounding_box
606
+ return {
607
+ "id": addressable_area.area_name,
608
+ "position": [position.x, position.y, position.z],
609
+ "boundingBox": {
610
+ "xDimension": bounding_box.x,
611
+ "yDimension": bounding_box.y,
612
+ "zDimension": bounding_box.z,
613
+ },
614
+ "displayName": addressable_area.display_name,
615
+ "compatibleModuleTypes": addressable_area.compatible_module_types,
616
+ "features": addressable_area.features,
617
+ }
618
+
619
+ def get_deck_slot_definitions(self) -> Dict[str, SlotDefV3]:
620
+ """Get all standard slot definitions available in the deck definition."""
621
+ if self._state.robot_type == "OT-2 Standard":
622
+ slots = _OT2_ORDERED_SLOTS
623
+ else:
624
+ slots = _FLEX_ORDERED_SLOTS
625
+ return {slot_name: self.get_slot_definition(slot_name) for slot_name in slots}
626
+
627
+ def get_staging_slot_definitions(self) -> Dict[str, SlotDefV3]:
628
+ """Get all staging slot definitions available in the deck definition."""
629
+ if self._state.robot_type == "OT-3 Standard":
630
+ return {
631
+ slot_name: self.get_slot_definition(slot_name)
632
+ for slot_name in _FLEX_ORDERED_STAGING_SLOTS
633
+ }
634
+ else:
635
+ return {}
636
+
637
+ def raise_if_area_not_in_deck_configuration(
638
+ self, addressable_area_name: str
639
+ ) -> None:
640
+ """Raise error if an addressable area is not compatible with or in the deck configuration.
641
+
642
+ For simulated runs/analysis, this will raise if the given addressable area is not compatible with other
643
+ previously referenced addressable areas, for example if a movable trash in A1 is in state, referencing the
644
+ deck slot A1 will raise since those two can't exist in any deck configuration combination.
645
+
646
+ For an on robot run, it will check if it is in the robot's deck configuration, if not it will raise an error.
647
+ """
648
+ if self._state.use_simulated_deck_config:
649
+ (
650
+ cutout_id,
651
+ potential_fixtures,
652
+ ) = deck_configuration_provider.get_potential_cutout_fixtures(
653
+ addressable_area_name, self._state.deck_definition
654
+ )
655
+
656
+ self._check_if_area_is_compatible_with_potential_fixtures(
657
+ addressable_area_name, cutout_id, potential_fixtures
658
+ )
659
+ else:
660
+ if (
661
+ addressable_area_name
662
+ not in self._state.loaded_addressable_areas_by_name
663
+ ):
664
+ raise AreaNotInDeckConfigurationError(
665
+ f"{addressable_area_name} not provided by deck configuration."
666
+ )
667
+
668
+ def get_current_potential_cutout_fixtures_for_addressable_area(
669
+ self, addressable_area_name: str
670
+ ) -> tuple[str, Set[PotentialCutoutFixture]]:
671
+ """Get the set of cutout fixtures that might provide a given addressable area.
672
+
673
+ This takes into account the constraints already established by load commands or by a loaded deck
674
+ configuration, and may therefore return different results for the same addressable area at
675
+ different points in the protocol after deck configuration constraints have changed.
676
+
677
+ This returns the common cutout id and the potential fixtures.
678
+ """
679
+ (
680
+ cutout_id,
681
+ base_potential_fixtures,
682
+ ) = deck_configuration_provider.get_potential_cutout_fixtures(
683
+ addressable_area_name, self._state.deck_definition
684
+ )
685
+ try:
686
+ loaded_potential_fixtures = (
687
+ self._state.potential_cutout_fixtures_by_cutout_id[cutout_id]
688
+ )
689
+ return cutout_id, loaded_potential_fixtures.intersection(
690
+ base_potential_fixtures
691
+ )
692
+ except KeyError:
693
+ # If there was a key error here, it's because this function was (eventually) called
694
+ # from the body of a command implementation whose state update will load the
695
+ # addressable area it's querying... but that state update has not been submitted
696
+ # and processed, so nothing has created the entry for this cutout id yet. Do what
697
+ # we'll do when we actually get to that state update, which is apply the base
698
+ # potential fixtures from the deck def.
699
+ return cutout_id, base_potential_fixtures