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,814 @@
1
+ from dataclasses import dataclass
2
+ from numpy import interp
3
+ from typing import Optional, Dict, Sequence, Tuple, List, Union
4
+
5
+ from opentrons_shared_data.liquid_classes.liquid_class_definition import (
6
+ TransferProperties as SharedDataTransferProperties,
7
+ AspirateProperties as SharedDataAspirateProperties,
8
+ SingleDispenseProperties as SharedDataSingleDispenseProperties,
9
+ MultiDispenseProperties as SharedDataMultiDispenseProperties,
10
+ TipPosition as SharedDataTipPosition,
11
+ DelayProperties as SharedDataDelayProperties,
12
+ DelayParams as SharedDataDelayParams,
13
+ TouchTipProperties as SharedDataTouchTipProperties,
14
+ LiquidClassTouchTipParams as SharedDataTouchTipParams,
15
+ MixProperties as SharedDataMixProperties,
16
+ MixParams as SharedDataMixParams,
17
+ BlowoutProperties as SharedDataBlowoutProperties,
18
+ BlowoutParams as SharedDataBlowoutParams,
19
+ ByTipTypeSetting as SharedByTipTypeSetting,
20
+ Submerge as SharedDataSubmerge,
21
+ RetractAspirate as SharedDataRetractAspirate,
22
+ RetractDispense as SharedDataRetractDispense,
23
+ BlowoutLocation,
24
+ PositionReference,
25
+ Coordinate,
26
+ )
27
+ from . import validation
28
+
29
+
30
+ class LiquidHandlingPropertyByVolume:
31
+ def __init__(self, by_volume_property: Sequence[Tuple[float, float]]) -> None:
32
+ self._initial_properties_by_volume = by_volume_property
33
+ self._properties_by_volume: Dict[float, float] = {
34
+ float(volume): value for volume, value in by_volume_property
35
+ }
36
+ # Volumes need to be sorted for proper interpolation of non-defined volumes, and the
37
+ # corresponding values need to be in the same order for them to be interpolated correctly
38
+ self._sorted_volumes: Tuple[float, ...] = ()
39
+ self._sorted_values: Tuple[float, ...] = ()
40
+ self._sort_volume_and_values()
41
+
42
+ def as_dict(self) -> Dict[float, float]:
43
+ """Get a dictionary representation of all set volumes and values along with the default."""
44
+ return self._properties_by_volume
45
+
46
+ def as_list_of_tuples(self) -> List[Tuple[float, float]]:
47
+ """Get as list of tuples."""
48
+ return list(self._properties_by_volume.items())
49
+
50
+ def get_for_volume(self, volume: float) -> float:
51
+ """Get a value by volume for this property. Volumes not defined will be interpolated between set volumes."""
52
+ validated_volume = validation.ensure_positive_float(volume)
53
+ if len(self._properties_by_volume) == 0:
54
+ raise ValueError(
55
+ "No properties found for any volumes. Cannot interpolate for the given volume."
56
+ )
57
+ try:
58
+ return self._properties_by_volume[validated_volume]
59
+ except KeyError:
60
+ # If volume is not defined in dictionary, do a piecewise interpolation with existing sorted values
61
+ return float(
62
+ interp(validated_volume, self._sorted_volumes, self._sorted_values)
63
+ )
64
+
65
+ def set_for_all_volumes(self, value: float) -> None:
66
+ """Override all existing volume-dependent values with the given value."""
67
+ self.clear_values()
68
+ self.set_for_volume(0, value)
69
+
70
+ def set_for_volume(self, volume: float, value: float) -> None:
71
+ """Add a new volume and value for the property for the interpolation curve."""
72
+ validated_volume = validation.ensure_positive_float(volume)
73
+ self._properties_by_volume[validated_volume] = value
74
+ self._sort_volume_and_values()
75
+
76
+ def delete_for_volume(self, volume: float) -> None:
77
+ """Remove an existing volume and value from the property."""
78
+ try:
79
+ del self._properties_by_volume[volume]
80
+ except KeyError:
81
+ raise KeyError(f"No value set for volume {volume} uL")
82
+ self._sort_volume_and_values()
83
+
84
+ def clear_values(self) -> None:
85
+ """Removes all existing volume and value pairs from the curve."""
86
+ self._properties_by_volume = {}
87
+
88
+ def reset_values(self) -> None:
89
+ """Resets volumes and values to the default."""
90
+ self._properties_by_volume = {
91
+ float(volume): value for volume, value in self._initial_properties_by_volume
92
+ }
93
+ self._sort_volume_and_values()
94
+
95
+ def _sort_volume_and_values(self) -> None:
96
+ """Sort volume in increasing order along with corresponding values in matching order."""
97
+ self._sorted_volumes, self._sorted_values = (
98
+ zip(*sorted(self._properties_by_volume.items()))
99
+ if len(self._properties_by_volume) > 0
100
+ else [(), ()]
101
+ )
102
+
103
+
104
+ # We use slots for this dataclass (and the rest of liquid properties) to prevent dynamic creation of attributes
105
+ # not defined in the class, not for any performance reasons. This is so that mistyping properties when overriding
106
+ # values will cause the protocol to fail analysis, rather than silently passing.
107
+ @dataclass(slots=True)
108
+ class TipPosition:
109
+
110
+ _position_reference: PositionReference
111
+ _offset: Coordinate
112
+
113
+ @property
114
+ def position_reference(self) -> PositionReference:
115
+ return self._position_reference
116
+
117
+ @position_reference.setter
118
+ def position_reference(self, new_position: Union[str, PositionReference]) -> None:
119
+ self._position_reference = (
120
+ new_position
121
+ if isinstance(new_position, PositionReference)
122
+ else PositionReference(new_position)
123
+ )
124
+
125
+ @property
126
+ def offset(self) -> Coordinate:
127
+ return self._offset
128
+
129
+ @offset.setter
130
+ def offset(self, new_offset: Union[Sequence[float], Coordinate]) -> None:
131
+ if isinstance(new_offset, Coordinate):
132
+ new_coordinate: Sequence[Union[int, float]] = [
133
+ new_offset.x,
134
+ new_offset.y,
135
+ new_offset.z,
136
+ ]
137
+ else:
138
+ new_coordinate = new_offset
139
+ x, y, z = validation.validate_coordinates(new_coordinate)
140
+ self._offset = Coordinate(x=x, y=y, z=z)
141
+
142
+ def as_shared_data_model(self) -> SharedDataTipPosition:
143
+ return SharedDataTipPosition(
144
+ positionReference=self._position_reference,
145
+ offset=self.offset,
146
+ )
147
+
148
+
149
+ @dataclass(slots=True)
150
+ class DelayProperties:
151
+
152
+ _enabled: bool
153
+ _duration: Optional[float]
154
+
155
+ @property
156
+ def enabled(self) -> bool:
157
+ return self._enabled
158
+
159
+ @enabled.setter
160
+ def enabled(self, enable: bool) -> None:
161
+ validated_enable = validation.ensure_boolean(enable)
162
+ if validated_enable and self._duration is None:
163
+ raise ValueError("duration must be set before enabling delay.")
164
+ self._enabled = validated_enable
165
+
166
+ @property
167
+ def duration(self) -> Optional[float]:
168
+ return self._duration
169
+
170
+ @duration.setter
171
+ def duration(self, new_duration: float) -> None:
172
+ validated_duration = validation.ensure_positive_float(new_duration)
173
+ self._duration = validated_duration
174
+
175
+ def as_shared_data_model(self) -> SharedDataDelayProperties:
176
+ return SharedDataDelayProperties(
177
+ enable=self._enabled,
178
+ params=SharedDataDelayParams(duration=self.duration)
179
+ if self.duration is not None
180
+ else None,
181
+ )
182
+
183
+
184
+ @dataclass(slots=True)
185
+ class TouchTipProperties:
186
+
187
+ _enabled: bool
188
+ _z_offset: Optional[float]
189
+ _mm_from_edge: Optional[float]
190
+ _speed: Optional[float]
191
+
192
+ @property
193
+ def enabled(self) -> bool:
194
+ return self._enabled
195
+
196
+ @enabled.setter
197
+ def enabled(self, enable: bool) -> None:
198
+ validated_enable = validation.ensure_boolean(enable)
199
+ if validated_enable and (
200
+ self._z_offset is None or self._mm_from_edge is None or self._speed is None
201
+ ):
202
+ raise ValueError(
203
+ "z_offset, mm_from_edge and speed must be set before enabling touch tip."
204
+ )
205
+ self._enabled = validated_enable
206
+
207
+ @property
208
+ def z_offset(self) -> Optional[float]:
209
+ return self._z_offset
210
+
211
+ @z_offset.setter
212
+ def z_offset(self, new_offset: float) -> None:
213
+ validated_offset = validation.ensure_float(new_offset)
214
+ self._z_offset = validated_offset
215
+
216
+ @property
217
+ def mm_from_edge(self) -> Optional[float]:
218
+ return self._mm_from_edge
219
+
220
+ @mm_from_edge.setter
221
+ def mm_from_edge(self, new_mm: float) -> None:
222
+ validated_mm = validation.ensure_float(new_mm)
223
+ self._mm_from_edge = validated_mm
224
+
225
+ @property
226
+ def speed(self) -> Optional[float]:
227
+ return self._speed
228
+
229
+ @speed.setter
230
+ def speed(self, new_speed: float) -> None:
231
+ validated_speed = validation.ensure_greater_than_zero_float(new_speed)
232
+ self._speed = validated_speed
233
+
234
+ def _get_shared_data_params(self) -> Optional[SharedDataTouchTipParams]:
235
+ """Get the touch tip params in schema v1 shape."""
236
+ if (
237
+ self._z_offset is not None
238
+ and self._mm_from_edge is not None
239
+ and self._speed is not None
240
+ ):
241
+ return SharedDataTouchTipParams(
242
+ zOffset=self._z_offset,
243
+ mmFromEdge=self._mm_from_edge,
244
+ speed=self._speed,
245
+ )
246
+ else:
247
+ return None
248
+
249
+ def as_shared_data_model(self) -> SharedDataTouchTipProperties:
250
+ return SharedDataTouchTipProperties(
251
+ enable=self._enabled,
252
+ params=self._get_shared_data_params(),
253
+ )
254
+
255
+
256
+ @dataclass(slots=True)
257
+ class MixProperties:
258
+
259
+ _enabled: bool
260
+ _repetitions: Optional[int]
261
+ _volume: Optional[float]
262
+
263
+ @property
264
+ def enabled(self) -> bool:
265
+ return self._enabled
266
+
267
+ @enabled.setter
268
+ def enabled(self, enable: bool) -> None:
269
+ validated_enable = validation.ensure_boolean(enable)
270
+ if validated_enable and (self._repetitions is None or self._volume is None):
271
+ raise ValueError("repetitions and volume must be set before enabling mix.")
272
+ self._enabled = validated_enable
273
+
274
+ @property
275
+ def repetitions(self) -> Optional[int]:
276
+ return self._repetitions
277
+
278
+ @repetitions.setter
279
+ def repetitions(self, new_repetitions: int) -> None:
280
+ validated_repetitions = validation.ensure_positive_int(new_repetitions)
281
+ self._repetitions = validated_repetitions
282
+
283
+ @property
284
+ def volume(self) -> Optional[float]:
285
+ return self._volume
286
+
287
+ @volume.setter
288
+ def volume(self, new_volume: float) -> None:
289
+ validated_volume = validation.ensure_greater_than_zero_float(new_volume)
290
+ self._volume = validated_volume
291
+
292
+ def _get_shared_data_params(self) -> Optional[SharedDataMixParams]:
293
+ """Get the mix params in schema v1 shape."""
294
+ if self._repetitions is not None and self._volume is not None:
295
+ return SharedDataMixParams(
296
+ repetitions=self._repetitions,
297
+ volume=self._volume,
298
+ )
299
+ else:
300
+ return None
301
+
302
+ def as_shared_data_model(self) -> SharedDataMixProperties:
303
+ return SharedDataMixProperties(
304
+ enable=self._enabled,
305
+ params=self._get_shared_data_params(),
306
+ )
307
+
308
+
309
+ @dataclass(slots=True)
310
+ class BlowoutProperties:
311
+
312
+ _enabled: bool
313
+ _location: Optional[BlowoutLocation]
314
+ _flow_rate: Optional[float]
315
+
316
+ @property
317
+ def enabled(self) -> bool:
318
+ return self._enabled
319
+
320
+ @enabled.setter
321
+ def enabled(self, enable: bool) -> None:
322
+ validated_enable = validation.ensure_boolean(enable)
323
+ if validated_enable and (self._location is None or self._flow_rate is None):
324
+ raise ValueError(
325
+ "location and flow_rate must be set before enabling blowout."
326
+ )
327
+ self._enabled = validated_enable
328
+
329
+ @property
330
+ def location(self) -> Optional[BlowoutLocation]:
331
+ return self._location
332
+
333
+ @location.setter
334
+ def location(self, new_location: str) -> None:
335
+ self._location = BlowoutLocation(new_location)
336
+
337
+ @property
338
+ def flow_rate(self) -> Optional[float]:
339
+ return self._flow_rate
340
+
341
+ @flow_rate.setter
342
+ def flow_rate(self, new_flow_rate: float) -> None:
343
+ validated_flow_rate = validation.ensure_greater_than_zero_float(new_flow_rate)
344
+ self._flow_rate = validated_flow_rate
345
+
346
+ def _get_shared_data_params(self) -> Optional[SharedDataBlowoutParams]:
347
+ """Get the mix params in schema v1 shape."""
348
+ if self._location is not None and self._flow_rate is not None:
349
+ return SharedDataBlowoutParams(
350
+ location=self._location,
351
+ flowRate=self._flow_rate,
352
+ )
353
+ else:
354
+ return None
355
+
356
+ def as_shared_data_model(self) -> SharedDataBlowoutProperties:
357
+ return SharedDataBlowoutProperties(
358
+ enable=self._enabled,
359
+ params=self._get_shared_data_params(),
360
+ )
361
+
362
+
363
+ @dataclass(slots=True)
364
+ class _SubmergeRetractCommon:
365
+
366
+ _speed: float
367
+ _delay: DelayProperties
368
+
369
+ @property
370
+ def speed(self) -> float:
371
+ return self._speed
372
+
373
+ @speed.setter
374
+ def speed(self, new_speed: float) -> None:
375
+ validated_speed = validation.ensure_positive_float(new_speed)
376
+ self._speed = validated_speed
377
+
378
+ @property
379
+ def delay(self) -> DelayProperties:
380
+ return self._delay
381
+
382
+
383
+ @dataclass(slots=True)
384
+ class Submerge(_SubmergeRetractCommon):
385
+
386
+ _start_position: TipPosition
387
+
388
+ @property
389
+ def start_position(self) -> TipPosition:
390
+ return self._start_position
391
+
392
+ def as_shared_data_model(self) -> SharedDataSubmerge:
393
+ return SharedDataSubmerge(
394
+ startPosition=self._start_position.as_shared_data_model(),
395
+ speed=self._speed,
396
+ delay=self._delay.as_shared_data_model(),
397
+ )
398
+
399
+
400
+ @dataclass(slots=True)
401
+ class RetractAspirate(_SubmergeRetractCommon):
402
+
403
+ _end_position: TipPosition
404
+ _air_gap_by_volume: LiquidHandlingPropertyByVolume
405
+ _touch_tip: TouchTipProperties
406
+
407
+ @property
408
+ def end_position(self) -> TipPosition:
409
+ return self._end_position
410
+
411
+ @property
412
+ def air_gap_by_volume(self) -> LiquidHandlingPropertyByVolume:
413
+ return self._air_gap_by_volume
414
+
415
+ @property
416
+ def touch_tip(self) -> TouchTipProperties:
417
+ return self._touch_tip
418
+
419
+ def as_shared_data_model(self) -> SharedDataRetractAspirate:
420
+ return SharedDataRetractAspirate(
421
+ endPosition=self._end_position.as_shared_data_model(),
422
+ speed=self._speed,
423
+ airGapByVolume=self._air_gap_by_volume.as_list_of_tuples(),
424
+ touchTip=self._touch_tip.as_shared_data_model(),
425
+ delay=self._delay.as_shared_data_model(),
426
+ )
427
+
428
+
429
+ @dataclass(slots=True)
430
+ class RetractDispense(_SubmergeRetractCommon):
431
+ _end_position: TipPosition
432
+ _air_gap_by_volume: LiquidHandlingPropertyByVolume
433
+ _touch_tip: TouchTipProperties
434
+ _blowout: BlowoutProperties
435
+
436
+ @property
437
+ def end_position(self) -> TipPosition:
438
+ return self._end_position
439
+
440
+ @property
441
+ def air_gap_by_volume(self) -> LiquidHandlingPropertyByVolume:
442
+ return self._air_gap_by_volume
443
+
444
+ @property
445
+ def touch_tip(self) -> TouchTipProperties:
446
+ return self._touch_tip
447
+
448
+ @property
449
+ def blowout(self) -> BlowoutProperties:
450
+ return self._blowout
451
+
452
+ def as_shared_data_model(self) -> SharedDataRetractDispense:
453
+ return SharedDataRetractDispense(
454
+ endPosition=self._end_position.as_shared_data_model(),
455
+ speed=self._speed,
456
+ airGapByVolume=self._air_gap_by_volume.as_list_of_tuples(),
457
+ blowout=self._blowout.as_shared_data_model(),
458
+ touchTip=self._touch_tip.as_shared_data_model(),
459
+ delay=self._delay.as_shared_data_model(),
460
+ )
461
+
462
+
463
+ @dataclass(slots=True)
464
+ class _BaseLiquidHandlingProperties:
465
+
466
+ _submerge: Submerge
467
+ _flow_rate_by_volume: LiquidHandlingPropertyByVolume
468
+ _correction_by_volume: LiquidHandlingPropertyByVolume
469
+ _delay: DelayProperties
470
+
471
+ @property
472
+ def submerge(self) -> Submerge:
473
+ return self._submerge
474
+
475
+ @property
476
+ def flow_rate_by_volume(self) -> LiquidHandlingPropertyByVolume:
477
+ return self._flow_rate_by_volume
478
+
479
+ @property
480
+ def correction_by_volume(self) -> LiquidHandlingPropertyByVolume:
481
+ return self._correction_by_volume
482
+
483
+ @property
484
+ def delay(self) -> DelayProperties:
485
+ return self._delay
486
+
487
+
488
+ @dataclass(slots=True)
489
+ class AspirateProperties(_BaseLiquidHandlingProperties):
490
+
491
+ _aspirate_position: TipPosition
492
+ _retract: RetractAspirate
493
+ _pre_wet: bool
494
+ _mix: MixProperties
495
+
496
+ @property
497
+ def aspirate_position(self) -> TipPosition:
498
+ return self._aspirate_position
499
+
500
+ @property
501
+ def pre_wet(self) -> bool:
502
+ return self._pre_wet
503
+
504
+ @pre_wet.setter
505
+ def pre_wet(self, new_setting: bool) -> None:
506
+ validated_setting = validation.ensure_boolean(new_setting)
507
+ self._pre_wet = validated_setting
508
+
509
+ @property
510
+ def retract(self) -> RetractAspirate:
511
+ return self._retract
512
+
513
+ @property
514
+ def mix(self) -> MixProperties:
515
+ return self._mix
516
+
517
+ def as_shared_data_model(self) -> SharedDataAspirateProperties:
518
+ return SharedDataAspirateProperties(
519
+ submerge=self._submerge.as_shared_data_model(),
520
+ retract=self._retract.as_shared_data_model(),
521
+ aspiratePosition=self._aspirate_position.as_shared_data_model(),
522
+ flowRateByVolume=self._flow_rate_by_volume.as_list_of_tuples(),
523
+ preWet=self._pre_wet,
524
+ mix=self._mix.as_shared_data_model(),
525
+ delay=self._delay.as_shared_data_model(),
526
+ correctionByVolume=self._correction_by_volume.as_list_of_tuples(),
527
+ )
528
+
529
+
530
+ @dataclass(slots=True)
531
+ class SingleDispenseProperties(_BaseLiquidHandlingProperties):
532
+
533
+ _dispense_position: TipPosition
534
+ _retract: RetractDispense
535
+ _push_out_by_volume: LiquidHandlingPropertyByVolume
536
+ _mix: MixProperties
537
+
538
+ @property
539
+ def dispense_position(self) -> TipPosition:
540
+ return self._dispense_position
541
+
542
+ @property
543
+ def push_out_by_volume(self) -> LiquidHandlingPropertyByVolume:
544
+ return self._push_out_by_volume
545
+
546
+ @property
547
+ def retract(self) -> RetractDispense:
548
+ return self._retract
549
+
550
+ @property
551
+ def mix(self) -> MixProperties:
552
+ return self._mix
553
+
554
+ def as_shared_data_model(self) -> SharedDataSingleDispenseProperties:
555
+ return SharedDataSingleDispenseProperties(
556
+ submerge=self._submerge.as_shared_data_model(),
557
+ retract=self._retract.as_shared_data_model(),
558
+ dispensePosition=self._dispense_position.as_shared_data_model(),
559
+ flowRateByVolume=self._flow_rate_by_volume.as_list_of_tuples(),
560
+ mix=self._mix.as_shared_data_model(),
561
+ pushOutByVolume=self._push_out_by_volume.as_list_of_tuples(),
562
+ delay=self._delay.as_shared_data_model(),
563
+ correctionByVolume=self._correction_by_volume.as_list_of_tuples(),
564
+ )
565
+
566
+
567
+ @dataclass(slots=True)
568
+ class MultiDispenseProperties(_BaseLiquidHandlingProperties):
569
+
570
+ _dispense_position: TipPosition
571
+ _retract: RetractDispense
572
+ _conditioning_by_volume: LiquidHandlingPropertyByVolume
573
+ _disposal_by_volume: LiquidHandlingPropertyByVolume
574
+
575
+ @property
576
+ def dispense_position(self) -> TipPosition:
577
+ return self._dispense_position
578
+
579
+ @property
580
+ def retract(self) -> RetractDispense:
581
+ return self._retract
582
+
583
+ @property
584
+ def conditioning_by_volume(self) -> LiquidHandlingPropertyByVolume:
585
+ return self._conditioning_by_volume
586
+
587
+ @property
588
+ def disposal_by_volume(self) -> LiquidHandlingPropertyByVolume:
589
+ return self._disposal_by_volume
590
+
591
+ def as_shared_data_model(self) -> SharedDataMultiDispenseProperties:
592
+ return SharedDataMultiDispenseProperties(
593
+ submerge=self._submerge.as_shared_data_model(),
594
+ retract=self._retract.as_shared_data_model(),
595
+ dispensePosition=self._dispense_position.as_shared_data_model(),
596
+ flowRateByVolume=self._flow_rate_by_volume.as_list_of_tuples(),
597
+ conditioningByVolume=self._conditioning_by_volume.as_list_of_tuples(),
598
+ disposalByVolume=self._disposal_by_volume.as_list_of_tuples(),
599
+ delay=self._delay.as_shared_data_model(),
600
+ correctionByVolume=self._correction_by_volume.as_list_of_tuples(),
601
+ )
602
+
603
+
604
+ @dataclass(slots=True)
605
+ class TransferProperties:
606
+ _aspirate: AspirateProperties
607
+ _dispense: SingleDispenseProperties
608
+ _multi_dispense: Optional[MultiDispenseProperties]
609
+
610
+ @property
611
+ def aspirate(self) -> AspirateProperties:
612
+ """Aspirate properties."""
613
+ return self._aspirate
614
+
615
+ @property
616
+ def dispense(self) -> SingleDispenseProperties:
617
+ """Single dispense properties."""
618
+ return self._dispense
619
+
620
+ @property
621
+ def multi_dispense(self) -> Optional[MultiDispenseProperties]:
622
+ """Multi dispense properties."""
623
+ return self._multi_dispense
624
+
625
+
626
+ def _build_tip_position(tip_position: SharedDataTipPosition) -> TipPosition:
627
+ return TipPosition(
628
+ _position_reference=tip_position.positionReference, _offset=tip_position.offset
629
+ )
630
+
631
+
632
+ def _build_delay_properties(
633
+ delay_properties: SharedDataDelayProperties,
634
+ ) -> DelayProperties:
635
+ if delay_properties.params is not None:
636
+ duration = delay_properties.params.duration
637
+ else:
638
+ duration = None
639
+ return DelayProperties(_enabled=delay_properties.enable, _duration=duration)
640
+
641
+
642
+ def _build_touch_tip_properties(
643
+ touch_tip_properties: SharedDataTouchTipProperties,
644
+ ) -> TouchTipProperties:
645
+ if touch_tip_properties.params is not None:
646
+ z_offset = touch_tip_properties.params.zOffset
647
+ mm_from_edge = touch_tip_properties.params.mmFromEdge
648
+ speed = touch_tip_properties.params.speed
649
+ else:
650
+ z_offset = None
651
+ mm_from_edge = None
652
+ speed = None
653
+ return TouchTipProperties(
654
+ _enabled=touch_tip_properties.enable,
655
+ _z_offset=z_offset,
656
+ _mm_from_edge=mm_from_edge,
657
+ _speed=speed,
658
+ )
659
+
660
+
661
+ def _build_mix_properties(
662
+ mix_properties: SharedDataMixProperties,
663
+ ) -> MixProperties:
664
+ if mix_properties.params is not None:
665
+ repetitions = mix_properties.params.repetitions
666
+ volume = mix_properties.params.volume
667
+ else:
668
+ repetitions = None
669
+ volume = None
670
+ return MixProperties(
671
+ _enabled=mix_properties.enable, _repetitions=repetitions, _volume=volume
672
+ )
673
+
674
+
675
+ def _build_blowout_properties(
676
+ blowout_properties: SharedDataBlowoutProperties,
677
+ ) -> BlowoutProperties:
678
+ if blowout_properties.params is not None:
679
+ location = blowout_properties.params.location
680
+ flow_rate = blowout_properties.params.flowRate
681
+ else:
682
+ location = None
683
+ flow_rate = None
684
+ return BlowoutProperties(
685
+ _enabled=blowout_properties.enable, _location=location, _flow_rate=flow_rate
686
+ )
687
+
688
+
689
+ def _build_submerge(
690
+ submerge_properties: SharedDataSubmerge,
691
+ ) -> Submerge:
692
+ return Submerge(
693
+ _start_position=_build_tip_position(submerge_properties.startPosition),
694
+ _speed=submerge_properties.speed,
695
+ _delay=_build_delay_properties(submerge_properties.delay),
696
+ )
697
+
698
+
699
+ def _build_retract_aspirate(
700
+ retract_aspirate: SharedDataRetractAspirate,
701
+ ) -> RetractAspirate:
702
+ return RetractAspirate(
703
+ _end_position=_build_tip_position(retract_aspirate.endPosition),
704
+ _speed=retract_aspirate.speed,
705
+ _air_gap_by_volume=LiquidHandlingPropertyByVolume(
706
+ retract_aspirate.airGapByVolume
707
+ ),
708
+ _touch_tip=_build_touch_tip_properties(retract_aspirate.touchTip),
709
+ _delay=_build_delay_properties(retract_aspirate.delay),
710
+ )
711
+
712
+
713
+ def _build_retract_dispense(
714
+ retract_dispense: SharedDataRetractDispense,
715
+ ) -> RetractDispense:
716
+ return RetractDispense(
717
+ _end_position=_build_tip_position(retract_dispense.endPosition),
718
+ _speed=retract_dispense.speed,
719
+ _air_gap_by_volume=LiquidHandlingPropertyByVolume(
720
+ retract_dispense.airGapByVolume
721
+ ),
722
+ _blowout=_build_blowout_properties(retract_dispense.blowout),
723
+ _touch_tip=_build_touch_tip_properties(retract_dispense.touchTip),
724
+ _delay=_build_delay_properties(retract_dispense.delay),
725
+ )
726
+
727
+
728
+ def build_aspirate_properties(
729
+ aspirate_properties: SharedDataAspirateProperties,
730
+ ) -> AspirateProperties:
731
+ return AspirateProperties(
732
+ _submerge=_build_submerge(aspirate_properties.submerge),
733
+ _retract=_build_retract_aspirate(aspirate_properties.retract),
734
+ _aspirate_position=_build_tip_position(aspirate_properties.aspiratePosition),
735
+ _flow_rate_by_volume=LiquidHandlingPropertyByVolume(
736
+ aspirate_properties.flowRateByVolume
737
+ ),
738
+ _correction_by_volume=LiquidHandlingPropertyByVolume(
739
+ aspirate_properties.correctionByVolume
740
+ ),
741
+ _pre_wet=aspirate_properties.preWet,
742
+ _mix=_build_mix_properties(aspirate_properties.mix),
743
+ _delay=_build_delay_properties(aspirate_properties.delay),
744
+ )
745
+
746
+
747
+ def build_single_dispense_properties(
748
+ single_dispense_properties: SharedDataSingleDispenseProperties,
749
+ ) -> SingleDispenseProperties:
750
+ return SingleDispenseProperties(
751
+ _submerge=_build_submerge(single_dispense_properties.submerge),
752
+ _retract=_build_retract_dispense(single_dispense_properties.retract),
753
+ _dispense_position=_build_tip_position(
754
+ single_dispense_properties.dispensePosition
755
+ ),
756
+ _flow_rate_by_volume=LiquidHandlingPropertyByVolume(
757
+ single_dispense_properties.flowRateByVolume
758
+ ),
759
+ _correction_by_volume=LiquidHandlingPropertyByVolume(
760
+ single_dispense_properties.correctionByVolume
761
+ ),
762
+ _mix=_build_mix_properties(single_dispense_properties.mix),
763
+ _push_out_by_volume=LiquidHandlingPropertyByVolume(
764
+ single_dispense_properties.pushOutByVolume
765
+ ),
766
+ _delay=_build_delay_properties(single_dispense_properties.delay),
767
+ )
768
+
769
+
770
+ def build_multi_dispense_properties(
771
+ multi_dispense_properties: Optional[SharedDataMultiDispenseProperties],
772
+ ) -> Optional[MultiDispenseProperties]:
773
+ if multi_dispense_properties is None:
774
+ return None
775
+ return MultiDispenseProperties(
776
+ _submerge=_build_submerge(multi_dispense_properties.submerge),
777
+ _retract=_build_retract_dispense(multi_dispense_properties.retract),
778
+ _dispense_position=_build_tip_position(
779
+ multi_dispense_properties.dispensePosition
780
+ ),
781
+ _flow_rate_by_volume=LiquidHandlingPropertyByVolume(
782
+ multi_dispense_properties.flowRateByVolume
783
+ ),
784
+ _correction_by_volume=LiquidHandlingPropertyByVolume(
785
+ multi_dispense_properties.correctionByVolume
786
+ ),
787
+ _conditioning_by_volume=LiquidHandlingPropertyByVolume(
788
+ multi_dispense_properties.conditioningByVolume
789
+ ),
790
+ _disposal_by_volume=LiquidHandlingPropertyByVolume(
791
+ multi_dispense_properties.disposalByVolume
792
+ ),
793
+ _delay=_build_delay_properties(multi_dispense_properties.delay),
794
+ )
795
+
796
+
797
+ def build_transfer_properties(
798
+ transfer_properties: Union[SharedDataTransferProperties, SharedByTipTypeSetting],
799
+ ) -> TransferProperties:
800
+ if isinstance(transfer_properties, SharedByTipTypeSetting):
801
+ _transfer_properties = SharedDataTransferProperties(
802
+ aspirate=transfer_properties.aspirate,
803
+ singleDispense=transfer_properties.singleDispense,
804
+ multiDispense=transfer_properties.multiDispense,
805
+ )
806
+ else:
807
+ _transfer_properties = transfer_properties
808
+ return TransferProperties(
809
+ _aspirate=build_aspirate_properties(_transfer_properties.aspirate),
810
+ _dispense=build_single_dispense_properties(_transfer_properties.singleDispense),
811
+ _multi_dispense=build_multi_dispense_properties(
812
+ _transfer_properties.multiDispense
813
+ ),
814
+ )