opentrons 8.3.1a1__py2.py3-none-any.whl → 8.4.0a1__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.
Files changed (192) 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 +19 -3
  39. opentrons/legacy_commands/helpers.py +15 -0
  40. opentrons/legacy_commands/types.py +3 -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 +1233 -65
  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/protocol.py +253 -11
  52. opentrons/protocol_api/core/engine/stringify.py +19 -8
  53. opentrons/protocol_api/core/engine/transfer_components_executor.py +853 -0
  54. opentrons/protocol_api/core/engine/well.py +60 -5
  55. opentrons/protocol_api/core/instrument.py +65 -19
  56. opentrons/protocol_api/core/labware.py +6 -2
  57. opentrons/protocol_api/core/legacy/labware_offset_provider.py +7 -3
  58. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +69 -21
  59. opentrons/protocol_api/core/legacy/legacy_labware_core.py +8 -4
  60. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +36 -0
  61. opentrons/protocol_api/core/legacy/legacy_well_core.py +25 -1
  62. opentrons/protocol_api/core/legacy/load_info.py +4 -12
  63. opentrons/protocol_api/core/legacy/module_geometry.py +6 -1
  64. opentrons/protocol_api/core/legacy/well_geometry.py +3 -3
  65. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +67 -21
  66. opentrons/protocol_api/core/module.py +43 -0
  67. opentrons/protocol_api/core/protocol.py +33 -0
  68. opentrons/protocol_api/core/well.py +21 -1
  69. opentrons/protocol_api/instrument_context.py +246 -123
  70. opentrons/protocol_api/labware.py +75 -11
  71. opentrons/protocol_api/module_contexts.py +140 -0
  72. opentrons/protocol_api/protocol_context.py +156 -16
  73. opentrons/protocol_api/validation.py +51 -41
  74. opentrons/protocol_engine/__init__.py +21 -2
  75. opentrons/protocol_engine/actions/actions.py +5 -5
  76. opentrons/protocol_engine/clients/sync_client.py +6 -0
  77. opentrons/protocol_engine/commands/__init__.py +30 -0
  78. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +0 -1
  79. opentrons/protocol_engine/commands/air_gap_in_place.py +3 -2
  80. opentrons/protocol_engine/commands/aspirate.py +6 -2
  81. opentrons/protocol_engine/commands/aspirate_in_place.py +3 -1
  82. opentrons/protocol_engine/commands/aspirate_while_tracking.py +237 -0
  83. opentrons/protocol_engine/commands/blow_out.py +2 -0
  84. opentrons/protocol_engine/commands/blow_out_in_place.py +4 -1
  85. opentrons/protocol_engine/commands/command_unions.py +69 -0
  86. opentrons/protocol_engine/commands/configure_for_volume.py +3 -0
  87. opentrons/protocol_engine/commands/dispense.py +3 -1
  88. opentrons/protocol_engine/commands/dispense_in_place.py +3 -0
  89. opentrons/protocol_engine/commands/dispense_while_tracking.py +240 -0
  90. opentrons/protocol_engine/commands/drop_tip.py +23 -1
  91. opentrons/protocol_engine/commands/evotip_dispense.py +6 -7
  92. opentrons/protocol_engine/commands/evotip_seal_pipette.py +24 -29
  93. opentrons/protocol_engine/commands/evotip_unseal_pipette.py +1 -7
  94. opentrons/protocol_engine/commands/flex_stacker/__init__.py +106 -0
  95. opentrons/protocol_engine/commands/flex_stacker/close_latch.py +72 -0
  96. opentrons/protocol_engine/commands/flex_stacker/common.py +15 -0
  97. opentrons/protocol_engine/commands/flex_stacker/empty.py +161 -0
  98. opentrons/protocol_engine/commands/flex_stacker/fill.py +164 -0
  99. opentrons/protocol_engine/commands/flex_stacker/open_latch.py +70 -0
  100. opentrons/protocol_engine/commands/flex_stacker/prepare_shuttle.py +112 -0
  101. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +394 -0
  102. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +190 -0
  103. opentrons/protocol_engine/commands/flex_stacker/store.py +288 -0
  104. opentrons/protocol_engine/commands/generate_command_schema.py +31 -2
  105. opentrons/protocol_engine/commands/labware_handling_common.py +24 -0
  106. opentrons/protocol_engine/commands/liquid_probe.py +21 -12
  107. opentrons/protocol_engine/commands/load_labware.py +42 -39
  108. opentrons/protocol_engine/commands/load_lid.py +21 -13
  109. opentrons/protocol_engine/commands/load_lid_stack.py +130 -47
  110. opentrons/protocol_engine/commands/load_module.py +18 -17
  111. opentrons/protocol_engine/commands/load_pipette.py +3 -0
  112. opentrons/protocol_engine/commands/move_labware.py +139 -20
  113. opentrons/protocol_engine/commands/pick_up_tip.py +5 -2
  114. opentrons/protocol_engine/commands/pipetting_common.py +154 -7
  115. opentrons/protocol_engine/commands/prepare_to_aspirate.py +17 -2
  116. opentrons/protocol_engine/commands/reload_labware.py +6 -19
  117. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +3 -1
  118. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +6 -1
  119. opentrons/protocol_engine/errors/__init__.py +8 -0
  120. opentrons/protocol_engine/errors/exceptions.py +50 -0
  121. opentrons/protocol_engine/execution/equipment.py +123 -106
  122. opentrons/protocol_engine/execution/labware_movement.py +8 -6
  123. opentrons/protocol_engine/execution/pipetting.py +233 -26
  124. opentrons/protocol_engine/execution/tip_handler.py +14 -5
  125. opentrons/protocol_engine/labware_offset_standardization.py +173 -0
  126. opentrons/protocol_engine/protocol_engine.py +22 -13
  127. opentrons/protocol_engine/resources/deck_configuration_provider.py +94 -2
  128. opentrons/protocol_engine/resources/deck_data_provider.py +1 -1
  129. opentrons/protocol_engine/resources/labware_data_provider.py +32 -12
  130. opentrons/protocol_engine/resources/labware_validation.py +7 -5
  131. opentrons/protocol_engine/slot_standardization.py +11 -23
  132. opentrons/protocol_engine/state/addressable_areas.py +84 -46
  133. opentrons/protocol_engine/state/frustum_helpers.py +26 -10
  134. opentrons/protocol_engine/state/geometry.py +683 -100
  135. opentrons/protocol_engine/state/labware.py +252 -55
  136. opentrons/protocol_engine/state/module_substates/__init__.py +4 -0
  137. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +68 -0
  138. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +22 -0
  139. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +13 -0
  140. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +20 -0
  141. opentrons/protocol_engine/state/modules.py +178 -52
  142. opentrons/protocol_engine/state/pipettes.py +54 -0
  143. opentrons/protocol_engine/state/state.py +1 -1
  144. opentrons/protocol_engine/state/tips.py +14 -0
  145. opentrons/protocol_engine/state/update_types.py +180 -25
  146. opentrons/protocol_engine/state/wells.py +54 -8
  147. opentrons/protocol_engine/types/__init__.py +292 -0
  148. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  149. opentrons/protocol_engine/types/command_annotations.py +53 -0
  150. opentrons/protocol_engine/types/deck_configuration.py +72 -0
  151. opentrons/protocol_engine/types/execution.py +96 -0
  152. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  153. opentrons/protocol_engine/types/instrument.py +47 -0
  154. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  155. opentrons/protocol_engine/types/labware.py +110 -0
  156. opentrons/protocol_engine/types/labware_movement.py +22 -0
  157. opentrons/protocol_engine/types/labware_offset_location.py +108 -0
  158. opentrons/protocol_engine/types/labware_offset_vector.py +33 -0
  159. opentrons/protocol_engine/types/liquid.py +40 -0
  160. opentrons/protocol_engine/types/liquid_class.py +59 -0
  161. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  162. opentrons/protocol_engine/types/liquid_level_detection.py +137 -0
  163. opentrons/protocol_engine/types/location.py +193 -0
  164. opentrons/protocol_engine/types/module.py +269 -0
  165. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  166. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  167. opentrons/protocol_engine/types/tip.py +18 -0
  168. opentrons/protocol_engine/types/util.py +21 -0
  169. opentrons/protocol_engine/types/well_position.py +107 -0
  170. opentrons/protocol_reader/extract_labware_definitions.py +7 -3
  171. opentrons/protocol_reader/file_format_validator.py +5 -3
  172. opentrons/protocol_runner/json_translator.py +4 -2
  173. opentrons/protocol_runner/legacy_command_mapper.py +6 -2
  174. opentrons/protocol_runner/run_orchestrator.py +4 -1
  175. opentrons/protocols/advanced_control/transfers/common.py +48 -1
  176. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +204 -0
  177. opentrons/protocols/api_support/definitions.py +1 -1
  178. opentrons/protocols/api_support/instrument.py +16 -3
  179. opentrons/protocols/labware.py +5 -6
  180. opentrons/protocols/models/__init__.py +0 -21
  181. opentrons/simulate.py +4 -2
  182. opentrons/types.py +15 -6
  183. {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/METADATA +4 -4
  184. {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/RECORD +188 -148
  185. opentrons/calibration_storage/ot2/models/defaults.py +0 -0
  186. opentrons/calibration_storage/ot3/models/defaults.py +0 -0
  187. opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
  188. opentrons/protocol_engine/types.py +0 -1311
  189. {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/LICENSE +0 -0
  190. {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/WHEEL +0 -0
  191. {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/entry_points.txt +0 -0
  192. {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ It's only for internal Opentrons use.
7
7
 
8
8
  from dataclasses import dataclass
9
9
  from typing import Optional, Union
10
- from opentrons_shared_data.labware.types import LabwareDefinition
10
+ from opentrons_shared_data.labware.types import LabwareDefinition2
11
11
 
12
12
  from opentrons.hardware_control.dev_types import PipetteDict
13
13
  from opentrons.hardware_control.modules.types import ModuleModel
@@ -18,13 +18,11 @@ from opentrons.types import Mount, DeckSlotName
18
18
  class LabwareLoadInfo:
19
19
  """Information about a successful labware load.
20
20
 
21
- :meta private:
22
-
23
21
  This is a separate class from the main user-facing `Labware` class
24
22
  because this is easier to construct in unit tests.
25
23
  """
26
24
 
27
- labware_definition: LabwareDefinition
25
+ labware_definition: LabwareDefinition2
28
26
 
29
27
  # todo(mm, 2021-10-11): Namespace, load name, and version can be derived from the
30
28
  # definition. Should they be removed from here?
@@ -47,10 +45,7 @@ class LabwareLoadInfo:
47
45
 
48
46
  @dataclass(frozen=True)
49
47
  class InstrumentLoadInfo:
50
- """Like `LabwareLoadInfo`, but for instruments (pipettes).
51
-
52
- :meta private:
53
- """
48
+ """Like `LabwareLoadInfo`, but for instruments (pipettes)."""
54
49
 
55
50
  instrument_load_name: str
56
51
  mount: Mount
@@ -59,10 +54,7 @@ class InstrumentLoadInfo:
59
54
 
60
55
  @dataclass(frozen=True)
61
56
  class ModuleLoadInfo:
62
- """Like `LabwareLoadInfo`, but for hardware modules.
63
-
64
- :meta private:
65
- """
57
+ """Like `LabwareLoadInfo`, but for hardware modules."""
66
58
 
67
59
  requested_model: ModuleModel
68
60
  loaded_model: ModuleModel
@@ -273,8 +273,13 @@ class ThermocyclerGeometry(ModuleGeometry):
273
273
  LegacyLabwareCore,
274
274
  )
275
275
 
276
- # Block first three columns from being accessed
277
276
  definition = labware._core.get_definition()
277
+
278
+ # For type checking. This should always pass because
279
+ # opentrons.protocol_api.core.legacy should only load labware with schema 2.
280
+ assert definition["schemaVersion"] == 2
281
+
282
+ # Block first three columns from being accessed
278
283
  definition["ordering"] = definition["ordering"][2::]
279
284
  return Labware(
280
285
  core=LegacyLabwareCore(definition, super().location),
@@ -4,9 +4,9 @@ from typing import Optional, cast, TYPE_CHECKING
4
4
 
5
5
  from opentrons.types import Point
6
6
  from opentrons_shared_data.labware.types import (
7
- WellDefinition,
8
- CircularWellDefinition,
9
- RectangularWellDefinition,
7
+ WellDefinition2 as WellDefinition,
8
+ CircularWellDefinition2 as CircularWellDefinition,
9
+ RectangularWellDefinition2 as RectangularWellDefinition,
10
10
  )
11
11
 
12
12
  if TYPE_CHECKING:
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- from typing import TYPE_CHECKING, Optional, Union, List
4
+ from typing import TYPE_CHECKING, Optional, Union, List, Tuple
5
5
 
6
6
  from opentrons import types
7
7
  from opentrons.hardware_control.dev_types import PipetteDict
@@ -23,6 +23,9 @@ from opentrons_shared_data.errors.exceptions import (
23
23
  UnexpectedTipAttachError,
24
24
  )
25
25
 
26
+ from opentrons.protocol_engine.types.liquid_level_detection import LiquidTrackingType
27
+
28
+ from ..legacy.legacy_labware_core import LegacyLabwareCore
26
29
  from ...disposal_locations import TrashBin, WasteChute
27
30
  from opentrons.protocol_api._nozzle_layout import NozzleLayout
28
31
  from opentrons.protocol_api._liquid import LiquidClass
@@ -42,7 +45,9 @@ _PRE_2_2_TIP_DROP_HEIGHT_MM = 10
42
45
  """In PAPIv2.1 and below, tips are always dropped 10 mm from the bottom of the well."""
43
46
 
44
47
 
45
- class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
48
+ class LegacyInstrumentCoreSimulator(
49
+ AbstractInstrument[LegacyWellCore, LegacyLabwareCore]
50
+ ):
46
51
  """A simulation of an instrument context."""
47
52
 
48
53
  def __init__(
@@ -84,7 +89,9 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
84
89
  def set_default_speed(self, speed: float) -> None:
85
90
  self._default_speed = speed
86
91
 
87
- def air_gap_in_place(self, volume: float, flow_rate: float) -> None:
92
+ def air_gap_in_place(
93
+ self, volume: float, flow_rate: float, correction_volume: Optional[float] = None
94
+ ) -> None:
88
95
  assert False, "Air gap tracking only available in API version 2.22 and later"
89
96
 
90
97
  def aspirate(
@@ -95,7 +102,8 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
95
102
  rate: float,
96
103
  flow_rate: float,
97
104
  in_place: bool,
98
- is_meniscus: Optional[bool] = None,
105
+ meniscus_tracking: Optional[types.MeniscusTrackingTarget] = None,
106
+ correction_volume: Optional[float] = None,
99
107
  ) -> None:
100
108
  if self.get_current_volume() == 0:
101
109
  # Make sure we're at the top of the labware and clear of any
@@ -137,7 +145,8 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
137
145
  flow_rate: float,
138
146
  in_place: bool,
139
147
  push_out: Optional[float],
140
- is_meniscus: Optional[bool] = None,
148
+ meniscus_tracking: Optional[types.MeniscusTrackingTarget] = None,
149
+ correction_volume: Optional[float] = None,
141
150
  ) -> None:
142
151
  if isinstance(location, (TrashBin, WasteChute)):
143
152
  raise APIVersionError(
@@ -177,7 +186,10 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
177
186
  radius: float,
178
187
  z_offset: float,
179
188
  speed: float,
189
+ mm_from_edge: Optional[float] = None,
180
190
  ) -> None:
191
+ if mm_from_edge is not None:
192
+ raise APIVersionError(api_element="mm_from_edge argument")
181
193
  self.move_to(location)
182
194
 
183
195
  def pick_up_tip(
@@ -365,6 +377,9 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
365
377
  def get_current_volume(self) -> float:
366
378
  return self._pipette_dict["current_volume"]
367
379
 
380
+ def get_has_clean_tip(self) -> bool:
381
+ return False
382
+
368
383
  def get_available_volume(self) -> float:
369
384
  return self._pipette_dict["available_volume"]
370
385
 
@@ -498,28 +513,47 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
498
513
  """This will never be called because it was added in API 2.15."""
499
514
  pass
500
515
 
501
- def load_liquid_class(
516
+ def transfer_liquid(
502
517
  self,
503
518
  liquid_class: LiquidClass,
504
- pipette_load_name: str,
505
- tiprack_uri: str,
506
- ) -> str:
507
- """This will never be called because it was added in .."""
508
- # TODO(spp, 2024-11-20): update the docstring and error to include API version
509
- assert False, "load_liquid_class is not supported in legacy context"
519
+ volume: float,
520
+ source: List[Tuple[types.Location, LegacyWellCore]],
521
+ dest: List[Tuple[types.Location, LegacyWellCore]],
522
+ new_tip: TransferTipPolicyV2,
523
+ tip_racks: List[Tuple[types.Location, LegacyLabwareCore]],
524
+ trash_location: Union[types.Location, TrashBin, WasteChute],
525
+ return_tip: bool,
526
+ ) -> None:
527
+ """This will never be called because it was added in API 2.23."""
528
+ assert False, "transfer_liquid is not supported in legacy context"
510
529
 
511
- def transfer_liquid(
530
+ def distribute_liquid(
512
531
  self,
513
- liquid_class_id: str,
532
+ liquid_class: LiquidClass,
514
533
  volume: float,
515
- source: List[LegacyWellCore],
516
- dest: List[LegacyWellCore],
534
+ source: Tuple[types.Location, LegacyWellCore],
535
+ dest: List[Tuple[types.Location, LegacyWellCore]],
517
536
  new_tip: TransferTipPolicyV2,
518
- trash_location: Union[LegacyWellCore, types.Location, TrashBin, WasteChute],
537
+ tip_racks: List[Tuple[types.Location, LegacyLabwareCore]],
538
+ trash_location: Union[types.Location, TrashBin, WasteChute],
539
+ return_tip: bool,
519
540
  ) -> None:
520
- """Transfer a liquid from source to dest according to liquid class properties."""
521
- # TODO(spp, 2024-11-20): update the docstring and error to include API version
522
- assert False, "transfer_liquid is not supported in legacy context"
541
+ """This will never be called because it was added in API 2.23."""
542
+ assert False, "distribute_liquid is not supported in legacy context"
543
+
544
+ def consolidate_liquid(
545
+ self,
546
+ liquid_class: LiquidClass,
547
+ volume: float,
548
+ source: List[Tuple[types.Location, LegacyWellCore]],
549
+ dest: Tuple[types.Location, LegacyWellCore],
550
+ new_tip: TransferTipPolicyV2,
551
+ tip_racks: List[Tuple[types.Location, LegacyLabwareCore]],
552
+ trash_location: Union[types.Location, TrashBin, WasteChute],
553
+ return_tip: bool,
554
+ ) -> None:
555
+ """This will never be called because it was added in API 2.23."""
556
+ assert False, "consolidate_liquid is not supported in legacy context"
523
557
 
524
558
  def get_active_channels(self) -> int:
525
559
  """This will never be called because it was added in API 2.16."""
@@ -549,7 +583,7 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
549
583
 
550
584
  def liquid_probe_without_recovery(
551
585
  self, well_core: WellCore, loc: types.Location
552
- ) -> float:
586
+ ) -> LiquidTrackingType:
553
587
  """This will never be called because it was added in API 2.20."""
554
588
  assert False, "liquid_probe_without_recovery only supported in API 2.20 & later"
555
589
 
@@ -559,3 +593,15 @@ class LegacyInstrumentCoreSimulator(AbstractInstrument[LegacyWellCore]):
559
593
  def nozzle_configuration_valid_for_lld(self) -> bool:
560
594
  """Check if the nozzle configuration currently supports LLD."""
561
595
  return False
596
+
597
+ def get_minimum_liquid_sense_height(self) -> float:
598
+ return 0.0
599
+
600
+ def estimate_liquid_height(
601
+ self,
602
+ well_core: LegacyWellCore,
603
+ starting_liquid_height: float,
604
+ operation_volume: float,
605
+ ) -> float:
606
+ """This will never be called because it was added in API 2.21."""
607
+ assert False, "estimate_liquid_height only supported in API 2.21 & later"
@@ -1,4 +1,5 @@
1
1
  """Core module control interfaces."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from abc import ABC, abstractmethod
@@ -379,3 +380,45 @@ class AbstractAbsorbanceReaderCore(AbstractModuleCore):
379
380
  @abstractmethod
380
381
  def is_lid_on(self) -> bool:
381
382
  """Return True if the Absorbance Reader's lid is currently closed."""
383
+
384
+
385
+ class AbstractFlexStackerCore(AbstractModuleCore):
386
+ """Core control interface for an attached Flex Stacker."""
387
+
388
+ MODULE_TYPE: ClassVar = ModuleType.FLEX_STACKER
389
+
390
+ @abstractmethod
391
+ def get_serial_number(self) -> str:
392
+ """Get the module's unique hardware serial number."""
393
+
394
+ @abstractmethod
395
+ def retrieve(self) -> None:
396
+ """Release a labware from the hopper to the staging slot."""
397
+
398
+ @abstractmethod
399
+ def store(self) -> None:
400
+ """Store a labware in the stacker hopper."""
401
+
402
+ @abstractmethod
403
+ def fill(self, message: str, count: int | None) -> None:
404
+ """Pause the protocol to allow for filling the stacker."""
405
+
406
+ @abstractmethod
407
+ def empty(self, message: str) -> None:
408
+ """Pause the protocol to allow for emptying the stacker."""
409
+
410
+ @abstractmethod
411
+ def set_stored_labware(
412
+ self,
413
+ main_load_name: str,
414
+ main_namespace: str | None,
415
+ main_version: int | None,
416
+ lid_load_name: str | None,
417
+ lid_namespace: str | None,
418
+ lid_version: int | None,
419
+ adapter_load_name: str | None,
420
+ adapter_namespace: str | None,
421
+ adapter_version: int | None,
422
+ count: int | None,
423
+ ) -> None:
424
+ """Configure the kind of labware that the stacker stores."""
@@ -111,6 +111,20 @@ class AbstractProtocol(
111
111
  """Load an individual lid labware using its identifying parameters. Must be loaded on a labware."""
112
112
  ...
113
113
 
114
+ @abstractmethod
115
+ def load_labware_to_flex_stacker_hopper(
116
+ self,
117
+ module_core: ModuleCoreType,
118
+ load_name: str,
119
+ quantity: int,
120
+ label: Optional[str],
121
+ namespace: Optional[str],
122
+ version: Optional[int],
123
+ lid: Optional[str],
124
+ ) -> None:
125
+ """Load one or more labware with or without a lid to the flex stacker hopper."""
126
+ ...
127
+
114
128
  @abstractmethod
115
129
  def move_labware(
116
130
  self,
@@ -131,6 +145,25 @@ class AbstractProtocol(
131
145
  ) -> None:
132
146
  ...
133
147
 
148
+ @abstractmethod
149
+ def move_lid(
150
+ self,
151
+ source_location: Union[DeckSlotName, StagingSlotName, LabwareCoreType],
152
+ new_location: Union[
153
+ DeckSlotName,
154
+ StagingSlotName,
155
+ LabwareCoreType,
156
+ OffDeckType,
157
+ WasteChute,
158
+ TrashBin,
159
+ ],
160
+ use_gripper: bool,
161
+ pause_for_manual_move: bool,
162
+ pick_up_offset: Optional[Tuple[float, float, float]],
163
+ drop_offset: Optional[Tuple[float, float, float]],
164
+ ) -> LabwareCoreType | None:
165
+ ...
166
+
134
167
  @abstractmethod
135
168
  def load_module(
136
169
  self,
@@ -1,9 +1,10 @@
1
1
  """Abstract interface for Well core implementations."""
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from typing import TypeVar, Optional
4
+ from typing import TypeVar, Optional, Union
5
5
 
6
6
  from opentrons.types import Point
7
+ from opentrons.protocol_engine.types.liquid_level_detection import LiquidTrackingType
7
8
 
8
9
  from .._liquid import Liquid
9
10
 
@@ -71,6 +72,10 @@ class AbstractWellCore(ABC):
71
72
  def get_center(self) -> Point:
72
73
  """Get the coordinate of the well's center."""
73
74
 
75
+ @abstractmethod
76
+ def get_meniscus(self) -> Union[Point, LiquidTrackingType]:
77
+ """Get the coordinate of the well's meniscus."""
78
+
74
79
  @abstractmethod
75
80
  def load_liquid(
76
81
  self,
@@ -83,5 +88,20 @@ class AbstractWellCore(ABC):
83
88
  def from_center_cartesian(self, x: float, y: float, z: float) -> Point:
84
89
  """Gets point in deck coordinates based on percentage of the radius of each axis."""
85
90
 
91
+ @abstractmethod
92
+ def estimate_liquid_height_after_pipetting(
93
+ self,
94
+ operation_volume: float,
95
+ ) -> LiquidTrackingType:
96
+ """Estimate what the liquid height will be after pipetting, without raising an error."""
97
+
98
+ @abstractmethod
99
+ def current_liquid_height(self) -> LiquidTrackingType:
100
+ """Get the current liquid height."""
101
+
102
+ @abstractmethod
103
+ def get_liquid_volume(self) -> LiquidTrackingType:
104
+ """Get the current volume within a well."""
105
+
86
106
 
87
107
  WellCoreType = TypeVar("WellCoreType", bound=AbstractWellCore)