opentrons 8.6.0a1__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 (600) 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 +501 -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 +183 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +552 -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/simulator_setup.py +260 -0
  200. opentrons/hardware_control/thread_manager.py +431 -0
  201. opentrons/hardware_control/threaded_async_lock.py +97 -0
  202. opentrons/hardware_control/types.py +792 -0
  203. opentrons/hardware_control/util.py +234 -0
  204. opentrons/legacy_broker.py +53 -0
  205. opentrons/legacy_commands/__init__.py +1 -0
  206. opentrons/legacy_commands/commands.py +483 -0
  207. opentrons/legacy_commands/helpers.py +153 -0
  208. opentrons/legacy_commands/module_commands.py +215 -0
  209. opentrons/legacy_commands/protocol_commands.py +54 -0
  210. opentrons/legacy_commands/publisher.py +155 -0
  211. opentrons/legacy_commands/robot_commands.py +51 -0
  212. opentrons/legacy_commands/types.py +1115 -0
  213. opentrons/motion_planning/__init__.py +32 -0
  214. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  215. opentrons/motion_planning/deck_conflict.py +396 -0
  216. opentrons/motion_planning/errors.py +35 -0
  217. opentrons/motion_planning/types.py +42 -0
  218. opentrons/motion_planning/waypoints.py +218 -0
  219. opentrons/ordered_set.py +138 -0
  220. opentrons/protocol_api/__init__.py +105 -0
  221. opentrons/protocol_api/_liquid.py +157 -0
  222. opentrons/protocol_api/_liquid_properties.py +814 -0
  223. opentrons/protocol_api/_nozzle_layout.py +31 -0
  224. opentrons/protocol_api/_parameter_context.py +300 -0
  225. opentrons/protocol_api/_parameters.py +31 -0
  226. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  227. opentrons/protocol_api/_types.py +43 -0
  228. opentrons/protocol_api/config.py +23 -0
  229. opentrons/protocol_api/core/__init__.py +23 -0
  230. opentrons/protocol_api/core/common.py +33 -0
  231. opentrons/protocol_api/core/core_map.py +74 -0
  232. opentrons/protocol_api/core/engine/__init__.py +22 -0
  233. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  234. opentrons/protocol_api/core/engine/deck_conflict.py +348 -0
  235. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  236. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  237. opentrons/protocol_api/core/engine/labware.py +238 -0
  238. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  239. opentrons/protocol_api/core/engine/module_core.py +1025 -0
  240. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  241. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  242. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  243. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  244. opentrons/protocol_api/core/engine/robot.py +139 -0
  245. opentrons/protocol_api/core/engine/stringify.py +74 -0
  246. opentrons/protocol_api/core/engine/transfer_components_executor.py +990 -0
  247. opentrons/protocol_api/core/engine/well.py +241 -0
  248. opentrons/protocol_api/core/instrument.py +459 -0
  249. opentrons/protocol_api/core/labware.py +151 -0
  250. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  251. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  252. opentrons/protocol_api/core/legacy/deck.py +369 -0
  253. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  254. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  255. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  256. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  257. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  258. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  259. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  260. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  261. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  262. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  263. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  265. opentrons/protocol_api/core/module.py +484 -0
  266. opentrons/protocol_api/core/protocol.py +311 -0
  267. opentrons/protocol_api/core/robot.py +51 -0
  268. opentrons/protocol_api/core/well.py +116 -0
  269. opentrons/protocol_api/core/well_grid.py +45 -0
  270. opentrons/protocol_api/create_protocol_context.py +177 -0
  271. opentrons/protocol_api/deck.py +223 -0
  272. opentrons/protocol_api/disposal_locations.py +244 -0
  273. opentrons/protocol_api/instrument_context.py +3212 -0
  274. opentrons/protocol_api/labware.py +1579 -0
  275. opentrons/protocol_api/module_contexts.py +1425 -0
  276. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  277. opentrons/protocol_api/protocol_context.py +1688 -0
  278. opentrons/protocol_api/robot_context.py +303 -0
  279. opentrons/protocol_api/validation.py +761 -0
  280. opentrons/protocol_engine/__init__.py +155 -0
  281. opentrons/protocol_engine/actions/__init__.py +65 -0
  282. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  283. opentrons/protocol_engine/actions/action_handler.py +13 -0
  284. opentrons/protocol_engine/actions/actions.py +302 -0
  285. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  286. opentrons/protocol_engine/clients/__init__.py +5 -0
  287. opentrons/protocol_engine/clients/sync_client.py +174 -0
  288. opentrons/protocol_engine/clients/transports.py +197 -0
  289. opentrons/protocol_engine/commands/__init__.py +757 -0
  290. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  296. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  297. opentrons/protocol_engine/commands/aspirate.py +244 -0
  298. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  299. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  300. opentrons/protocol_engine/commands/blow_out.py +146 -0
  301. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  302. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  303. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  306. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  307. opentrons/protocol_engine/commands/command.py +308 -0
  308. opentrons/protocol_engine/commands/command_unions.py +974 -0
  309. opentrons/protocol_engine/commands/comment.py +57 -0
  310. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  311. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  312. opentrons/protocol_engine/commands/custom.py +67 -0
  313. opentrons/protocol_engine/commands/dispense.py +194 -0
  314. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  315. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  316. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  317. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  318. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  319. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  320. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  321. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  322. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  323. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  324. opentrons/protocol_engine/commands/flex_stacker/store.py +326 -0
  325. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  326. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  327. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  328. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  329. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  330. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  331. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  333. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  334. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  336. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  337. opentrons/protocol_engine/commands/home.py +100 -0
  338. opentrons/protocol_engine/commands/identify_module.py +86 -0
  339. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  340. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  341. opentrons/protocol_engine/commands/load_labware.py +210 -0
  342. opentrons/protocol_engine/commands/load_lid.py +154 -0
  343. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  344. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  345. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  346. opentrons/protocol_engine/commands/load_module.py +223 -0
  347. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  348. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  349. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  350. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  351. opentrons/protocol_engine/commands/move_labware.py +546 -0
  352. opentrons/protocol_engine/commands/move_relative.py +102 -0
  353. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  355. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  356. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  357. opentrons/protocol_engine/commands/movement_common.py +338 -0
  358. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  359. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  360. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  361. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  362. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  363. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  364. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  365. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  366. opentrons/protocol_engine/commands/robot/common.py +18 -0
  367. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  369. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  370. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  371. opentrons/protocol_engine/commands/save_position.py +109 -0
  372. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  373. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  374. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  375. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  376. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  377. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  378. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  379. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  380. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  381. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  384. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  386. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  388. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  390. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  391. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  392. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  401. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  402. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  403. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  404. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  405. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  406. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  407. opentrons/protocol_engine/engine_support.py +28 -0
  408. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  409. opentrons/protocol_engine/errors/__init__.py +191 -0
  410. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  411. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  412. opentrons/protocol_engine/execution/__init__.py +50 -0
  413. opentrons/protocol_engine/execution/command_executor.py +216 -0
  414. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  415. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  416. opentrons/protocol_engine/execution/equipment.py +819 -0
  417. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  418. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  419. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  420. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  421. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  422. opentrons/protocol_engine/execution/movement.py +349 -0
  423. opentrons/protocol_engine/execution/pipetting.py +607 -0
  424. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  425. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  426. opentrons/protocol_engine/execution/run_control.py +33 -0
  427. opentrons/protocol_engine/execution/status_bar.py +34 -0
  428. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  429. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  430. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  431. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  432. opentrons/protocol_engine/notes/__init__.py +17 -0
  433. opentrons/protocol_engine/notes/notes.py +59 -0
  434. opentrons/protocol_engine/plugins.py +104 -0
  435. opentrons/protocol_engine/protocol_engine.py +683 -0
  436. opentrons/protocol_engine/resources/__init__.py +26 -0
  437. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  438. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  439. opentrons/protocol_engine/resources/file_provider.py +161 -0
  440. opentrons/protocol_engine/resources/fixture_validation.py +58 -0
  441. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  442. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  443. opentrons/protocol_engine/resources/model_utils.py +32 -0
  444. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  445. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  446. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  447. opentrons/protocol_engine/slot_standardization.py +128 -0
  448. opentrons/protocol_engine/state/__init__.py +1 -0
  449. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  450. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  451. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  452. opentrons/protocol_engine/state/_move_types.py +83 -0
  453. opentrons/protocol_engine/state/_well_math.py +193 -0
  454. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  455. opentrons/protocol_engine/state/command_history.py +309 -0
  456. opentrons/protocol_engine/state/commands.py +1158 -0
  457. opentrons/protocol_engine/state/config.py +39 -0
  458. opentrons/protocol_engine/state/files.py +57 -0
  459. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  460. opentrons/protocol_engine/state/geometry.py +2359 -0
  461. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  462. opentrons/protocol_engine/state/labware.py +1459 -0
  463. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  464. opentrons/protocol_engine/state/liquids.py +73 -0
  465. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  466. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  467. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  468. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  469. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  471. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  472. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  473. opentrons/protocol_engine/state/modules.py +1500 -0
  474. opentrons/protocol_engine/state/motion.py +373 -0
  475. opentrons/protocol_engine/state/pipettes.py +905 -0
  476. opentrons/protocol_engine/state/state.py +421 -0
  477. opentrons/protocol_engine/state/state_summary.py +36 -0
  478. opentrons/protocol_engine/state/tips.py +420 -0
  479. opentrons/protocol_engine/state/update_types.py +904 -0
  480. opentrons/protocol_engine/state/wells.py +290 -0
  481. opentrons/protocol_engine/types/__init__.py +308 -0
  482. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  483. opentrons/protocol_engine/types/command_annotations.py +53 -0
  484. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  485. opentrons/protocol_engine/types/execution.py +96 -0
  486. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  487. opentrons/protocol_engine/types/instrument.py +47 -0
  488. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  489. opentrons/protocol_engine/types/labware.py +131 -0
  490. opentrons/protocol_engine/types/labware_movement.py +22 -0
  491. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  492. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  493. opentrons/protocol_engine/types/liquid.py +40 -0
  494. opentrons/protocol_engine/types/liquid_class.py +59 -0
  495. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  496. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  497. opentrons/protocol_engine/types/location.py +194 -0
  498. opentrons/protocol_engine/types/module.py +303 -0
  499. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  500. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  501. opentrons/protocol_engine/types/tip.py +18 -0
  502. opentrons/protocol_engine/types/util.py +21 -0
  503. opentrons/protocol_engine/types/well_position.py +124 -0
  504. opentrons/protocol_reader/__init__.py +37 -0
  505. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  506. opentrons/protocol_reader/file_format_validator.py +152 -0
  507. opentrons/protocol_reader/file_hasher.py +27 -0
  508. opentrons/protocol_reader/file_identifier.py +284 -0
  509. opentrons/protocol_reader/file_reader_writer.py +90 -0
  510. opentrons/protocol_reader/input_file.py +16 -0
  511. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  512. opentrons/protocol_reader/protocol_reader.py +188 -0
  513. opentrons/protocol_reader/protocol_source.py +124 -0
  514. opentrons/protocol_reader/role_analyzer.py +86 -0
  515. opentrons/protocol_runner/__init__.py +26 -0
  516. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  517. opentrons/protocol_runner/json_file_reader.py +55 -0
  518. opentrons/protocol_runner/json_translator.py +314 -0
  519. opentrons/protocol_runner/legacy_command_mapper.py +848 -0
  520. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  521. opentrons/protocol_runner/protocol_runner.py +530 -0
  522. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  523. opentrons/protocol_runner/run_orchestrator.py +496 -0
  524. opentrons/protocol_runner/task_queue.py +95 -0
  525. opentrons/protocols/__init__.py +6 -0
  526. opentrons/protocols/advanced_control/__init__.py +0 -0
  527. opentrons/protocols/advanced_control/common.py +38 -0
  528. opentrons/protocols/advanced_control/mix.py +60 -0
  529. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  530. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  531. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  532. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  533. opentrons/protocols/api_support/__init__.py +0 -0
  534. opentrons/protocols/api_support/constants.py +8 -0
  535. opentrons/protocols/api_support/deck_type.py +110 -0
  536. opentrons/protocols/api_support/definitions.py +18 -0
  537. opentrons/protocols/api_support/instrument.py +151 -0
  538. opentrons/protocols/api_support/labware_like.py +233 -0
  539. opentrons/protocols/api_support/tip_tracker.py +175 -0
  540. opentrons/protocols/api_support/types.py +32 -0
  541. opentrons/protocols/api_support/util.py +403 -0
  542. opentrons/protocols/bundle.py +89 -0
  543. opentrons/protocols/duration/__init__.py +4 -0
  544. opentrons/protocols/duration/errors.py +5 -0
  545. opentrons/protocols/duration/estimator.py +628 -0
  546. opentrons/protocols/execution/__init__.py +0 -0
  547. opentrons/protocols/execution/dev_types.py +181 -0
  548. opentrons/protocols/execution/errors.py +40 -0
  549. opentrons/protocols/execution/execute.py +84 -0
  550. opentrons/protocols/execution/execute_json_v3.py +275 -0
  551. opentrons/protocols/execution/execute_json_v4.py +359 -0
  552. opentrons/protocols/execution/execute_json_v5.py +28 -0
  553. opentrons/protocols/execution/execute_python.py +169 -0
  554. opentrons/protocols/execution/json_dispatchers.py +87 -0
  555. opentrons/protocols/execution/types.py +7 -0
  556. opentrons/protocols/geometry/__init__.py +0 -0
  557. opentrons/protocols/geometry/planning.py +297 -0
  558. opentrons/protocols/labware.py +312 -0
  559. opentrons/protocols/models/__init__.py +0 -0
  560. opentrons/protocols/models/json_protocol.py +679 -0
  561. opentrons/protocols/parameters/__init__.py +0 -0
  562. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  563. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  564. opentrons/protocols/parameters/exceptions.py +34 -0
  565. opentrons/protocols/parameters/parameter_definition.py +272 -0
  566. opentrons/protocols/parameters/types.py +17 -0
  567. opentrons/protocols/parameters/validation.py +267 -0
  568. opentrons/protocols/parse.py +671 -0
  569. opentrons/protocols/types.py +159 -0
  570. opentrons/py.typed +0 -0
  571. opentrons/resources/scripts/lpc21isp +0 -0
  572. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  573. opentrons/simulate.py +1065 -0
  574. opentrons/system/__init__.py +6 -0
  575. opentrons/system/camera.py +51 -0
  576. opentrons/system/log_control.py +59 -0
  577. opentrons/system/nmcli.py +856 -0
  578. opentrons/system/resin.py +24 -0
  579. opentrons/system/smoothie_update.py +15 -0
  580. opentrons/system/wifi.py +204 -0
  581. opentrons/tools/__init__.py +0 -0
  582. opentrons/tools/args_handler.py +22 -0
  583. opentrons/tools/write_pipette_memory.py +157 -0
  584. opentrons/types.py +618 -0
  585. opentrons/util/__init__.py +1 -0
  586. opentrons/util/async_helpers.py +166 -0
  587. opentrons/util/broker.py +84 -0
  588. opentrons/util/change_notifier.py +47 -0
  589. opentrons/util/entrypoint_util.py +278 -0
  590. opentrons/util/get_union_elements.py +26 -0
  591. opentrons/util/helpers.py +6 -0
  592. opentrons/util/linal.py +178 -0
  593. opentrons/util/logging_config.py +265 -0
  594. opentrons/util/logging_queue_handler.py +61 -0
  595. opentrons/util/performance_helpers.py +157 -0
  596. opentrons-8.6.0a1.dist-info/METADATA +37 -0
  597. opentrons-8.6.0a1.dist-info/RECORD +600 -0
  598. opentrons-8.6.0a1.dist-info/WHEEL +4 -0
  599. opentrons-8.6.0a1.dist-info/entry_points.txt +3 -0
  600. opentrons-8.6.0a1.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,777 @@
