opentrons 8.3.2__py2.py3-none-any.whl → 8.4.0__py2.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 (196) hide show
  1. opentrons/calibration_storage/ot2/mark_bad_calibration.py +2 -0
  2. opentrons/calibration_storage/ot2/tip_length.py +6 -6
  3. opentrons/config/advanced_settings.py +9 -11
  4. opentrons/config/feature_flags.py +0 -4
  5. opentrons/config/reset.py +7 -2
  6. opentrons/drivers/asyncio/communication/__init__.py +2 -0
  7. opentrons/drivers/asyncio/communication/async_serial.py +4 -0
  8. opentrons/drivers/asyncio/communication/errors.py +41 -8
  9. opentrons/drivers/asyncio/communication/serial_connection.py +36 -10
  10. opentrons/drivers/flex_stacker/__init__.py +9 -3
  11. opentrons/drivers/flex_stacker/abstract.py +140 -15
  12. opentrons/drivers/flex_stacker/driver.py +593 -47
  13. opentrons/drivers/flex_stacker/errors.py +64 -0
  14. opentrons/drivers/flex_stacker/simulator.py +222 -24
  15. opentrons/drivers/flex_stacker/types.py +211 -15
  16. opentrons/drivers/flex_stacker/utils.py +19 -0
  17. opentrons/execute.py +4 -2
  18. opentrons/hardware_control/api.py +5 -0
  19. opentrons/hardware_control/backends/flex_protocol.py +4 -0
  20. opentrons/hardware_control/backends/ot3controller.py +12 -1
  21. opentrons/hardware_control/backends/ot3simulator.py +3 -0
  22. opentrons/hardware_control/backends/subsystem_manager.py +8 -4
  23. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +10 -6
  24. opentrons/hardware_control/instruments/ot3/pipette_handler.py +59 -6
  25. opentrons/hardware_control/modules/__init__.py +12 -1
  26. opentrons/hardware_control/modules/absorbance_reader.py +11 -9
  27. opentrons/hardware_control/modules/flex_stacker.py +498 -0
  28. opentrons/hardware_control/modules/heater_shaker.py +12 -10
  29. opentrons/hardware_control/modules/magdeck.py +5 -1
  30. opentrons/hardware_control/modules/tempdeck.py +5 -1
  31. opentrons/hardware_control/modules/thermocycler.py +15 -14
  32. opentrons/hardware_control/modules/types.py +191 -1
  33. opentrons/hardware_control/modules/utils.py +3 -0
  34. opentrons/hardware_control/motion_utilities.py +20 -0
  35. opentrons/hardware_control/ot3api.py +145 -15
  36. opentrons/hardware_control/protocols/liquid_handler.py +47 -1
  37. opentrons/hardware_control/types.py +6 -0
  38. opentrons/legacy_commands/commands.py +102 -5
  39. opentrons/legacy_commands/helpers.py +74 -1
  40. opentrons/legacy_commands/types.py +33 -2
  41. opentrons/protocol_api/__init__.py +2 -0
  42. opentrons/protocol_api/_liquid.py +39 -8
  43. opentrons/protocol_api/_liquid_properties.py +20 -19
  44. opentrons/protocol_api/_transfer_liquid_validation.py +91 -0
  45. opentrons/protocol_api/core/common.py +3 -1
  46. opentrons/protocol_api/core/engine/deck_conflict.py +11 -1
  47. opentrons/protocol_api/core/engine/instrument.py +1356 -107
  48. opentrons/protocol_api/core/engine/labware.py +8 -4
  49. opentrons/protocol_api/core/engine/load_labware_params.py +68 -10
  50. opentrons/protocol_api/core/engine/module_core.py +118 -2
  51. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +6 -14
  52. opentrons/protocol_api/core/engine/protocol.py +253 -11
  53. opentrons/protocol_api/core/engine/stringify.py +19 -8
  54. opentrons/protocol_api/core/engine/transfer_components_executor.py +858 -0
  55. opentrons/protocol_api/core/engine/well.py +73 -5
  56. opentrons/protocol_api/core/instrument.py +71 -21
  57. opentrons/protocol_api/core/labware.py +6 -2
  58. opentrons/protocol_api/core/legacy/labware_offset_provider.py +7 -3
  59. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +76 -49
  60. opentrons/protocol_api/core/legacy/legacy_labware_core.py +8 -4
  61. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +36 -0
  62. opentrons/protocol_api/core/legacy/legacy_well_core.py +27 -2
  63. opentrons/protocol_api/core/legacy/load_info.py +4 -12
  64. opentrons/protocol_api/core/legacy/module_geometry.py +6 -1
  65. opentrons/protocol_api/core/legacy/well_geometry.py +3 -3
  66. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +73 -23
  67. opentrons/protocol_api/core/module.py +43 -0
  68. opentrons/protocol_api/core/protocol.py +33 -0
  69. opentrons/protocol_api/core/well.py +23 -2
  70. opentrons/protocol_api/instrument_context.py +454 -150
  71. opentrons/protocol_api/labware.py +98 -50
  72. opentrons/protocol_api/module_contexts.py +140 -0
  73. opentrons/protocol_api/protocol_context.py +163 -19
  74. opentrons/protocol_api/validation.py +51 -41
  75. opentrons/protocol_engine/__init__.py +21 -2
  76. opentrons/protocol_engine/actions/actions.py +5 -5
  77. opentrons/protocol_engine/clients/sync_client.py +6 -0
  78. opentrons/protocol_engine/commands/__init__.py +66 -36
  79. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +0 -1
  80. opentrons/protocol_engine/commands/air_gap_in_place.py +3 -2
  81. opentrons/protocol_engine/commands/aspirate.py +6 -2
  82. opentrons/protocol_engine/commands/aspirate_in_place.py +3 -1
  83. opentrons/protocol_engine/commands/aspirate_while_tracking.py +210 -0
  84. opentrons/protocol_engine/commands/blow_out.py +2 -0
  85. opentrons/protocol_engine/commands/blow_out_in_place.py +4 -1
  86. opentrons/protocol_engine/commands/command_unions.py +102 -33
  87. opentrons/protocol_engine/commands/configure_for_volume.py +3 -0
  88. opentrons/protocol_engine/commands/dispense.py +3 -1
  89. opentrons/protocol_engine/commands/dispense_in_place.py +3 -0
  90. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  91. opentrons/protocol_engine/commands/drop_tip.py +23 -1
  92. opentrons/protocol_engine/commands/flex_stacker/__init__.py +106 -0
  93. opentrons/protocol_engine/commands/flex_stacker/close_latch.py +72 -0
  94. opentrons/protocol_engine/commands/flex_stacker/common.py +15 -0
  95. opentrons/protocol_engine/commands/flex_stacker/empty.py +161 -0
  96. opentrons/protocol_engine/commands/flex_stacker/fill.py +164 -0
  97. opentrons/protocol_engine/commands/flex_stacker/open_latch.py +70 -0
  98. opentrons/protocol_engine/commands/flex_stacker/prepare_shuttle.py +112 -0
  99. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +394 -0
  100. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +190 -0
  101. opentrons/protocol_engine/commands/flex_stacker/store.py +291 -0
  102. opentrons/protocol_engine/commands/generate_command_schema.py +31 -2
  103. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  104. opentrons/protocol_engine/commands/liquid_probe.py +27 -13
  105. opentrons/protocol_engine/commands/load_labware.py +42 -39
  106. opentrons/protocol_engine/commands/load_lid.py +21 -13
  107. opentrons/protocol_engine/commands/load_lid_stack.py +130 -47
  108. opentrons/protocol_engine/commands/load_module.py +18 -17
  109. opentrons/protocol_engine/commands/load_pipette.py +3 -0
  110. opentrons/protocol_engine/commands/move_labware.py +139 -20
  111. opentrons/protocol_engine/commands/move_to_well.py +5 -11
  112. opentrons/protocol_engine/commands/pick_up_tip.py +5 -2
  113. opentrons/protocol_engine/commands/pipetting_common.py +159 -8
  114. opentrons/protocol_engine/commands/prepare_to_aspirate.py +15 -5
  115. opentrons/protocol_engine/commands/{evotip_dispense.py → pressure_dispense.py} +33 -34
  116. opentrons/protocol_engine/commands/reload_labware.py +6 -19
  117. opentrons/protocol_engine/commands/{evotip_seal_pipette.py → seal_pipette_to_tip.py} +97 -76
  118. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +3 -1
  119. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +6 -1
  120. opentrons/protocol_engine/commands/{evotip_unseal_pipette.py → unseal_pipette_from_tip.py} +31 -40
  121. opentrons/protocol_engine/errors/__init__.py +10 -0
  122. opentrons/protocol_engine/errors/exceptions.py +62 -0
  123. opentrons/protocol_engine/execution/equipment.py +123 -106
  124. opentrons/protocol_engine/execution/labware_movement.py +8 -6
  125. opentrons/protocol_engine/execution/pipetting.py +235 -25
  126. opentrons/protocol_engine/execution/tip_handler.py +82 -32
  127. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  128. opentrons/protocol_engine/protocol_engine.py +22 -13
  129. opentrons/protocol_engine/resources/deck_configuration_provider.py +98 -2
  130. opentrons/protocol_engine/resources/deck_data_provider.py +1 -1
  131. opentrons/protocol_engine/resources/labware_data_provider.py +32 -12
  132. opentrons/protocol_engine/resources/labware_validation.py +7 -5
  133. opentrons/protocol_engine/slot_standardization.py +11 -23
  134. opentrons/protocol_engine/state/addressable_areas.py +84 -46
  135. opentrons/protocol_engine/state/frustum_helpers.py +36 -14
  136. opentrons/protocol_engine/state/geometry.py +892 -227
  137. opentrons/protocol_engine/state/labware.py +252 -55
  138. opentrons/protocol_engine/state/module_substates/__init__.py +4 -0
  139. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +68 -0
  140. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +22 -0
  141. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +13 -0
  142. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +20 -0
  143. opentrons/protocol_engine/state/modules.py +210 -67
  144. opentrons/protocol_engine/state/pipettes.py +54 -0
  145. opentrons/protocol_engine/state/state.py +1 -1
  146. opentrons/protocol_engine/state/tips.py +14 -0
  147. opentrons/protocol_engine/state/update_types.py +180 -25
  148. opentrons/protocol_engine/state/wells.py +55 -9
  149. opentrons/protocol_engine/types/__init__.py +300 -0
  150. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  151. opentrons/protocol_engine/types/command_annotations.py +53 -0
  152. opentrons/protocol_engine/types/deck_configuration.py +72 -0
  153. opentrons/protocol_engine/types/execution.py +96 -0
  154. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  155. opentrons/protocol_engine/types/instrument.py +47 -0
  156. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  157. opentrons/protocol_engine/types/labware.py +111 -0
  158. opentrons/protocol_engine/types/labware_movement.py +22 -0
  159. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  160. opentrons/protocol_engine/types/labware_offset_vector.py +33 -0
  161. opentrons/protocol_engine/types/liquid.py +40 -0
  162. opentrons/protocol_engine/types/liquid_class.py +59 -0
  163. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  164. opentrons/protocol_engine/types/liquid_level_detection.py +131 -0
  165. opentrons/protocol_engine/types/location.py +194 -0
  166. opentrons/protocol_engine/types/module.py +301 -0
  167. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  168. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  169. opentrons/protocol_engine/types/tip.py +18 -0
  170. opentrons/protocol_engine/types/util.py +21 -0
  171. opentrons/protocol_engine/types/well_position.py +124 -0
  172. opentrons/protocol_reader/extract_labware_definitions.py +7 -3
  173. opentrons/protocol_reader/file_format_validator.py +5 -3
  174. opentrons/protocol_runner/json_translator.py +4 -2
  175. opentrons/protocol_runner/legacy_command_mapper.py +6 -2
  176. opentrons/protocol_runner/run_orchestrator.py +4 -1
  177. opentrons/protocols/advanced_control/transfers/common.py +48 -1
  178. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +204 -0
  179. opentrons/protocols/api_support/definitions.py +1 -1
  180. opentrons/protocols/api_support/instrument.py +16 -3
  181. opentrons/protocols/labware.py +27 -23
  182. opentrons/protocols/models/__init__.py +0 -21
  183. opentrons/simulate.py +4 -2
  184. opentrons/types.py +20 -7
  185. opentrons/util/logging_config.py +94 -25
  186. opentrons/util/logging_queue_handler.py +61 -0
  187. {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/METADATA +4 -4
  188. {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/RECORD +192 -151
  189. opentrons/calibration_storage/ot2/models/defaults.py +0 -0
  190. opentrons/calibration_storage/ot3/models/defaults.py +0 -0
  191. opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
  192. opentrons/protocol_engine/types.py +0 -1311
  193. {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/LICENSE +0 -0
  194. {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/WHEEL +0 -0
  195. {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/entry_points.txt +0 -0
  196. {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/top_level.txt +0 -0
@@ -14,6 +14,7 @@ and/or schema generation.
14
14
  """
15
15
 
16
16
  from . import absorbance_reader
17
+ from . import flex_stacker
17
18
  from . import heater_shaker
18
19
  from . import magnetic_module
19
20
  from . import temperature_module
@@ -60,6 +61,14 @@ from .aspirate import (
60
61
  AspirateCommandType,
61
62
  )
62
63
 
64
+ from .aspirate_while_tracking import (
65
+ AspirateWhileTracking,
66
+ AspirateWhileTrackingParams,
67
+ AspirateWhileTrackingCreate,
68
+ AspirateWhileTrackingResult,
69
+ AspirateWhileTrackingCommandType,
70
+ )
71
+
63
72
  from .aspirate_in_place import (
64
73
  AspirateInPlace,
65
74
  AspirateInPlaceParams,
@@ -92,6 +101,14 @@ from .dispense import (
92
101
  DispenseCommandType,
93
102
  )
94
103
 
104
+ from .dispense_while_tracking import (
105
+ DispenseWhileTracking,
106
+ DispenseWhileTrackingParams,
107
+ DispenseWhileTrackingCreate,
108
+ DispenseWhileTrackingResult,
109
+ DispenseWhileTrackingCommandType,
110
+ )
111
+
95
112
  from .dispense_in_place import (
96
113
  DispenseInPlace,
97
114
  DispenseInPlaceParams,
@@ -380,26 +397,26 @@ from .liquid_probe import (
380
397
  TryLiquidProbeCommandType,
381
398
  )
382
399
 
383
- from .evotip_seal_pipette import (
384
- EvotipSealPipette,
385
- EvotipSealPipetteParams,
386
- EvotipSealPipetteCreate,
387
- EvotipSealPipetteResult,
388
- EvotipSealPipetteCommandType,
400
+ from .seal_pipette_to_tip import (
401
+ SealPipetteToTip,
402
+ SealPipetteToTipParams,
403
+ SealPipetteToTipCreate,
404
+ SealPipetteToTipResult,
405
+ SealPipetteToTipCommandType,
389
406
  )
390
- from .evotip_unseal_pipette import (
391
- EvotipUnsealPipette,
392
- EvotipUnsealPipetteParams,
393
- EvotipUnsealPipetteCreate,
394
- EvotipUnsealPipetteResult,
395
- EvotipUnsealPipetteCommandType,
407
+ from .unseal_pipette_from_tip import (
408
+ UnsealPipetteFromTip,
409
+ UnsealPipetteFromTipParams,
410
+ UnsealPipetteFromTipCreate,
411
+ UnsealPipetteFromTipResult,
412
+ UnsealPipetteFromTipCommandType,
396
413
  )
397
- from .evotip_dispense import (
398
- EvotipDispense,
399
- EvotipDispenseParams,
400
- EvotipDispenseCreate,
401
- EvotipDispenseResult,
402
- EvotipDispenseCommandType,
414
+ from .pressure_dispense import (
415
+ PressureDispense,
416
+ PressureDispenseParams,
417
+ PressureDispenseCreate,
418
+ PressureDispenseResult,
419
+ PressureDispenseCommandType,
403
420
  )
404
421
 
405
422
  __all__ = [
@@ -435,6 +452,12 @@ __all__ = [
435
452
  "AspirateParams",
436
453
  "AspirateResult",
437
454
  "AspirateCommandType",
455
+ # aspirate while tracking command models
456
+ "AspirateWhileTracking",
457
+ "AspirateWhileTrackingCreate",
458
+ "AspirateWhileTrackingParams",
459
+ "AspirateWhileTrackingResult",
460
+ "AspirateWhileTrackingCommandType",
438
461
  # aspirate in place command models
439
462
  "AspirateInPlace",
440
463
  "AspirateInPlaceCreate",
@@ -459,6 +482,12 @@ __all__ = [
459
482
  "DispenseParams",
460
483
  "DispenseResult",
461
484
  "DispenseCommandType",
485
+ # dispense while tracking command models
486
+ "DispenseWhileTracking",
487
+ "DispenseWhileTrackingCreate",
488
+ "DispenseWhileTrackingParams",
489
+ "DispenseWhileTrackingResult",
490
+ "DispenseWhileTrackingCommandType",
462
491
  # dispense in place command models
463
492
  "DispenseInPlace",
464
493
  "DispenseInPlaceCreate",
@@ -636,6 +665,7 @@ __all__ = [
636
665
  # hardware control command models
637
666
  # hardware module command bundles
638
667
  "absorbance_reader",
668
+ "flex_stacker",
639
669
  "heater_shaker",
640
670
  "magnetic_module",
641
671
  "temperature_module",
@@ -692,22 +722,22 @@ __all__ = [
692
722
  "TryLiquidProbeCreate",
693
723
  "TryLiquidProbeResult",
694
724
  "TryLiquidProbeCommandType",
695
- # evotip seal command bundle
696
- "EvotipSealPipette",
697
- "EvotipSealPipetteParams",
698
- "EvotipSealPipetteCreate",
699
- "EvotipSealPipetteResult",
700
- "EvotipSealPipetteCommandType",
701
- # evotip unseal command bundle
702
- "EvotipUnsealPipette",
703
- "EvotipUnsealPipetteParams",
704
- "EvotipUnsealPipetteCreate",
705
- "EvotipUnsealPipetteResult",
706
- "EvotipUnsealPipetteCommandType",
707
- # evotip dispense command bundle
708
- "EvotipDispense",
709
- "EvotipDispenseParams",
710
- "EvotipDispenseCreate",
711
- "EvotipDispenseResult",
712
- "EvotipDispenseCommandType",
725
+ # seal command bundle
726
+ "SealPipetteToTip",
727
+ "SealPipetteToTipParams",
728
+ "SealPipetteToTipCreate",
729
+ "SealPipetteToTipResult",
730
+ "SealPipetteToTipCommandType",
731
+ # unseal command bundle
732
+ "UnsealPipetteFromTip",
733
+ "UnsealPipetteFromTipParams",
734
+ "UnsealPipetteFromTipCreate",
735
+ "UnsealPipetteFromTipResult",
736
+ "UnsealPipetteFromTipCommandType",
737
+ # pressure dispense command bundle
738
+ "PressureDispense",
739
+ "PressureDispenseParams",
740
+ "PressureDispenseCreate",
741
+ "PressureDispenseResult",
742
+ "PressureDispenseCommandType",
713
743
  ]
@@ -33,7 +33,6 @@ from .read import (
33
33
 
34
34
 
35
35
  __all__ = [
36
- "MoveLidResult",
37
36
  # absorbanace_reader/closeLid
38
37
  "CloseLidCommandType",
39
38
  "CloseLidParams",
@@ -14,6 +14,7 @@ from .pipetting_common import (
14
14
  FlowRateMixin,
15
15
  BaseLiquidHandlingResult,
16
16
  OverpressureError,
17
+ DEFAULT_CORRECTION_VOLUME,
17
18
  )
18
19
  from .command import (
19
20
  AbstractCommandImpl,
@@ -84,9 +85,8 @@ class AirGapInPlaceImplementation(
84
85
  PipetteNotReadyToAirGapError: pipette plunger is not ready.
85
86
  """
86
87
  ready_to_aspirate = self._pipetting.get_is_ready_to_aspirate(
87
- pipette_id=params.pipetteId,
88
+ pipette_id=params.pipetteId
88
89
  )
89
-
90
90
  if not ready_to_aspirate:
91
91
  raise PipetteNotReadyToAspirateError(
92
92
  "Pipette cannot air gap in place because of a previous blow out."
@@ -103,6 +103,7 @@ class AirGapInPlaceImplementation(
103
103
  volume=params.volume,
104
104
  flow_rate=params.flowRate,
105
105
  command_note_adder=self._command_note_adder,
106
+ correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME,
106
107
  )
107
108
  except PipetteOverpressureError as e:
108
109
  return DefinedErrorData(
@@ -12,6 +12,7 @@ from .pipetting_common import (
12
12
  BaseLiquidHandlingResult,
13
13
  aspirate_in_place,
14
14
  prepare_for_aspirate,
15
+ DEFAULT_CORRECTION_VOLUME,
15
16
  )
16
17
  from .movement_common import (
17
18
  LiquidHandlingWellLocationMixin,
@@ -47,7 +48,10 @@ AspirateCommandType = Literal["aspirate"]
47
48
 
48
49
 
49
50
  class AspirateParams(
50
- PipetteIdMixin, AspirateVolumeMixin, FlowRateMixin, LiquidHandlingWellLocationMixin
51
+ PipetteIdMixin,
52
+ AspirateVolumeMixin,
53
+ FlowRateMixin,
54
+ LiquidHandlingWellLocationMixin,
51
55
  ):
52
56
  """Parameters required to aspirate from a specific well."""
53
57
 
@@ -148,7 +152,6 @@ class AspirateImplementation(AbstractCommandImpl[AspirateParams, _ExecuteReturn]
148
152
  labware_id=labware_id,
149
153
  well_name=well_name,
150
154
  )
151
-
152
155
  move_result = await move_to_well(
153
156
  movement=self._movement,
154
157
  model_utils=self._model_utils,
@@ -179,6 +182,7 @@ class AspirateImplementation(AbstractCommandImpl[AspirateParams, _ExecuteReturn]
179
182
  command_note_adder=self._command_note_adder,
180
183
  pipetting=self._pipetting,
181
184
  model_utils=self._model_utils,
185
+ correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME,
182
186
  )
183
187
  state_update.append(aspirate_result.state_update)
184
188
  if isinstance(aspirate_result, DefinedErrorData):
@@ -13,6 +13,7 @@ from .pipetting_common import (
13
13
  BaseLiquidHandlingResult,
14
14
  OverpressureError,
15
15
  aspirate_in_place,
16
+ DEFAULT_CORRECTION_VOLUME,
16
17
  )
17
18
  from .command import (
18
19
  AbstractCommandImpl,
@@ -82,7 +83,7 @@ class AspirateInPlaceImplementation(
82
83
  PipetteNotReadyToAspirateError: pipette plunger is not ready.
83
84
  """
84
85
  ready_to_aspirate = self._pipetting.get_is_ready_to_aspirate(
85
- pipette_id=params.pipetteId,
86
+ pipette_id=params.pipetteId
86
87
  )
87
88
  if not ready_to_aspirate:
88
89
  raise PipetteNotReadyToAspirateError(
@@ -108,6 +109,7 @@ class AspirateInPlaceImplementation(
108
109
  command_note_adder=self._command_note_adder,
109
110
  pipetting=self._pipetting,
110
111
  model_utils=self._model_utils,
112
+ correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME,
111
113
  )
112
114
  if isinstance(result, DefinedErrorData):
113
115
  if (
@@ -0,0 +1,210 @@
1
+ """Aspirate command request, result, and implementation models."""
2
+
3
+ from __future__ import annotations
4
+ from typing import TYPE_CHECKING, Optional, Type, Union
5
+ from typing_extensions import Literal
6
+
7
+ from .pipetting_common import (
8
+ OverpressureError,
9
+ PipetteIdMixin,
10
+ AspirateVolumeMixin,
11
+ FlowRateMixin,
12
+ BaseLiquidHandlingResult,
13
+ aspirate_while_tracking,
14
+ )
15
+ from .movement_common import (
16
+ LiquidHandlingWellLocationMixin,
17
+ DestinationPositionResult,
18
+ StallOrCollisionError,
19
+ move_to_well,
20
+ )
21
+ from .command import (
22
+ AbstractCommandImpl,
23
+ BaseCommand,
24
+ BaseCommandCreate,
25
+ DefinedErrorData,
26
+ SuccessData,
27
+ )
28
+ from ..state.update_types import StateUpdate
29
+ from ..errors.exceptions import PipetteNotReadyToAspirateError
30
+ from opentrons.hardware_control import HardwareControlAPI
31
+ from ..state.update_types import CLEAR
32
+ from ..types import DeckPoint
33
+
34
+ if TYPE_CHECKING:
35
+ from ..execution import PipettingHandler, GantryMover, MovementHandler
36
+ from ..resources import ModelUtils
37
+ from ..state.state import StateView
38
+ from ..notes import CommandNoteAdder
39
+
40
+
41
+ AspirateWhileTrackingCommandType = Literal["aspirateWhileTracking"]
42
+
43
+
44
+ class AspirateWhileTrackingParams(
45
+ PipetteIdMixin,
46
+ AspirateVolumeMixin,
47
+ FlowRateMixin,
48
+ LiquidHandlingWellLocationMixin,
49
+ ):
50
+ """Parameters required to aspirate from a specific well."""
51
+
52
+ pass
53
+
54
+
55
+ class AspirateWhileTrackingResult(BaseLiquidHandlingResult, DestinationPositionResult):
56
+ """Result data from execution of an Aspirate command."""
57
+
58
+ pass
59
+
60
+
61
+ _ExecuteReturn = Union[
62
+ SuccessData[AspirateWhileTrackingResult],
63
+ DefinedErrorData[OverpressureError] | DefinedErrorData[StallOrCollisionError],
64
+ ]
65
+
66
+
67
+ class AspirateWhileTrackingImplementation(
68
+ AbstractCommandImpl[AspirateWhileTrackingParams, _ExecuteReturn]
69
+ ):
70
+ """AspirateWhileTracking command implementation."""
71
+
72
+ def __init__(
73
+ self,
74
+ pipetting: PipettingHandler,
75
+ state_view: StateView,
76
+ hardware_api: HardwareControlAPI,
77
+ command_note_adder: CommandNoteAdder,
78
+ model_utils: ModelUtils,
79
+ gantry_mover: GantryMover,
80
+ movement: MovementHandler,
81
+ **kwargs: object,
82
+ ) -> None:
83
+ self._pipetting = pipetting
84
+ self._state_view = state_view
85
+ self._hardware_api = hardware_api
86
+ self._command_note_adder = command_note_adder
87
+ self._model_utils = model_utils
88
+ self._gantry_mover = gantry_mover
89
+ self._movement = movement
90
+
91
+ async def execute(self, params: AspirateWhileTrackingParams) -> _ExecuteReturn:
92
+ """Move to and aspirate from the requested well.
93
+
94
+ Raises:
95
+ TipNotAttachedError: if no tip is attached to the pipette.
96
+ PipetteNotReadyToAspirateError: pipette plunger is not ready.
97
+ """
98
+ ready_to_aspirate = self._state_view.pipettes.get_ready_to_aspirate(
99
+ pipette_id=params.pipetteId
100
+ )
101
+ if not ready_to_aspirate:
102
+ raise PipetteNotReadyToAspirateError(
103
+ "Pipette cannot aspirate while tracking because of a previous blow out."
104
+ " The first aspirate following a blow-out must be from a specific well"
105
+ " so the plunger can be reset in a known safe position."
106
+ )
107
+ state_update = StateUpdate()
108
+
109
+ move_result = await move_to_well(
110
+ movement=self._movement,
111
+ model_utils=self._model_utils,
112
+ pipette_id=params.pipetteId,
113
+ labware_id=params.labwareId,
114
+ well_name=params.wellName,
115
+ well_location=params.wellLocation,
116
+ operation_volume=-params.volume,
117
+ )
118
+ state_update.append(move_result.state_update)
119
+ if isinstance(move_result, DefinedErrorData):
120
+ return DefinedErrorData(
121
+ public=move_result.public, state_update=state_update
122
+ )
123
+
124
+ aspirate_result = await aspirate_while_tracking(
125
+ pipette_id=params.pipetteId,
126
+ labware_id=params.labwareId,
127
+ well_name=params.wellName,
128
+ volume=params.volume,
129
+ flow_rate=params.flowRate,
130
+ location_if_error={
131
+ "retryLocation": (
132
+ move_result.public.position.x,
133
+ move_result.public.position.y,
134
+ move_result.public.position.z,
135
+ )
136
+ },
137
+ command_note_adder=self._command_note_adder,
138
+ pipetting=self._pipetting,
139
+ model_utils=self._model_utils,
140
+ )
141
+ position_after_aspirate = await self._gantry_mover.get_position(
142
+ params.pipetteId
143
+ )
144
+ result_deck_point = DeckPoint.model_construct(
145
+ x=position_after_aspirate.x,
146
+ y=position_after_aspirate.y,
147
+ z=position_after_aspirate.z,
148
+ )
149
+ if isinstance(aspirate_result, DefinedErrorData):
150
+ return DefinedErrorData(
151
+ public=aspirate_result.public,
152
+ state_update=aspirate_result.state_update.set_liquid_operated(
153
+ labware_id=params.labwareId,
154
+ well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
155
+ params.labwareId,
156
+ params.wellName,
157
+ params.pipetteId,
158
+ ),
159
+ volume_added=CLEAR,
160
+ ),
161
+ state_update_if_false_positive=aspirate_result.state_update_if_false_positive,
162
+ )
163
+
164
+ return SuccessData(
165
+ public=AspirateWhileTrackingResult(
166
+ volume=aspirate_result.public.volume,
167
+ position=result_deck_point,
168
+ ),
169
+ state_update=aspirate_result.state_update.set_liquid_operated(
170
+ labware_id=params.labwareId,
171
+ well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
172
+ params.labwareId,
173
+ params.wellName,
174
+ params.pipetteId,
175
+ ),
176
+ volume_added=-aspirate_result.public.volume
177
+ * self._state_view.geometry.get_nozzles_per_well(
178
+ params.labwareId,
179
+ params.wellName,
180
+ params.pipetteId,
181
+ ),
182
+ ),
183
+ )
184
+
185
+
186
+ class AspirateWhileTracking(
187
+ BaseCommand[
188
+ AspirateWhileTrackingParams,
189
+ AspirateWhileTrackingResult,
190
+ OverpressureError | StallOrCollisionError,
191
+ ]
192
+ ):
193
+ """AspirateWhileTracking command model."""
194
+
195
+ commandType: AspirateWhileTrackingCommandType = "aspirateWhileTracking"
196
+ params: AspirateWhileTrackingParams
197
+ result: Optional[AspirateWhileTrackingResult] = None
198
+
199
+ _ImplementationCls: Type[
200
+ AspirateWhileTrackingImplementation
201
+ ] = AspirateWhileTrackingImplementation
202
+
203
+
204
+ class AspirateWhileTrackingCreate(BaseCommandCreate[AspirateWhileTrackingParams]):
205
+ """Create aspirateWhileTracking command request model."""
206
+
207
+ commandType: AspirateWhileTrackingCommandType = "aspirateWhileTracking"
208
+ params: AspirateWhileTrackingParams
209
+
210
+ _CommandCls: Type[AspirateWhileTracking] = AspirateWhileTracking
@@ -115,6 +115,8 @@ class BlowOutImplementation(AbstractCommandImpl[BlowOutParams, _ExecuteReturn]):
115
115
  public=BlowOutResult(position=move_result.public.position),
116
116
  state_update=StateUpdate.reduce(
117
117
  move_result.state_update, blow_out_result.state_update
118
+ ).set_pipette_ready_to_aspirate(
119
+ pipette_id=params.pipetteId, ready_to_aspirate=False
118
120
  ),
119
121
  )
120
122
 
@@ -89,7 +89,10 @@ class BlowOutInPlaceImplementation(
89
89
  if isinstance(result, DefinedErrorData):
90
90
  return result
91
91
  return SuccessData(
92
- public=BlowOutInPlaceResult(), state_update=result.state_update
92
+ public=BlowOutInPlaceResult(),
93
+ state_update=result.state_update.set_pipette_ready_to_aspirate(
94
+ pipette_id=params.pipetteId, ready_to_aspirate=False
95
+ ),
93
96
  )
94
97
 
95
98