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,904 @@
1
+ """Structures to represent changes that commands want to make to engine state."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ import enum
7
+ import typing
8
+ from typing_extensions import Self, Optional
9
+ from datetime import datetime
10
+
11
+ from opentrons.hardware_control.nozzle_manager import NozzleMap
12
+ from opentrons.protocol_engine.resources import pipette_data_provider
13
+ from opentrons.protocol_engine.types import (
14
+ DeckPoint,
15
+ LabwareLocation,
16
+ OnLabwareLocation,
17
+ TipGeometry,
18
+ AspiratedFluid,
19
+ LiquidClassRecord,
20
+ ABSMeasureMode,
21
+ LiquidTrackingType,
22
+ StackerStoredLabwareGroup,
23
+ ModuleModel,
24
+ ModuleDefinition,
25
+ LabwareWellId,
26
+ )
27
+ from opentrons.types import MountType, DeckSlotName
28
+ from opentrons_shared_data.labware.labware_definition import LabwareDefinition
29
+ from opentrons_shared_data.pipette.types import PipetteNameType
30
+
31
+
32
+ class _NoChangeEnum(enum.Enum):
33
+ NO_CHANGE = enum.auto()
34
+
35
+
36
+ NO_CHANGE: typing.Final = _NoChangeEnum.NO_CHANGE
37
+ """A sentinel value to indicate that a value shouldn't be changed.
38
+
39
+ Useful when `None` is semantically unclear or already has some other meaning.
40
+ """
41
+
42
+
43
+ NoChangeType: typing.TypeAlias = typing.Literal[_NoChangeEnum.NO_CHANGE]
44
+ """The type of `NO_CHANGE`, as `NoneType` is to `None`.
45
+
46
+ Unfortunately, mypy doesn't let us write `Literal[NO_CHANGE]`. Use this instead.
47
+ """
48
+
49
+
50
+ class _ClearEnum(enum.Enum):
51
+ CLEAR = enum.auto()
52
+
53
+
54
+ CLEAR: typing.Final = _ClearEnum.CLEAR
55
+ """A sentinel value to indicate that a value should be cleared.
56
+
57
+ Useful when `None` is semantically unclear or has some other meaning.
58
+ """
59
+
60
+
61
+ ClearType: typing.TypeAlias = typing.Literal[_ClearEnum.CLEAR]
62
+ """The type of `CLEAR`, as `NoneType` is to `None`.
63
+
64
+ Unfortunately, mypy doesn't let us write `Literal[CLEAR]`. Use this instead.
65
+ """
66
+
67
+
68
+ @dataclasses.dataclass(frozen=True)
69
+ class AddressableArea:
70
+ """Designates an addressable area."""
71
+
72
+ addressable_area_name: str
73
+
74
+
75
+ @dataclasses.dataclass
76
+ class PipetteLocationUpdate:
77
+ """An update to a pipette's location."""
78
+
79
+ pipette_id: str
80
+ """The ID of the already-loaded pipette."""
81
+
82
+ new_location: LabwareWellId | AddressableArea | None | NoChangeType
83
+ """The pipette's new logical location.
84
+
85
+ Note: `new_location=None` means "change the location to `None` (unknown)",
86
+ not "do not change the location".
87
+ """
88
+
89
+ new_deck_point: DeckPoint | NoChangeType
90
+
91
+
92
+ @dataclasses.dataclass
93
+ class LabwareLocationUpdate:
94
+ """An update to a labware's location."""
95
+
96
+ labware_id: str
97
+ """The ID of the already-loaded labware."""
98
+
99
+ new_location: LabwareLocation
100
+ """The labware's new location."""
101
+
102
+ offset_id: str | None
103
+ """The ID of the labware's new offset, for its new location."""
104
+
105
+
106
+ @dataclasses.dataclass
107
+ class BatchLabwareLocationUpdate:
108
+ """An update to the locations of multiple labware."""
109
+
110
+ new_locations_by_id: dict[str, LabwareLocation]
111
+ """The new locations of each ID."""
112
+ new_offset_ids_by_id: dict[str, str | None]
113
+ """The new offsets of each id."""
114
+
115
+
116
+ # todo(mm, 2025-04-28): Combine with BatchLoadedLabwareUpdate.
117
+ @dataclasses.dataclass
118
+ class LoadedLabwareUpdate:
119
+ """An update that loads a new labware."""
120
+
121
+ labware_id: str
122
+ """The unique ID of the new labware."""
123
+
124
+ new_location: LabwareLocation
125
+ """The labware's initial location."""
126
+
127
+ offset_id: str | None
128
+ """The ID of the labware's offset."""
129
+
130
+ display_name: str | None
131
+
132
+ definition: LabwareDefinition
133
+
134
+
135
+ @dataclasses.dataclass
136
+ class BatchLoadedLabwareUpdate:
137
+ """An update that loads multiple new labware."""
138
+
139
+ new_locations_by_id: typing.Dict[str, LabwareLocation]
140
+ """Each new labwares's initial location keyed by Labware ID."""
141
+
142
+ offset_ids_by_id: typing.Dict[str, str | None]
143
+ """The ID of each labware's offset keyed by labware ID."""
144
+
145
+ display_names_by_id: typing.Dict[str, str | None]
146
+ """The Display Name for each new labware keyed by labware ID"""
147
+
148
+ definitions_by_id: typing.Dict[str, LabwareDefinition]
149
+ """The Labware Definition for each labware keyed by Labware ID."""
150
+
151
+
152
+ @dataclasses.dataclass
153
+ class LoadedLidStackUpdate:
154
+ """An update that loads a new lid stack."""
155
+
156
+ stack_id: str
157
+ """The unique ID of the Lid Stack Object."""
158
+
159
+ stack_object_definition: LabwareDefinition
160
+ "The System-only Labware Definition of the Lid Stack Object"
161
+
162
+ stack_location: LabwareLocation
163
+ "The initial location of the Lid Stack Object."
164
+
165
+ new_locations_by_id: typing.Dict[str, OnLabwareLocation]
166
+ """Each lid's initial location keyed by Labware ID."""
167
+
168
+ definition: LabwareDefinition | None
169
+ "The Labware Definition of the Lid Labware(s) loaded."
170
+
171
+
172
+ @dataclasses.dataclass
173
+ class LabwareLidUpdate:
174
+ """An update that identifies a lid on a given parent labware."""
175
+
176
+ parent_labware_ids: typing.List[str]
177
+ """The unique IDs of the parent labwares."""
178
+
179
+ lid_ids: typing.List[str | None]
180
+ """The unique IDs of the new lids."""
181
+
182
+
183
+ @dataclasses.dataclass
184
+ class LoadPipetteUpdate:
185
+ """An update that loads a new pipette.
186
+
187
+ NOTE: Currently, if this is provided, a PipetteConfigUpdate must always be
188
+ provided alongside it to fully initialize everything.
189
+ """
190
+
191
+ pipette_id: str
192
+ """The unique ID of the new pipette."""
193
+
194
+ pipette_name: PipetteNameType
195
+ mount: MountType
196
+ liquid_presence_detection: bool | None
197
+
198
+
199
+ @dataclasses.dataclass
200
+ class PipetteConfigUpdate:
201
+ """An update to a pipette's config."""
202
+
203
+ pipette_id: str
204
+ """The ID of the already-loaded pipette."""
205
+
206
+ # todo(mm, 2024-10-14): Does serial_number belong in LoadPipetteUpdate?
207
+ serial_number: str
208
+
209
+ config: pipette_data_provider.LoadedStaticPipetteData
210
+
211
+
212
+ @dataclasses.dataclass
213
+ class PipetteNozzleMapUpdate:
214
+ """Update pipette nozzle map."""
215
+
216
+ pipette_id: str
217
+ nozzle_map: NozzleMap
218
+
219
+
220
+ @dataclasses.dataclass
221
+ class PipetteTipStateUpdate:
222
+ """Update pipette tip state."""
223
+
224
+ pipette_id: str
225
+ tip_geometry: TipGeometry | None
226
+ tip_source: LabwareWellId | None
227
+
228
+
229
+ @dataclasses.dataclass
230
+ class PipetteAspirateReadyUpdate:
231
+ """Update pipette ready state."""
232
+
233
+ pipette_id: str
234
+ ready_to_aspirate: bool
235
+
236
+
237
+ @dataclasses.dataclass
238
+ class TipsUsedUpdate:
239
+ """Represents an update that marks tips in a tip rack as used."""
240
+
241
+ labware_id: str
242
+ """The labware ID of the tip rack."""
243
+
244
+ well_names: list[str]
245
+ """The exact wells in the tip rack that should be marked as used.
246
+
247
+ This is the *full* list, which is probably more than what appeared in the pickUpTip
248
+ command's params, for multi-channel reasons.
249
+ """
250
+
251
+
252
+ @dataclasses.dataclass
253
+ class LiquidLoadedUpdate:
254
+ """An update from loading a liquid."""
255
+
256
+ labware_id: str
257
+ volumes: typing.Dict[str, float]
258
+ last_loaded: datetime
259
+
260
+
261
+ @dataclasses.dataclass
262
+ class LiquidProbedUpdate:
263
+ """An update from probing a liquid."""
264
+
265
+ labware_id: str
266
+ well_name: str
267
+ last_probed: datetime
268
+ height: LiquidTrackingType | ClearType
269
+ volume: LiquidTrackingType | ClearType
270
+
271
+
272
+ @dataclasses.dataclass
273
+ class LiquidOperatedUpdate:
274
+ """An update from operating a liquid."""
275
+
276
+ labware_id: str
277
+ well_names: list[str]
278
+ volume_added: float | ClearType
279
+
280
+
281
+ @dataclasses.dataclass
282
+ class PipetteAspiratedFluidUpdate:
283
+ """Represents the pipette aspirating something. Might be air or liquid from a well."""
284
+
285
+ pipette_id: str
286
+ fluid: AspiratedFluid
287
+ type: typing.Literal["aspirated"] = "aspirated"
288
+
289
+
290
+ @dataclasses.dataclass
291
+ class PipetteEjectedFluidUpdate:
292
+ """Represents the pipette pushing something out. Might be air or liquid."""
293
+
294
+ pipette_id: str
295
+ volume: float
296
+ type: typing.Literal["ejected"] = "ejected"
297
+
298
+
299
+ @dataclasses.dataclass
300
+ class PipetteUnknownFluidUpdate:
301
+ """Represents the amount of fluid in the pipette becoming unknown."""
302
+
303
+ pipette_id: str
304
+ type: typing.Literal["unknown"] = "unknown"
305
+
306
+
307
+ @dataclasses.dataclass
308
+ class PipetteEmptyFluidUpdate:
309
+ """Sets the pipette to be valid and empty."""
310
+
311
+ pipette_id: str
312
+ clean_tip: bool
313
+ type: typing.Literal["empty"] = "empty"
314
+
315
+
316
+ @dataclasses.dataclass
317
+ class AbsorbanceReaderLidUpdate:
318
+ """An update to an absorbance reader's lid location."""
319
+
320
+ is_lid_on: bool
321
+
322
+
323
+ @dataclasses.dataclass
324
+ class AbsorbanceReaderDataUpdate:
325
+ """An update to an absorbance reader's lid location."""
326
+
327
+ read_result: typing.Dict[int, typing.Dict[str, float]]
328
+
329
+
330
+ @dataclasses.dataclass(frozen=True)
331
+ class AbsorbanceReaderInitializeUpdate:
332
+ """An update to an absorbance reader's initialization."""
333
+
334
+ measure_mode: ABSMeasureMode
335
+ sample_wave_lengths: typing.List[int]
336
+ reference_wave_length: typing.Optional[int]
337
+
338
+
339
+ @dataclasses.dataclass
340
+ class AbsorbanceReaderStateUpdate:
341
+ """An update to the absorbance reader module state."""
342
+
343
+ module_id: str
344
+ absorbance_reader_lid: AbsorbanceReaderLidUpdate | NoChangeType = NO_CHANGE
345
+ absorbance_reader_data: AbsorbanceReaderDataUpdate | NoChangeType = NO_CHANGE
346
+ initialize_absorbance_reader_update: (
347
+ AbsorbanceReaderInitializeUpdate | NoChangeType
348
+ ) = NO_CHANGE
349
+
350
+
351
+ @dataclasses.dataclass
352
+ class FlexStackerPoolConstraint:
353
+ """The labware definitions that are contained in the pool."""
354
+
355
+ max_pool_count: int
356
+ pool_overlap: float
357
+ pool_height: float
358
+ primary_definition: LabwareDefinition
359
+ lid_definition: LabwareDefinition | None
360
+ adapter_definition: LabwareDefinition | None
361
+
362
+
363
+ @dataclasses.dataclass
364
+ class FlexStackerStateUpdate:
365
+ """An update to the Flex Stacker module state."""
366
+
367
+ module_id: str
368
+ pool_constraint: FlexStackerPoolConstraint | NoChangeType = NO_CHANGE
369
+ contained_labware_bottom_first: list[
370
+ StackerStoredLabwareGroup
371
+ ] | NoChangeType = NO_CHANGE
372
+
373
+ @classmethod
374
+ def create_or_override(
375
+ cls,
376
+ maybe_inst: FlexStackerStateUpdate | NoChangeType,
377
+ module_id: str,
378
+ ) -> FlexStackerStateUpdate:
379
+ """Build or default a state update."""
380
+ if maybe_inst == NO_CHANGE:
381
+ return FlexStackerStateUpdate(module_id=module_id)
382
+ else:
383
+ return maybe_inst
384
+
385
+
386
+ @dataclasses.dataclass
387
+ class LiquidClassLoadedUpdate:
388
+ """The state update from loading a liquid class."""
389
+
390
+ liquid_class_id: str
391
+ liquid_class_record: LiquidClassRecord
392
+
393
+
394
+ @dataclasses.dataclass
395
+ class FilesAddedUpdate:
396
+ """An update that adds a new data file."""
397
+
398
+ file_ids: list[str]
399
+
400
+
401
+ @dataclasses.dataclass
402
+ class AddressableAreaUsedUpdate:
403
+ """An update that says an addressable area has been used."""
404
+
405
+ addressable_area_name: str
406
+
407
+
408
+ @dataclasses.dataclass
409
+ class LoadModuleUpdate:
410
+ """An update that loads a module."""
411
+
412
+ module_id: str
413
+ definition: ModuleDefinition
414
+ slot_name: DeckSlotName
415
+ requested_model: ModuleModel
416
+ serial_number: Optional[str]
417
+
418
+
419
+ @dataclasses.dataclass
420
+ class StateUpdate:
421
+ """Represents an update to perform on engine state."""
422
+
423
+ pipette_location: PipetteLocationUpdate | NoChangeType | ClearType = NO_CHANGE
424
+
425
+ loaded_pipette: LoadPipetteUpdate | NoChangeType = NO_CHANGE
426
+
427
+ loaded_module: LoadModuleUpdate | NoChangeType = NO_CHANGE
428
+
429
+ pipette_config: PipetteConfigUpdate | NoChangeType = NO_CHANGE
430
+
431
+ pipette_nozzle_map: PipetteNozzleMapUpdate | NoChangeType = NO_CHANGE
432
+
433
+ pipette_tip_state: PipetteTipStateUpdate | NoChangeType = NO_CHANGE
434
+
435
+ pipette_aspirated_fluid: (
436
+ PipetteAspiratedFluidUpdate
437
+ | PipetteEjectedFluidUpdate
438
+ | PipetteUnknownFluidUpdate
439
+ | PipetteEmptyFluidUpdate
440
+ | NoChangeType
441
+ ) = NO_CHANGE
442
+
443
+ labware_location: LabwareLocationUpdate | NoChangeType = NO_CHANGE
444
+
445
+ batch_labware_location: BatchLabwareLocationUpdate | NoChangeType = NO_CHANGE
446
+
447
+ loaded_labware: LoadedLabwareUpdate | NoChangeType = NO_CHANGE
448
+
449
+ batch_loaded_labware: BatchLoadedLabwareUpdate | NoChangeType = NO_CHANGE
450
+
451
+ loaded_lid_stack: LoadedLidStackUpdate | NoChangeType = NO_CHANGE
452
+
453
+ labware_lid: LabwareLidUpdate | NoChangeType = NO_CHANGE
454
+
455
+ tips_used: TipsUsedUpdate | NoChangeType = NO_CHANGE
456
+
457
+ liquid_loaded: LiquidLoadedUpdate | NoChangeType = NO_CHANGE
458
+
459
+ liquid_probed: LiquidProbedUpdate | NoChangeType = NO_CHANGE
460
+
461
+ liquid_operated: LiquidOperatedUpdate | NoChangeType = NO_CHANGE
462
+
463
+ absorbance_reader_state_update: AbsorbanceReaderStateUpdate | NoChangeType = (
464
+ NO_CHANGE
465
+ )
466
+
467
+ flex_stacker_state_update: FlexStackerStateUpdate | NoChangeType = NO_CHANGE
468
+
469
+ liquid_class_loaded: LiquidClassLoadedUpdate | NoChangeType = NO_CHANGE
470
+
471
+ files_added: FilesAddedUpdate | NoChangeType = NO_CHANGE
472
+
473
+ addressable_area_used: AddressableAreaUsedUpdate | NoChangeType = NO_CHANGE
474
+
475
+ ready_to_aspirate: PipetteAspirateReadyUpdate | NoChangeType = NO_CHANGE
476
+
477
+ def append(self, other: Self) -> Self:
478
+ """Apply another `StateUpdate` "on top of" this one.
479
+
480
+ This object is mutated in-place, taking values from `other`.
481
+ If an attribute in `other` is `NO_CHANGE`, the value in this object is kept.
482
+ """
483
+ fields = dataclasses.fields(other)
484
+ for field in fields:
485
+ other_value = other.__dict__[field.name]
486
+ if other_value != NO_CHANGE:
487
+ self.__dict__[field.name] = other_value
488
+ return self
489
+
490
+ @classmethod
491
+ def reduce(cls: typing.Type[Self], *args: Self) -> Self:
492
+ """Fuse multiple state updates into a single one.
493
+
494
+ State updates that are later in the parameter list are preferred to those that are earlier;
495
+ NO_CHANGE is ignored.
496
+ """
497
+ accumulator = cls()
498
+ for arg in args:
499
+ accumulator.append(arg)
500
+ return accumulator
501
+
502
+ # These convenience functions let the caller avoid the boilerplate of constructing a
503
+ # complicated dataclass tree, and allow chaining.
504
+
505
+ @typing.overload
506
+ def set_pipette_location(
507
+ self: Self, *, pipette_id: str, new_deck_point: DeckPoint
508
+ ) -> Self:
509
+ """Schedule a pipette's coordinates to be changed while preserving its logical location."""
510
+
511
+ @typing.overload
512
+ def set_pipette_location(
513
+ self: Self,
514
+ *,
515
+ pipette_id: str,
516
+ new_labware_id: str,
517
+ new_well_name: str,
518
+ new_deck_point: DeckPoint,
519
+ ) -> Self:
520
+ """Schedule a pipette's location to be set to a well."""
521
+
522
+ @typing.overload
523
+ def set_pipette_location(
524
+ self: Self,
525
+ *,
526
+ pipette_id: str,
527
+ new_addressable_area_name: str,
528
+ new_deck_point: DeckPoint,
529
+ ) -> Self:
530
+ """Schedule a pipette's location to be set to an addressable area."""
531
+ pass
532
+
533
+ def set_pipette_location( # noqa: D102
534
+ self: Self,
535
+ *,
536
+ pipette_id: str,
537
+ new_labware_id: str | NoChangeType = NO_CHANGE,
538
+ new_well_name: str | NoChangeType = NO_CHANGE,
539
+ new_addressable_area_name: str | NoChangeType = NO_CHANGE,
540
+ new_deck_point: DeckPoint,
541
+ ) -> Self:
542
+ if new_addressable_area_name != NO_CHANGE:
543
+ self.pipette_location = PipetteLocationUpdate(
544
+ pipette_id=pipette_id,
545
+ new_location=AddressableArea(
546
+ addressable_area_name=new_addressable_area_name
547
+ ),
548
+ new_deck_point=new_deck_point,
549
+ )
550
+ elif new_labware_id == NO_CHANGE or new_well_name == NO_CHANGE:
551
+ self.pipette_location = PipetteLocationUpdate(
552
+ pipette_id=pipette_id,
553
+ new_location=NO_CHANGE,
554
+ new_deck_point=new_deck_point,
555
+ )
556
+ else:
557
+ self.pipette_location = PipetteLocationUpdate(
558
+ pipette_id=pipette_id,
559
+ new_location=LabwareWellId(
560
+ labware_id=new_labware_id, well_name=new_well_name
561
+ ),
562
+ new_deck_point=new_deck_point,
563
+ )
564
+ return self
565
+
566
+ def clear_all_pipette_locations(self) -> Self:
567
+ """Mark all pipettes as having an unknown location."""
568
+ self.pipette_location = CLEAR
569
+ return self
570
+
571
+ def set_labware_location(
572
+ self: Self,
573
+ *,
574
+ labware_id: str,
575
+ new_location: LabwareLocation,
576
+ new_offset_id: str | None,
577
+ ) -> Self:
578
+ """Set a labware's location. See `LabwareLocationUpdate`."""
579
+ self.labware_location = LabwareLocationUpdate(
580
+ labware_id=labware_id,
581
+ new_location=new_location,
582
+ offset_id=new_offset_id,
583
+ )
584
+ return self
585
+
586
+ def set_batch_labware_location(
587
+ self: Self,
588
+ *,
589
+ new_locations_by_id: typing.Mapping[str, LabwareLocation],
590
+ new_offset_ids_by_id: typing.Mapping[str, str | None],
591
+ ) -> Self:
592
+ """Update the location of multiple labware objects."""
593
+ self.batch_labware_location = BatchLabwareLocationUpdate(
594
+ new_locations_by_id=dict(new_locations_by_id),
595
+ new_offset_ids_by_id=dict(new_offset_ids_by_id),
596
+ )
597
+ return self
598
+
599
+ def set_loaded_labware(
600
+ self: Self,
601
+ definition: LabwareDefinition,
602
+ labware_id: str,
603
+ offset_id: str | None,
604
+ display_name: str | None,
605
+ location: LabwareLocation,
606
+ ) -> Self:
607
+ """Add a new labware to state. See `LoadedLabwareUpdate`."""
608
+ self.loaded_labware = LoadedLabwareUpdate(
609
+ definition=definition,
610
+ labware_id=labware_id,
611
+ offset_id=offset_id,
612
+ new_location=location,
613
+ display_name=display_name,
614
+ )
615
+ return self
616
+
617
+ def set_batch_loaded_labware(
618
+ self: Self,
619
+ definitions_by_id: typing.Mapping[str, LabwareDefinition],
620
+ offset_ids_by_id: typing.Mapping[str, str | None],
621
+ display_names_by_id: typing.Mapping[str, str | None],
622
+ new_locations_by_id: typing.Mapping[str, LabwareLocation],
623
+ ) -> Self:
624
+ """Add a set of new labwares to state. See `BatchLoadedLabwareUpdate`."""
625
+ self.batch_loaded_labware = BatchLoadedLabwareUpdate(
626
+ new_locations_by_id=dict(new_locations_by_id),
627
+ offset_ids_by_id=dict(offset_ids_by_id),
628
+ display_names_by_id=dict(display_names_by_id),
629
+ definitions_by_id=dict(definitions_by_id),
630
+ )
631
+ return self
632
+
633
+ def set_loaded_lid_stack(
634
+ self: Self,
635
+ stack_id: str,
636
+ stack_object_definition: LabwareDefinition,
637
+ stack_location: LabwareLocation,
638
+ locations: typing.Dict[str, OnLabwareLocation],
639
+ labware_definition: LabwareDefinition | None,
640
+ ) -> Self:
641
+ """Add a new lid stack to state. See `LoadedLidStackUpdate`."""
642
+ self.loaded_lid_stack = LoadedLidStackUpdate(
643
+ stack_id=stack_id,
644
+ stack_object_definition=stack_object_definition,
645
+ stack_location=stack_location,
646
+ definition=labware_definition,
647
+ new_locations_by_id=locations,
648
+ )
649
+ return self
650
+
651
+ def set_lids(
652
+ self: Self,
653
+ parent_labware_ids: typing.Sequence[str],
654
+ lid_ids: typing.Sequence[str | None],
655
+ ) -> Self:
656
+ """Update the labware parent of a loaded or moved lid. See `LabwareLidUpdate`."""
657
+ self.labware_lid = LabwareLidUpdate(
658
+ parent_labware_ids=list(parent_labware_ids),
659
+ lid_ids=list(lid_ids),
660
+ )
661
+ return self
662
+
663
+ def set_load_pipette(
664
+ self: Self,
665
+ pipette_id: str,
666
+ pipette_name: PipetteNameType,
667
+ mount: MountType,
668
+ liquid_presence_detection: bool | None,
669
+ ) -> Self:
670
+ """Add a new pipette to state. See `LoadPipetteUpdate`."""
671
+ self.loaded_pipette = LoadPipetteUpdate(
672
+ pipette_id=pipette_id,
673
+ pipette_name=pipette_name,
674
+ mount=mount,
675
+ liquid_presence_detection=liquid_presence_detection,
676
+ )
677
+ return self
678
+
679
+ def set_load_module(
680
+ self: Self,
681
+ module_id: str,
682
+ definition: ModuleDefinition,
683
+ slot_name: DeckSlotName,
684
+ requested_model: ModuleModel,
685
+ serial_number: Optional[str],
686
+ ) -> Self:
687
+ """Add a new module to state. See `LoadModuleUpdate`."""
688
+ self.loaded_module = LoadModuleUpdate(
689
+ module_id=module_id,
690
+ definition=definition,
691
+ serial_number=serial_number,
692
+ slot_name=slot_name,
693
+ requested_model=requested_model,
694
+ )
695
+ return self
696
+
697
+ def update_pipette_config(
698
+ self: Self,
699
+ pipette_id: str,
700
+ config: pipette_data_provider.LoadedStaticPipetteData,
701
+ serial_number: str,
702
+ ) -> Self:
703
+ """Update a pipette's config. See `PipetteConfigUpdate`."""
704
+ self.pipette_config = PipetteConfigUpdate(
705
+ pipette_id=pipette_id, config=config, serial_number=serial_number
706
+ )
707
+ return self
708
+
709
+ def update_pipette_nozzle(
710
+ self: Self, pipette_id: str, nozzle_map: NozzleMap
711
+ ) -> Self:
712
+ """Update a pipette's nozzle map. See `PipetteNozzleMapUpdate`."""
713
+ self.pipette_nozzle_map = PipetteNozzleMapUpdate(
714
+ pipette_id=pipette_id, nozzle_map=nozzle_map
715
+ )
716
+ return self
717
+
718
+ def update_pipette_tip_state(
719
+ self: Self,
720
+ pipette_id: str,
721
+ tip_geometry: TipGeometry | None,
722
+ tip_source: LabwareWellId | None,
723
+ ) -> Self:
724
+ """Update a pipette's tip state. See `PipetteTipStateUpdate`."""
725
+ self.pipette_tip_state = PipetteTipStateUpdate(
726
+ pipette_id=pipette_id,
727
+ tip_geometry=tip_geometry,
728
+ tip_source=tip_source,
729
+ )
730
+ return self
731
+
732
+ def mark_tips_as_used(self: Self, labware_id: str, well_names: list[str]) -> Self:
733
+ """Mark tips in a tip rack as used. See `TipsUsedUpdate`."""
734
+ self.tips_used = TipsUsedUpdate(labware_id=labware_id, well_names=well_names)
735
+ return self
736
+
737
+ def set_liquid_loaded(
738
+ self: Self,
739
+ labware_id: str,
740
+ volumes: typing.Dict[str, float],
741
+ last_loaded: datetime,
742
+ ) -> Self:
743
+ """Add liquid volumes to well state. See `LoadLiquidUpdate`."""
744
+ self.liquid_loaded = LiquidLoadedUpdate(
745
+ labware_id=labware_id,
746
+ volumes=volumes,
747
+ last_loaded=last_loaded,
748
+ )
749
+ return self
750
+
751
+ def set_liquid_probed(
752
+ self: Self,
753
+ labware_id: str,
754
+ well_name: str,
755
+ last_probed: datetime,
756
+ height: LiquidTrackingType | ClearType,
757
+ volume: LiquidTrackingType | ClearType,
758
+ ) -> Self:
759
+ """Add a liquid height and volume to well state. See `ProbeLiquidUpdate`."""
760
+ self.liquid_probed = LiquidProbedUpdate(
761
+ labware_id=labware_id,
762
+ well_name=well_name,
763
+ height=height,
764
+ volume=volume,
765
+ last_probed=last_probed,
766
+ )
767
+ return self
768
+
769
+ def set_liquid_operated(
770
+ self: Self,
771
+ labware_id: str,
772
+ well_names: list[str],
773
+ volume_added: float | ClearType,
774
+ ) -> Self:
775
+ """Update liquid volumes in well state. See `OperateLiquidUpdate`."""
776
+ self.liquid_operated = LiquidOperatedUpdate(
777
+ labware_id=labware_id,
778
+ well_names=well_names,
779
+ volume_added=volume_added,
780
+ )
781
+ return self
782
+
783
+ def set_fluid_aspirated(self: Self, pipette_id: str, fluid: AspiratedFluid) -> Self:
784
+ """Update record of fluid held inside a pipette. See `PipetteAspiratedFluidUpdate`."""
785
+ self.pipette_aspirated_fluid = PipetteAspiratedFluidUpdate(
786
+ type="aspirated", pipette_id=pipette_id, fluid=fluid
787
+ )
788
+ return self
789
+
790
+ def set_fluid_ejected(self: Self, pipette_id: str, volume: float) -> Self:
791
+ """Update record of fluid held inside a pipette. See `PipetteEjectedFluidUpdate`."""
792
+ self.pipette_aspirated_fluid = PipetteEjectedFluidUpdate(
793
+ type="ejected", pipette_id=pipette_id, volume=volume
794
+ )
795
+ return self
796
+
797
+ def set_fluid_unknown(self: Self, pipette_id: str) -> Self:
798
+ """Update record of fluid held inside a pipette. See `PipetteUnknownFluidUpdate`."""
799
+ self.pipette_aspirated_fluid = PipetteUnknownFluidUpdate(
800
+ type="unknown", pipette_id=pipette_id
801
+ )
802
+ return self
803
+
804
+ def set_fluid_empty(self: Self, pipette_id: str, clean_tip: bool = False) -> Self:
805
+ """Update record of fluid held inside a pipette. See `PipetteEmptyFluidUpdate`."""
806
+ self.pipette_aspirated_fluid = PipetteEmptyFluidUpdate(
807
+ type="empty", pipette_id=pipette_id, clean_tip=clean_tip
808
+ )
809
+ return self
810
+
811
+ def set_absorbance_reader_lid(self: Self, module_id: str, is_lid_on: bool) -> Self:
812
+ """Update an absorbance reader's lid location. See `AbsorbanceReaderLidUpdate`."""
813
+ assert self.absorbance_reader_state_update == NO_CHANGE
814
+ self.absorbance_reader_state_update = AbsorbanceReaderStateUpdate(
815
+ module_id=module_id,
816
+ absorbance_reader_lid=AbsorbanceReaderLidUpdate(is_lid_on=is_lid_on),
817
+ )
818
+ return self
819
+
820
+ def set_absorbance_reader_data(
821
+ self, module_id: str, read_result: typing.Dict[int, typing.Dict[str, float]]
822
+ ) -> Self:
823
+ """Update an absorbance reader's read data. See `AbsorbanceReaderReadDataUpdate`."""
824
+ assert self.absorbance_reader_state_update == NO_CHANGE
825
+ self.absorbance_reader_state_update = AbsorbanceReaderStateUpdate(
826
+ module_id=module_id,
827
+ absorbance_reader_data=AbsorbanceReaderDataUpdate(read_result=read_result),
828
+ )
829
+ return self
830
+
831
+ def initialize_absorbance_reader(
832
+ self,
833
+ module_id: str,
834
+ measure_mode: ABSMeasureMode,
835
+ sample_wave_lengths: typing.List[int],
836
+ reference_wave_length: typing.Optional[int],
837
+ ) -> Self:
838
+ """Initialize absorbance reader."""
839
+ assert self.absorbance_reader_state_update == NO_CHANGE
840
+ self.absorbance_reader_state_update = AbsorbanceReaderStateUpdate(
841
+ module_id=module_id,
842
+ initialize_absorbance_reader_update=AbsorbanceReaderInitializeUpdate(
843
+ measure_mode=measure_mode,
844
+ sample_wave_lengths=sample_wave_lengths,
845
+ reference_wave_length=reference_wave_length,
846
+ ),
847
+ )
848
+ return self
849
+
850
+ def set_addressable_area_used(self: Self, addressable_area_name: str) -> Self:
851
+ """Mark that an addressable area has been used. See `AddressableAreaUsedUpdate`."""
852
+ self.addressable_area_used = AddressableAreaUsedUpdate(
853
+ addressable_area_name=addressable_area_name
854
+ )
855
+ return self
856
+
857
+ def update_flex_stacker_labware_pool_definition(
858
+ self,
859
+ module_id: str,
860
+ max_count: int,
861
+ pool_overlap: float,
862
+ pool_height: float,
863
+ primary_definition: LabwareDefinition,
864
+ adapter_definition: LabwareDefinition | None,
865
+ lid_definition: LabwareDefinition | None,
866
+ ) -> Self:
867
+ """Constrain the labware pool to a specific definition."""
868
+ self.flex_stacker_state_update = dataclasses.replace(
869
+ FlexStackerStateUpdate.create_or_override(
870
+ self.flex_stacker_state_update, module_id
871
+ ),
872
+ pool_constraint=FlexStackerPoolConstraint(
873
+ max_pool_count=max_count,
874
+ pool_overlap=pool_overlap,
875
+ pool_height=pool_height,
876
+ primary_definition=primary_definition,
877
+ lid_definition=lid_definition,
878
+ adapter_definition=adapter_definition,
879
+ ),
880
+ )
881
+ return self
882
+
883
+ def update_flex_stacker_contained_labware(
884
+ self,
885
+ module_id: str,
886
+ contained_labware_bottom_first: list[StackerStoredLabwareGroup],
887
+ ) -> Self:
888
+ """Set the labware pool to a specific count."""
889
+ self.flex_stacker_state_update = dataclasses.replace(
890
+ FlexStackerStateUpdate.create_or_override(
891
+ self.flex_stacker_state_update, module_id
892
+ ),
893
+ contained_labware_bottom_first=contained_labware_bottom_first,
894
+ )
895
+ return self
896
+
897
+ def set_pipette_ready_to_aspirate(
898
+ self, pipette_id: str, ready_to_aspirate: bool
899
+ ) -> Self:
900
+ """Set the ready to aspirate state for a pipette."""
901
+ self.ready_to_aspirate = PipetteAspirateReadyUpdate(
902
+ pipette_id=pipette_id, ready_to_aspirate=ready_to_aspirate
903
+ )
904
+ return self