1
+ from __future__ import annotations
2
+
3
+ import functools
4
+
5
+ """ Classes and functions for pipette state tracking
6
+ """
7
+ import logging
8
+ from typing import Any, Dict, Optional, Set, Tuple, Union, cast
9
+
10
+ from opentrons_shared_data.pipette.pipette_definition import (
11
+ PipetteConfigurations,
12
+ PlungerPositions,
13
+ MotorConfigurations,
14
+ SupportedTipsDefinition,
15
+ PickUpTipConfigurations,
16
+ DropTipConfigurations,
17
+ PipetteModelVersionType,
18
+ PipetteNameType,
19
+ PipetteLiquidPropertiesDefinition,
20
+ PressFitPickUpTipConfiguration,
21
+ )
22
+ from opentrons_shared_data.pipette import (
23
+ load_data as load_pipette_data,
24
+ types as pip_types,
25
+ )
26
+ from opentrons_shared_data.errors.exceptions import (
27
+ InvalidLiquidClassName,
28
+ CommandPreconditionViolated,
29
+ )
30
+ from opentrons_shared_data.pipette.ul_per_mm import (
31
+ calculate_ul_per_mm,
32
+ PIPETTING_FUNCTION_FALLBACK_VERSION,
33
+ PIPETTING_FUNCTION_LATEST_VERSION,
34
+ )
35
+
36
+
37
+ from opentrons.types import Point, Mount
38
+ from opentrons.config import robot_configs
39
+ from opentrons.config.types import RobotConfig
40
+ from opentrons.drivers.types import MoveSplit
41
+ from ..instrument_abc import AbstractInstrument
42
+
43
+ from .instrument_calibration import (
44
+ PipetteOffsetByPipetteMount,
45
+ load_pipette_offset,
46
+ )
47
+ from opentrons.hardware_control.types import (
48
+ CriticalPoint,
49
+ BoardRevision,
50
+ )
51
+ from opentrons.hardware_control.errors import InvalidCriticalPoint
52
+ from opentrons.hardware_control import nozzle_manager
53
+
54
+
55
+ from opentrons_shared_data.pipette.types import (
56
+ UlPerMmAction,
57
+ PipetteName,
58
+ PipetteModel,
59
+ PipetteOEMType,
60
+ )
61
+ from opentrons.hardware_control.dev_types import InstrumentHardwareConfigs
62
+
63
+ from opentrons.hardware_control.util import (
64
+ pick_up_speed_by_configuration,
65
+ pick_up_distance_by_configuration,
66
+ pick_up_current_by_configuration,
67
+ nominal_tip_overlap_dictionary_by_configuration,
68
+ )
69
+
70
+ RECONFIG_KEYS = {"quirks"}
71
+
72
+
73
+ mod_log = logging.getLogger(__name__)
74
+
75
+ # TODO (lc 11-1-2022) Once we unify calibration loading
76
+ # for the hardware controller, we will be able to
77
+ # unify the pipette classes again.
78
+
79
+
80
+ class Pipette(AbstractInstrument[PipetteConfigurations]):
81
+ """A class to gather and track pipette state and configs.
82
+
83
+ This class should not touch hardware or call back out to the hardware
84
+ control API. Its only purpose is to gather state.
85
+ """
86
+
87
+ DictType = Dict[
88
+ str, Union[str, float, bool]
89
+ ] # spp: as_dict() has value items that aren't Union[str, float, bool]..
90
+ #: The type of this data class as a dict
91
+
92
+ def __init__(
93
+ self,
94
+ config: PipetteConfigurations,
95
+ pipette_offset_cal: PipetteOffsetByPipetteMount,
96
+ pipette_id: Optional[str] = None,
97
+ use_old_aspiration_functions: bool = False,
98
+ ) -> None:
99
+ self._config = config
100
+ self._config_as_dict = config.model_dump()
101
+ self._pipette_offset = pipette_offset_cal
102
+ self._pipette_type = self._config.pipette_type
103
+ self._pipette_version = self._config.version
104
+ self._max_channels = self._config.channels
105
+ self._backlash_distance = config.backlash_distance
106
+ self._pick_up_configurations = config.pick_up_tip_configurations
107
+
108
+ self._liquid_class_name = pip_types.LiquidClasses.default
109
+ self._liquid_class = self._config.liquid_properties[self._liquid_class_name]
110
+
111
+ # TODO (lc 12-05-2022) figure out how we can safely deprecate "name" and "model"
112
+ self._pipette_name = PipetteNameType(
113
+ pipette_type=config.pipette_type,
114
+ pipette_channels=config.channels,
115
+ pipette_generation=config.display_category,
116
+ oem_type=PipetteOEMType.OT,
117
+ )
118
+ self._acting_as = self._pipette_name
119
+ self._pipette_model = PipetteModelVersionType(
120
+ pipette_type=config.pipette_type,
121
+ pipette_channels=config.channels,
122
+ pipette_version=config.version,
123
+ oem_type=PipetteOEMType.OT,
124
+ )
125
+ self._valid_nozzle_maps = load_pipette_data.load_valid_nozzle_maps(
126
+ self._pipette_model.pipette_type,
127
+ self._pipette_model.pipette_channels,
128
+ self._pipette_model.pipette_version,
129
+ PipetteOEMType.OT,
130
+ )
131
+ self._nozzle_offset = self._config.nozzle_offset
132
+ self._nozzle_manager = (
133
+ nozzle_manager.NozzleConfigurationManager.build_from_config(
134
+ self._config, self._valid_nozzle_maps
135
+ )
136
+ )
137
+ self._current_volume = 0.0
138
+ self._working_volume = float(self._liquid_class.max_volume)
139
+ self._current_tip_length = 0.0
140
+ self._current_tiprack_diameter = 0.0
141
+ self._has_tip = False
142
+ self._pipette_id = pipette_id
143
+ self._log = mod_log.getChild(
144
+ self._pipette_id if self._pipette_id else "<unknown>"
145
+ )
146
+ self._log.info(
147
+ "loaded: {}, pipette offset: {}".format(
148
+ self._pipette_model, self._pipette_offset.offset
149
+ )
150
+ )
151
+ self.ready_to_aspirate = False
152
+ #: True if ready to aspirate
153
+
154
+ self._active_tip_settings = self._liquid_class.supported_tips[
155
+ pip_types.PipetteTipType(self._liquid_class.max_volume)
156
+ ]
157
+ self._fallback_tip_length = self._active_tip_settings.default_tip_length
158
+
159
+ self._aspirate_flow_rate = (
160
+ self._active_tip_settings.default_aspirate_flowrate.default
161
+ )
162
+ self._dispense_flow_rate = (
163
+ self._active_tip_settings.default_dispense_flowrate.default
164
+ )
165
+ self._blow_out_flow_rate = (
166
+ self._active_tip_settings.default_blowout_flowrate.default
167
+ )
168
+
169
+ self._versioned_tip_overlap_dictionary = (
170
+ self.get_nominal_tip_overlap_dictionary_by_configuration()
171
+ )
172
+
173
+ if use_old_aspiration_functions:
174
+ self._pipetting_function_version = PIPETTING_FUNCTION_FALLBACK_VERSION
175
+ else:
176
+ self._pipetting_function_version = PIPETTING_FUNCTION_LATEST_VERSION
177
+
178
+ @property
179
+ def push_out_volume(self) -> float:
180
+ return self._active_tip_settings.default_push_out_volume
181
+
182
+ def act_as(self, name: PipetteNameType) -> None:
183
+ """Reconfigure to act as ``name``. ``name`` must be either the
184
+ actual name of the pipette, or a name in its back-compatibility
185
+ config.
186
+ """
187
+ if name == self._acting_as:
188
+ return
189
+
190
+ str_name = f"{name.pipette_type.name}_{str(name.pipette_channels)}"
191
+ assert str_name in self._config.pipette_backcompat_names + [
192
+ self.name
193
+ ], f"{self.name} is not back-compatible with {name}"
194
+
195
+ liquid_model = load_pipette_data.load_liquid_model(
196
+ name.pipette_type, name.pipette_channels, name.get_version(), name.oem_type
197
+ )
198
+ # TODO need to grab name config here to deal with act as test
199
+ self._liquid_class.max_volume = liquid_model["default"].max_volume
200
+ self._liquid_class.min_volume = liquid_model["default"].min_volume
201
+ self.working_volume = liquid_model["default"].max_volume
202
+ self.update_config_item(
203
+ {
204
+ "min_volume": liquid_model["default"].min_volume,
205
+ "max_volume": liquid_model["default"].max_volume,
206
+ },
207
+ pip_types.LiquidClasses.default,
208
+ )
209
+
210
+ @property
211
+ def acting_as(self) -> PipetteNameType:
212
+ return self._acting_as
213
+
214
+ @property
215
+ def config(self) -> PipetteConfigurations:
216
+ return self._config
217
+
218
+ @property
219
+ def liquid_class(self) -> PipetteLiquidPropertiesDefinition:
220
+ return self._liquid_class
221
+
222
+ @property
223
+ def liquid_class_name(self) -> pip_types.LiquidClasses:
224
+ return self._liquid_class_name
225
+
226
+ @property
227
+ def nozzle_offset(self) -> Point:
228
+ return self._nozzle_manager.starting_nozzle_offset
229
+
230
+ @property
231
+ def nozzle_manager(self) -> nozzle_manager.NozzleConfigurationManager:
232
+ return self._nozzle_manager
233
+
234
+ @property
235
+ def pipette_offset(self) -> PipetteOffsetByPipetteMount:
236
+ return self._pipette_offset
237
+
238
+ @property
239
+ def tip_overlap(self) -> Dict[str, Dict[str, float]]:
240
+ return self._versioned_tip_overlap_dictionary
241
+
242
+ @property
243
+ def channels(self) -> pip_types.PipetteChannelType:
244
+ return self._max_channels
245
+
246
+ @property
247
+ def plunger_positions(self) -> PlungerPositions:
248
+ return self._config.plunger_positions_configurations[self._liquid_class_name]
249
+
250
+ @property
251
+ def plunger_motor_current(self) -> MotorConfigurations:
252
+ return self._config.plunger_motor_configurations
253
+
254
+ @property
255
+ def pick_up_configurations(self) -> PickUpTipConfigurations:
256
+ return self._config.pick_up_tip_configurations
257
+
258
+ @pick_up_configurations.setter
259
+ def pick_up_configurations(self, pick_up_configs: PickUpTipConfigurations) -> None:
260
+ self._pick_up_configurations = pick_up_configs
261
+
262
+ @property
263
+ def drop_configurations(self) -> DropTipConfigurations:
264
+ return self._config.drop_tip_configurations
265
+
266
+ @property
267
+ def active_tip_settings(self) -> SupportedTipsDefinition:
268
+ return self._active_tip_settings
269
+
270
+ def update_config_item(
271
+ self,
272
+ elements: Dict[str, Any],
273
+ liquid_class: Optional[pip_types.LiquidClasses] = None,
274
+ ) -> None:
275
+ self._log.info(f"updated config: {elements}")
276
+ self._config = load_pipette_data.update_pipette_configuration(
277
+ self._config, elements, liquid_class
278
+ )
279
+ # Update the cached dict representation
280
+ self._config_as_dict = self._config.model_dump()
281
+
282
+ def reload_configurations(self) -> None:
283
+ self._config = load_pipette_data.load_definition(
284
+ self._pipette_model.pipette_type,
285
+ self._pipette_model.pipette_channels,
286
+ self._pipette_model.pipette_version,
287
+ self._pipette_model.oem_type,
288
+ )
289
+ self._config_as_dict = self._config.model_dump()
290
+
291
+ def reset_state(self) -> None:
292
+ self._current_volume = 0.0
293
+ self._working_volume = float(self.liquid_class.max_volume)
294
+ self._current_tip_length = 0.0
295
+ self._current_tiprack_diameter = 0.0
296
+ self._has_tip = False
297
+ self.ready_to_aspirate = False
298
+ #: True if ready to aspirate
299
+ self._active_tip_settings = self.liquid_class.supported_tips[
300
+ pip_types.PipetteTipType(self._working_volume)
301
+ ]
302
+ self._fallback_tip_length = self.active_tip_settings.default_tip_length
303
+
304
+ self._aspirate_flow_rate = (
305
+ self.active_tip_settings.default_aspirate_flowrate.default
306
+ )
307
+ self._dispense_flow_rate = (
308
+ self.active_tip_settings.default_dispense_flowrate.default
309
+ )
310
+ self._blow_out_flow_rate = (
311
+ self.active_tip_settings.default_blowout_flowrate.default
312
+ )
313
+
314
+ self._versioned_tip_overlap_dictionary = (
315
+ self.get_nominal_tip_overlap_dictionary_by_configuration()
316
+ )
317
+
318
+ self._nozzle_manager = (
319
+ nozzle_manager.NozzleConfigurationManager.build_from_config(
320
+ self._config, self._valid_nozzle_maps
321
+ )
322
+ )
323
+
324
+ def reset_pipette_offset(self, mount: Mount, to_default: bool) -> None:
325
+ """Reset the pipette offset to system defaults."""
326
+ if to_default:
327
+ self._pipette_offset = load_pipette_offset(pip_id=None, mount=mount)
328
+ else:
329
+ self._pipette_offset = load_pipette_offset(self._pipette_id, mount)
330
+
331
+ def save_pipette_offset(self, mount: Mount, offset: Point) -> None:
332
+ """Update the pipette offset to a new value."""
333
+ # TODO (lc 10-31-2022) We should have this command be supported properly by
334
+ # ot-3 and ot-2 when we split out the pipette class
335
+ self._pipette_offset = load_pipette_offset(self._pipette_id, mount)
336
+
337
+ @property
338
+ def name(self) -> PipetteName:
339
+ return cast(PipetteName, f"{self._pipette_name}")
340
+
341
+ @property
342
+ def model(self) -> PipetteModel:
343
+ return cast(PipetteModel, f"{self._pipette_model}")
344
+
345
+ @property
346
+ def pipette_type(self) -> pip_types.PipetteModelType:
347
+ return self._pipette_type
348
+
349
+ @property
350
+ def pipette_id(self) -> Optional[str]:
351
+ return self._pipette_id
352
+
353
+ def critical_point(self, cp_override: Optional[CriticalPoint] = None) -> Point:
354
+ """
355
+ The vector from the pipette's origin to its critical point. The
356
+ critical point for a pipette is the end of the nozzle if no tip is
357
+ attached, or the end of the tip if a tip is attached.
358
+
359
+ If `cp_override` is specified and valid - so is either
360
+ :py:attr:`CriticalPoint.NOZZLE` or :py:attr:`CriticalPoint.TIP` when
361
+ we have a tip, or :py:attr:`CriticalPoint.XY_CENTER` - the specified
362
+ critical point will be used.
363
+ """
364
+
365
+ if cp_override in [
366
+ CriticalPoint.GRIPPER_JAW_CENTER,
367
+ CriticalPoint.GRIPPER_FRONT_CALIBRATION_PIN,
368
+ CriticalPoint.GRIPPER_REAR_CALIBRATION_PIN,
369
+ ]:
370
+ raise InvalidCriticalPoint(cp_override.name, "pipette")
371
+
372
+ instr = Point(*self._pipette_offset.offset)
373
+ cp_with_tip_length = self._nozzle_manager.critical_point_with_tip_length(
374
+ cp_override,
375
+ self.current_tip_length if cp_override != CriticalPoint.NOZZLE else 0.0,
376
+ )
377
+
378
+ cp = cp_with_tip_length + instr
379
+
380
+ if self._log.isEnabledFor(logging.DEBUG):
381
+ info_str = "cp: {}{}: {} (from: ".format(
382
+ cp_override, " (from override)" if cp_override else "", cp
383
+ )
384
+ info_str += "model offset: {} + instrument offset: {}".format(
385
+ cp_with_tip_length, instr
386
+ )
387
+ info_str += " - tip_length: {}".format(self.current_tip_length)
388
+ info_str += ")"
389
+ self._log.debug(info_str)
390
+
391
+ return cp
392
+
393
+ @property
394
+ def current_volume(self) -> float:
395
+ """The amount of liquid currently aspirated"""
396
+ return self._current_volume
397
+
398
+ @property
399
+ def current_tip_length(self) -> float:
400
+ """The length of the current tip attached (0.0 if no tip)"""
401
+ return self._current_tip_length
402
+
403
+ @current_tip_length.setter
404
+ def current_tip_length(self, tip_length: float) -> None:
405
+ self._current_tip_length = tip_length
406
+
407
+ @property
408
+ def current_tiprack_diameter(self) -> float:
409
+ """The diameter of the current tip rack (0.0 if no tip)"""
410
+ return self._current_tiprack_diameter
411
+
412
+ @current_tiprack_diameter.setter
413
+ def current_tiprack_diameter(self, diameter: float) -> None:
414
+ self._current_tiprack_diameter = diameter
415
+
416
+ @property
417
+ def aspirate_flow_rate(self) -> float:
418
+ """Current active flow rate (not config value)"""
419
+ return self._aspirate_flow_rate
420
+
421
+ @aspirate_flow_rate.setter
422
+ def aspirate_flow_rate(self, new_flow_rate: float) -> None:
423
+ assert new_flow_rate > 0
424
+ self._aspirate_flow_rate = new_flow_rate
425
+
426
+ @property
427
+ def dispense_flow_rate(self) -> float:
428
+ """Current active flow rate (not config value)"""
429
+ return self._dispense_flow_rate
430
+
431
+ @dispense_flow_rate.setter
432
+ def dispense_flow_rate(self, new_flow_rate: float) -> None:
433
+ assert new_flow_rate > 0
434
+ self._dispense_flow_rate = new_flow_rate
435
+
436
+ @property
437
+ def blow_out_flow_rate(self) -> float:
438
+ """Current active flow rate (not config value)"""
439
+ return self._blow_out_flow_rate
440
+
441
+ @blow_out_flow_rate.setter
442
+ def blow_out_flow_rate(self, new_flow_rate: float) -> None:
443
+ assert new_flow_rate > 0
444
+ self._blow_out_flow_rate = new_flow_rate
445
+
446
+ @property
447
+ def aspirate_flow_rates_lookup(self) -> Dict[str, float]:
448
+ return self._active_tip_settings.default_aspirate_flowrate.values_by_api_level
449
+
450
+ @property
451
+ def dispense_flow_rates_lookup(self) -> Dict[str, float]:
452
+ return self._active_tip_settings.default_dispense_flowrate.values_by_api_level
453
+
454
+ @property
455
+ def blow_out_flow_rates_lookup(self) -> Dict[str, float]:
456
+ return self.active_tip_settings.default_blowout_flowrate.values_by_api_level
457
+
458
+ @property
459
+ def working_volume(self) -> float:
460
+ """The working volume of the pipette"""
461
+ return self._working_volume
462
+
463
+ @working_volume.setter
464
+ def working_volume(self, tip_volume: float) -> None:
465
+ """The working volume is the current tip max volume"""
466
+ self._working_volume = min(self.liquid_class.max_volume, tip_volume)
467
+ tip_size_type = pip_types.PipetteTipType.check_and_return_type(
468
+ int(self._working_volume), self.liquid_class.max_volume
469
+ )
470
+ self._active_tip_settings = self.liquid_class.supported_tips[tip_size_type]
471
+ self._fallback_tip_length = self._active_tip_settings.default_tip_length
472
+
473
+ @property
474
+ def minimum_volume(self) -> float:
475
+ """The smallest controllable volume the pipette can handle with the current liquid class.."""
476
+ return self.liquid_class.min_volume
477
+
478
+ @property
479
+ def available_volume(self) -> float:
480
+ """The amount of liquid possible to aspirate"""
481
+ return self.working_volume - self.current_volume
482
+
483
+ def set_current_volume(self, new_volume: float) -> None:
484
+ assert new_volume >= 0
485
+ assert new_volume <= self.working_volume
486
+ self._current_volume = new_volume
487
+
488
+ def add_current_volume(self, volume_incr: float) -> None:
489
+ assert self.ok_to_add_volume(volume_incr)
490
+ self._current_volume += volume_incr
491
+
492
+ def remove_current_volume(self, volume_incr: float) -> None:
493
+ assert self._current_volume >= volume_incr
494
+ self._current_volume -= volume_incr
495
+
496
+ def ok_to_add_volume(self, volume_incr: float) -> bool:
497
+ return self.current_volume + volume_incr <= self.working_volume
498
+
499
+ def ok_to_push_out(self, push_out_dist_mm: float) -> bool:
500
+ return push_out_dist_mm <= (
501
+ self.plunger_positions.bottom - self.plunger_positions.blow_out
502
+ )
503
+
504
+ def update_nozzle_configuration(
505
+ self,
506
+ back_left_nozzle: str,
507
+ front_right_nozzle: str,
508
+ starting_nozzle: Optional[str] = None,
509
+ ) -> None:
510
+ """
511
+ Update nozzle configuration manager.
512
+ """
513
+ self._nozzle_manager.update_nozzle_configuration(
514
+ back_left_nozzle, front_right_nozzle, starting_nozzle
515
+ )
516
+
517
+ def reset_nozzle_configuration(self) -> None:
518
+ """
519
+ Reset nozzle configuration manager.
520
+ """
521
+ self._nozzle_manager.reset_to_default_configuration()
522
+
523
+ def add_tip(self, tip_length: float) -> None:
524
+ """
525
+ Add a tip to the pipette for position tracking and validation
526
+ (effectively updates the pipette's critical point)
527
+
528
+ :param tip_length: a positive, non-zero float presenting the distance
529
+ in Z from the end of the pipette nozzle to the end of the tip
530
+ :return:
531
+ """
532
+ assert tip_length > 0.0, "tip_length must be greater than 0"
533
+ assert not self.has_tip
534
+ self._has_tip = True
535
+ self._current_tip_length = tip_length
536
+
537
+ def remove_tip(self) -> None:
538
+ """
539
+ Remove the tip from the pipette (effectively updates the pipette's
540
+ critical point)
541
+ """
542
+ self._has_tip = False
543
+ self._current_tip_length = 0.0
544
+
545
+ @property
546
+ def has_tip(self) -> bool:
547
+ return self._has_tip
548
+
549
+ def get_pick_up_speed_by_configuration(
550
+ self,
551
+ config: PressFitPickUpTipConfiguration,
552
+ ) -> float:
553
+ return pick_up_speed_by_configuration(
554
+ config,
555
+ self._nozzle_manager.current_configuration.valid_map_key,
556
+ pip_types.PipetteTipType(self._liquid_class.max_volume),
557
+ )
558
+
559
+ def get_pick_up_distance_by_configuration(
560
+ self,
561
+ config: PressFitPickUpTipConfiguration,
562
+ ) -> float:
563
+ return pick_up_distance_by_configuration(
564
+ config,
565
+ self._nozzle_manager.current_configuration.valid_map_key,
566
+ pip_types.PipetteTipType(self._liquid_class.max_volume),
567
+ )
568
+
569
+ def get_pick_up_current_by_configuration(
570
+ self,
571
+ config: PressFitPickUpTipConfiguration,
572
+ ) -> float:
573
+ return pick_up_current_by_configuration(
574
+ config,
575
+ self._nozzle_manager.current_configuration.valid_map_key,
576
+ pip_types.PipetteTipType(self._liquid_class.max_volume),
577
+ )
578
+
579
+ def get_nominal_tip_overlap_dictionary_by_configuration(
580
+ self,
581
+ ) -> Dict[str, Dict[str, float]]:
582
+ return nominal_tip_overlap_dictionary_by_configuration(
583
+ self._config,
584
+ self._nozzle_manager.current_configuration.valid_map_key,
585
+ pip_types.PipetteTipType(self._liquid_class.max_volume),
586
+ )
587
+
588
+ # Cache max is chosen somewhat arbitrarily. With a float is input we don't
589
+ # want this to unbounded.
590
+ @functools.lru_cache(maxsize=100)
591
+ def ul_per_mm(self, ul: float, action: UlPerMmAction) -> float:
592
+ return calculate_ul_per_mm(
593
+ ul, action, self._active_tip_settings, self._pipetting_function_version
594
+ )
595
+
596
+ def __str__(self) -> str:
597
+ return "{} current volume {}ul critical point: {} at {}".format(
598
+ self._config.display_name,
599
+ self.current_volume,
600
+ "tip end" if self.has_tip else "nozzle end",
601
+ 0,
602
+ )
603
+
604
+ def __repr__(self) -> str:
605
+ return "<{}: {} {}>".format(
606
+ self.__class__.__name__, self._config.display_name, id(self)
607
+ )
608
+
609
+ def as_dict(self) -> "Pipette.DictType":
610
+ self._config_as_dict.update(
611
+ {
612
+ "current_volume": self.current_volume,
613
+ "available_volume": self.available_volume,
614
+ "name": self.name,
615
+ "model": self.model,
616
+ "pipette_id": self.pipette_id,
617
+ "has_tip": self.has_tip,
618
+ "working_volume": self.working_volume,
619
+ "aspirate_flow_rate": self.aspirate_flow_rate,
620
+ "dispense_flow_rate": self.dispense_flow_rate,
621
+ "blow_out_flow_rate": self.blow_out_flow_rate,
622
+ "default_aspirate_flow_rates": self.aspirate_flow_rates_lookup,
623
+ "default_blow_out_flow_rates": self.blow_out_flow_rates_lookup,
624
+ "default_dispense_flow_rates": self.dispense_flow_rates_lookup,
625
+ "tip_length": self.current_tip_length,
626
+ "return_tip_height": self.active_tip_settings.default_return_tip_height,
627
+ "tip_overlap": self.tip_overlap["v0"],
628
+ "versioned_tip_overlap": self.tip_overlap,
629
+ "back_compat_names": self._config.pipette_backcompat_names,
630
+ "supported_tips": self.liquid_class.supported_tips,
631
+ }
632
+ )
633
+ return self._config_as_dict
634
+
635
+ def set_liquid_class_by_name(self, class_name: str) -> None:
636
+ """Change the currently active liquid class."""
637
+ if self.current_volume > 0:
638
+ raise CommandPreconditionViolated(
639
+ "Cannot switch liquid classes when liquid is in the tip"
640
+ )
641
+ if class_name != "default":
642
+ raise InvalidLiquidClassName(
643
+ message=f"Liquid class {class_name} is not valid for {self._config.display_name}"
644
+ )
645
+
646
+
647
+ def _reload_and_check_skip(
648
+ new_config: PipetteConfigurations,
649
+ attached_instr: Pipette,
650
+ pipette_offset: PipetteOffsetByPipetteMount,
651
+ use_old_aspiration_functions: bool,
652
+ ) -> Tuple[Pipette, bool]:
653
+ # Once we have determined that the new and attached pipettes
654
+ # are similar enough that we might skip, see if the configs
655
+ # match closely enough.
656
+ # Returns a pipette object and True if we may skip hw reconfig
657
+ if (
658
+ new_config == attached_instr.config
659
+ and pipette_offset == attached_instr._pipette_offset
660
+ ):
661
+ # Same config, good enough
662
+ return attached_instr, True
663
+ else:
664
+ newdict = new_config.model_dump()
665
+ olddict = attached_instr.config.model_dump()
666
+ changed: Set[str] = set()
667
+ for k in newdict.keys():
668
+ if newdict[k] != olddict[k]:
669
+ changed.add(k)
670
+ if changed.intersection(RECONFIG_KEYS):
671
+ # Something has changed that requires reconfig
672
+ p = Pipette(
673
+ new_config,
674
+ pipette_offset,
675
+ attached_instr._pipette_id,
676
+ use_old_aspiration_functions,
677
+ )
678
+ p.act_as(attached_instr.acting_as)
679
+ return p, False
680
+ # Good to skip
681
+ return attached_instr, True
682
+
683
+
684
+ def load_from_config_and_check_skip(
685
+ config: Optional[PipetteConfigurations],
686
+ attached: Optional[Pipette],
687
+ requested: Optional[PipetteName],
688
+ serial: Optional[str],
689
+ pipette_offset: PipetteOffsetByPipetteMount,
690
+ use_old_aspiration_functions: bool,
691
+ ) -> Tuple[Optional[Pipette], bool]:
692
+ """
693
+ Given the pipette config for an attached pipette (if any) freshly read
694
+ from disk, and any attached instruments,
695
+
696
+ - Compare the new and configured pipette configs
697
+ - Load the new configs if they differ
698
+ - Return a bool indicating whether hardware reconfiguration may be
699
+ skipped
700
+ """
701
+
702
+ if not config and not attached:
703
+ # nothing attached now, nothing used to be attached, nothing
704
+ # to reconfigure
705
+ return attached, True
706
+
707
+ if config and attached:
708
+ # something was attached and something is attached. are they
709
+ # the same? we can tell by comparing serials
710
+ if serial == attached.pipette_id:
711
+ if requested:
712
+ # if there is an explicit instrument request, in addition
713
+ # to checking if the old and new responses are the same
714
+ # we also have to make sure the old pipette is properly
715
+ # configured to the request
716
+ if requested == str(attached.acting_as):
717
+ # similar enough to check
718
+ return _reload_and_check_skip(
719
+ config, attached, pipette_offset, use_old_aspiration_functions
720
+ )
721
+ else:
722
+ # if there is no request, make sure that the old pipette
723
+ # did not have backcompat applied
724
+ if str(attached.acting_as) == attached.name:
725
+ # similar enough to check
726
+ return _reload_and_check_skip(
727
+ config, attached, pipette_offset, use_old_aspiration_functions
728
+ )
729
+
730
+ if config:
731
+ return (
732
+ Pipette(config, pipette_offset, serial, use_old_aspiration_functions),
733
+ False,
734
+ )
735
+ else:
736
+ return None, False
737
+
738
+
739
+ def _build_splits(pipette: Pipette) -> Optional[MoveSplit]:
740
+ if pip_types.Quirks.needsUnstick in pipette.config.quirks:
741
+ return MoveSplit(
742
+ split_distance=1,
743
+ split_current=1.75,
744
+ split_speed=1,
745
+ after_time=1800,
746
+ fullstep=True,
747
+ )
748
+ else:
749
+ return None
750
+
751
+
752
+ def generate_hardware_configs(
753
+ pipette: Optional[Pipette], robot_config: RobotConfig, revision: BoardRevision
754
+ ) -> InstrumentHardwareConfigs:
755
+ """
756
+ Fuse robot and pipette configuration to generate commands to send to
757
+ the motor driver if required
758
+ """
759
+ if pipette:
760
+ return {
761
+ "steps_per_mm": pipette.config.mount_configurations.stepsPerMM,
762
+ "home_pos": pipette.config.mount_configurations.homePosition,
763
+ "max_travel": pipette.config.mount_configurations.travelDistance,
764
+ "idle_current": pipette.plunger_motor_current.idle,
765
+ "splits": _build_splits(pipette),
766
+ }
767
+ else:
768
+ dpcs = robot_config.default_pipette_configs
769
+ return {
770
+ "steps_per_mm": dpcs["stepsPerMM"],
771
+ "home_pos": dpcs["homePosition"],
772
+ "max_travel": dpcs["maxTravel"],
773
+ "idle_current": robot_configs.current_for_revision(
774
+ robot_config.low_current, revision
775
+ )["B"],
776
+ "splits": None,
777
+ }