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
@@ -19,23 +19,35 @@ from typing import (
19
19
  List,
20
20
  Dict,
21
21
  Optional,
22
- Union,
23
22
  Tuple,
24
23
  cast,
25
24
  Sequence,
26
25
  Mapping,
26
+ Union,
27
+ Literal,
27
28
  )
28
29
 
29
- from opentrons_shared_data.labware.types import LabwareDefinition, LabwareParameters
30
+ from opentrons_shared_data.labware.types import (
31
+ LabwareDefinition,
32
+ LabwareDefinition2,
33
+ LabwareParameters2,
34
+ LabwareParameters3,
35
+ )
30
36
 
31
- from opentrons.types import Location, Point, NozzleMapInterface
37
+ from opentrons.types import (
38
+ Location,
39
+ Point,
40
+ NozzleMapInterface,
41
+ MeniscusTrackingTarget,
42
+ Mount,
43
+ )
32
44
  from opentrons.protocols.api_support.types import APIVersion
33
45
  from opentrons.protocols.api_support.util import (
34
46
  requires_version,
35
47
  APIVersionError,
36
48
  UnsupportedAPIError,
37
49
  )
38
-
50
+ from opentrons.protocol_engine.types import LiquidTrackingType
39
51
 
40
52
  # TODO(mc, 2022-09-02): re-exports provided for backwards compatibility
41
53
  # remove when their usage is no longer needed
@@ -49,7 +61,10 @@ from . import validation
49
61
  from ._liquid import Liquid
50
62
  from ._types import OffDeckType
51
63
  from .core import well_grid
52
- from .core.engine import ENGINE_CORE_API_VERSION, SET_OFFSET_RESTORED_API_VERSION
64
+ from .core.engine import (
65
+ ENGINE_CORE_API_VERSION,
66
+ SET_OFFSET_RESTORED_API_VERSION,
67
+ )
53
68
  from .core.labware import AbstractLabware
54
69
  from .core.module import AbstractModuleCore
55
70
  from .core.core_map import LoadedCoreMap
@@ -248,16 +263,21 @@ class Well:
248
263
  return Location(self._core.get_center(), self)
249
264
 
250
265
  @requires_version(2, 21)
251
- def meniscus(self, z: float = 0.0) -> Location:
266
+ def meniscus(
267
+ self, z: float = 0.0, target: Literal["start", "end", "dynamic"] = "end"
268
+ ) -> Location:
252
269
  """
253
270
  :param z: An offset on the z-axis, in mm. Positive offsets are higher and
254
271
  negative offsets are lower.
255
- :return: A :py:class:`~opentrons.types.Location` that indicates location is meniscus and that holds the ``z`` offset in its point.z field.
272
+ :param target: The relative position of the liquid meniscus inside the well to target when performing a liquid handling operation.
273
+
274
+ :return: A :py:class:`~opentrons.types.Location` corresponding to the liquid meniscus, plus a target position and ``z`` offset as specified.
256
275
 
257
- :meta private:
258
276
  """
259
277
  return Location(
260
- point=Point(x=0, y=0, z=z), labware=self, _ot_internal_is_meniscus=True
278
+ point=Point(x=0, y=0, z=z),
279
+ labware=self,
280
+ _meniscus_tracking=MeniscusTrackingTarget(target),
261
281
  )
262
282
 
263
283
  @requires_version(2, 8)
@@ -307,15 +327,45 @@ class Well:
307
327
  :param Liquid liquid: The liquid to load into the well.
308
328
  :param float volume: The volume of liquid to load, in µL.
309
329
 
310
- .. TODO: flag as deprecated in 2.22 docs
311
- In API version 2.22 and later, use :py:meth:`~Labware.load_liquid`, :py:meth:`~Labware.load_liquid_by_well`,
312
- or :py:meth:`~Labware.load_empty` to load liquid into a well.
330
+ .. deprecated:: 2.22
331
+ Use :py:meth:`.Labware.load_liquid`, :py:meth:`.Labware.load_liquid_by_well`, or :py:meth:`.Labware.load_empty` instead.
332
+
313
333
  """
314
334
  self._core.load_liquid(
315
335
  liquid=liquid,
316
336
  volume=volume,
317
337
  )
318
338
 
339
+ @requires_version(2, 21)
340
+ def current_liquid_height(self) -> LiquidTrackingType:
341
+ """Get the current liquid height in a well."""
342
+ return self._core.current_liquid_height()
343
+
344
+ @requires_version(2, 21)
345
+ def current_liquid_volume(self) -> LiquidTrackingType:
346
+ """Get the current liquid volume in a well."""
347
+ return self._core.get_liquid_volume()
348
+
349
+ @requires_version(2, 21)
350
+ def estimate_liquid_height_after_pipetting(
351
+ self,
352
+ mount: Mount | str,
353
+ operation_volume: float,
354
+ ) -> LiquidTrackingType:
355
+ """Check the height of the liquid within a well.
356
+
357
+ :returns: The height, in mm, of the liquid from the deck.
358
+
359
+ :meta private:
360
+
361
+ This is intended for Opentrons internal use only and is not a guaranteed API.
362
+ """
363
+
364
+ projected_final_height = self._core.estimate_liquid_height_after_pipetting(
365
+ operation_volume=operation_volume, mount=mount
366
+ )
367
+ return projected_final_height
368
+
319
369
  def _from_center_cartesian(self, x: float, y: float, z: float) -> Point:
320
370
  """
321
371
  Private version of from_center_cartesian. Present only for backward
@@ -509,7 +559,7 @@ class Labware:
509
559
 
510
560
  @property
511
561
  @requires_version(2, 0)
512
- def parameters(self) -> "LabwareParameters":
562
+ def parameters(self) -> "LabwareParameters2 | LabwareParameters3":
513
563
  """Internal properties of a labware including type and quirks."""
514
564
  return self._core.get_parameters()
515
565
 
@@ -636,7 +686,7 @@ class Labware:
636
686
  version: Optional[int] = None,
637
687
  ) -> Labware:
638
688
  """
639
- Load a stack of Lids onto a valid Deck Location or Adapter.
689
+ Load a stack of Opentrons Tough Auto-Sealing Lids onto a valid deck location or adapter.
640
690
 
641
691
  :param str load_name: A string to use for looking up a lid definition.
642
692
  You can find the ``load_name`` for any standard lid on the Opentrons
@@ -657,7 +707,7 @@ class Labware:
657
707
  leave this unspecified to let ``load_lid_stack()`` choose a version
658
708
  automatically.
659
709
 
660
- :return: The initialized and loaded labware object representing the Lid Stack.
710
+ :return: The initialized and loaded labware object representing the lid stack.
661
711
  """
662
712
  if self._api_version < validation.LID_STACK_VERSION_GATE:
663
713
  raise APIVersionError(
@@ -712,18 +762,25 @@ class Labware:
712
762
 
713
763
  .. list-table::
714
764
  :header-rows: 1
765
+ :widths: 1 5
715
766
 
716
767
  * - API level
717
768
  - Offset behavior
718
769
  * - 2.12–2.13
719
770
  - Offsets only apply to the exact :py:class:`.Labware` instance.
771
+
772
+ If your protocol has multiple instances of the same type of labware,
773
+ you must either use ``set_offset()`` on all of them or none of them.
720
774
  * - 2.14–2.17
721
775
  - ``set_offset()`` is not available, and the API raises an error.
722
- * - 2.18 and newer
776
+ * - 2.18--2.22
723
777
  -
724
778
  - Offsets apply to any labware of the same type, in the same on-deck location.
725
779
  - Offsets can't be set on labware that is currently off-deck.
726
780
  - Offsets do not follow a labware instance when using :py:meth:`.move_labware`.
781
+ * - 2.23 and newer
782
+ -
783
+ On Flex, offsets can apply to all labware of the same type, regardless of their on-deck location.
727
784
 
728
785
  .. note::
729
786
 
@@ -1215,22 +1272,15 @@ class Labware:
1215
1272
  ) -> None:
1216
1273
  """Mark several wells as containing the same amount of liquid.
1217
1274
 
1218
- This method should be called at the beginning of a protocol, soon after loading the labware and before
1219
- liquid handling operations begin. It is a base of information for liquid tracking functionality. If a well in a labware
1220
- has not been named in a call to :py:meth:`~Labware.load_empty`, :py:meth:`~Labware.load_liquid`, or
1221
- :py:meth:`~Labware.load_liquid_by_well`, the volume it contains is unknown and the well's liquid will not be tracked.
1222
-
1223
- For example, to load 10µL of a liquid named ``water`` (defined with :py:meth:`~ProtocolContext.define_liquid`)
1224
- into all the wells of a labware, you could call ``labware.load_liquid(labware.wells(), 10, water)``.
1225
-
1226
- If you want to load different volumes of liquid into different wells, use :py:meth:`~Labware.load_liquid_by_well`.
1227
-
1228
- If you want to mark the well as containing no liquid, use :py:meth:`~Labware.load_empty`.
1275
+ This method should be called at the beginning of a protocol, soon after loading labware and before
1276
+ liquid handling operations begin. Loading liquids is required for liquid tracking functionality. If a well
1277
+ hasn't been assigned a starting volume with :py:meth:`~Labware.load_empty`, :py:meth:`~Labware.load_liquid`, or
1278
+ :py:meth:`~Labware.load_liquid_by_well`, the volume it contains is unknown and the well's liquid will not be tracked throughout the protocol.
1229
1279
 
1230
1280
  :param wells: The wells to load the liquid into.
1231
- :type wells: List of well names or list of Well objects, for instance from :py:meth:`~Labware.wells`.
1281
+ :type wells: List of string well names or list of :py:class:`.Well` objects (e.g., from :py:meth:`~Labware.wells`).
1232
1282
 
1233
- :param volume: The volume of liquid to load into each well, in 10µL.
1283
+ :param volume: The volume of liquid to load into each well.
1234
1284
  :type volume: float
1235
1285
 
1236
1286
  :param liquid: The liquid to load into each well, previously defined by :py:meth:`~ProtocolContext.define_liquid`
@@ -1266,18 +1316,9 @@ class Labware:
1266
1316
  ) -> None:
1267
1317
  """Mark several wells as containing unique volumes of liquid.
1268
1318
 
1269
- This method should be called at the beginning of a protocol, soon after loading the labware and before
1270
- liquid handling operations begin. It is a base of information for liquid tracking functionality. If a well in a labware
1271
- has not been named in a call to :py:meth:`~Labware.load_empty`, :py:meth:`~Labware.load_liquid`, or
1272
- :py:meth:`~Labware.load_liquid_by_well`, the volume it contains is unknown and the well's liquid will not be tracked.
1273
-
1274
- For example, to load a decreasing amount of of a liquid named ``water`` (defined with :py:meth:`~ProtocolContext.define_liquid`)
1275
- into each successive well of a row, you could call
1276
- ``labware.load_liquid_by_well({'A1': 1000, 'A2': 950, 'A3': 900, ..., 'A12': 600}, water)``
1277
-
1278
- If you want to load the same volume of a liquid into multiple wells, it is often easier to use :py:meth:`~Labware.load_liquid`.
1279
-
1280
- If you want to mark the well as containing no liquid, use :py:meth:`~Labware.load_empty`.
1319
+ This method should be called at the beginning of a protocol, soon after loading labware and before
1320
+ liquid handling begins. Loading liquids is required for liquid tracking functionality. If a well hasn't been assigned a starting volume with :py:meth:`~Labware.load_empty`, :py:meth:`~Labware.load_liquid`, or
1321
+ :py:meth:`~Labware.load_liquid_by_well`, the volume it contains is unknown and the well's liquid will not be tracked throughout the protocol.
1281
1322
 
1282
1323
  :param volumes: A dictionary of well names (or :py:class:`Well` objects, for instance from ``labware['A1']``)
1283
1324
  :type wells: Dict[Union[str, Well], float]
@@ -1313,12 +1354,9 @@ class Labware:
1313
1354
  def load_empty(self, wells: Sequence[Union[Well, str]]) -> None:
1314
1355
  """Mark several wells as empty.
1315
1356
 
1316
- This method should be called at the beginning of a protocol, soon after loading the labware and before liquid handling
1317
- operations begin. It is a base of information for liquid tracking functionality. If a well in a labware has not been named
1318
- in a call to :py:meth:`Labware.load_empty`, :py:meth:`Labware.load_liquid`, or :py:meth:`Labware.load_liquid_by_well`, the
1319
- volume it contains is unknown and the well's liquid will not be tracked.
1320
-
1321
- For instance, to mark all wells in the labware as empty, you can call ``labware.load_empty(labware.wells())``.
1357
+ This method should be called at the beginning of a protocol, after loading the labware and before liquid handling
1358
+ begins. Loading liquids is required for liquid tracking functionality. If a well in a labware hasn't been assigned a starting volume with :py:meth:`Labware.load_empty`, :py:meth:`Labware.load_liquid`, or :py:meth:`Labware.load_liquid_by_well`, the
1359
+ volume it contains is unknown and the well's liquid will not be tracked throughout the protocol.
1322
1360
 
1323
1361
  :param wells: The list of wells to mark empty. To mark all wells as empty, pass ``labware.wells()``. You can also specify
1324
1362
  wells by their names (for instance, ``labware.load_empty(['A1', 'A2'])``).
@@ -1417,7 +1455,7 @@ def next_available_tip(
1417
1455
  # TODO(mc, 2022-11-09): implementation detail, move somewhere else
1418
1456
  # only used in old calibration flows by robot-server
1419
1457
  def load_from_definition(
1420
- definition: "LabwareDefinition",
1458
+ definition: "LabwareDefinition2",
1421
1459
  parent: Location,
1422
1460
  label: Optional[str] = None,
1423
1461
  api_level: Optional[APIVersion] = None,
@@ -1461,8 +1499,8 @@ def load(
1461
1499
  label: Optional[str] = None,
1462
1500
  namespace: Optional[str] = None,
1463
1501
  version: int = 1,
1464
- bundled_defs: Optional[Dict[str, LabwareDefinition]] = None,
1465
- extra_defs: Optional[Dict[str, LabwareDefinition]] = None,
1502
+ bundled_defs: Optional[Mapping[str, LabwareDefinition2]] = None,
1503
+ extra_defs: Optional[Mapping[str, LabwareDefinition2]] = None,
1466
1504
  api_level: Optional[APIVersion] = None,
1467
1505
  ) -> Labware:
1468
1506
  """
@@ -1500,4 +1538,14 @@ def load(
1500
1538
  extra_defs=extra_defs,
1501
1539
  )
1502
1540
 
1541
+ # The legacy `load_from_definition()` function that we're calling only supports
1542
+ # schemaVersion==2 labware. Fortunately, when robot-server calls this function,
1543
+ # we only expect it to try to load schemaVersion==2 labware, so we never expect
1544
+ # this ValueError to be raised in practice.
1545
+ if definition["schemaVersion"] != 2:
1546
+ raise ValueError(
1547
+ f"{namespace}/{load_name}/{version} has schema {definition['schemaVersion']}."
1548
+ " Only schema 2 is supported."
1549
+ )
1550
+
1503
1551
  return load_from_definition(definition, parent, label, api_level)
@@ -29,6 +29,7 @@ from .core.common import (
29
29
  HeaterShakerCore,
30
30
  MagneticBlockCore,
31
31
  AbsorbanceReaderCore,
32
+ FlexStackerCore,
32
33
  )
33
34
  from .core.core_map import LoadedCoreMap
34
35
  from .core.engine import ENGINE_CORE_API_VERSION
@@ -1098,3 +1099,142 @@ class AbsorbanceReaderContext(ModuleContext):
1098
1099
  :returns: A dictionary of wavelengths to dictionary of values ordered by well name.
1099
1100
  """
1100
1101
  return self._core.read(filename=export_filename)
1102
+
1103
+
1104
+ class FlexStackerContext(ModuleContext):
1105
+ """An object representing a connected Flex Stacker module.
1106
+
1107
+ It should not be instantiated directly; instead, it should be
1108
+ created through :py:meth:`.ProtocolContext.load_module`.
1109
+
1110
+ .. versionadded:: 2.23
1111
+ """
1112
+
1113
+ _core: FlexStackerCore
1114
+
1115
+ @property
1116
+ @requires_version(2, 23)
1117
+ def serial_number(self) -> str:
1118
+ """Get the module's unique hardware serial number."""
1119
+ return self._core.get_serial_number()
1120
+
1121
+ @requires_version(2, 23)
1122
+ def retrieve(self) -> Labware:
1123
+ """Retrieve a labware from the Flex Stacker and place it on the shuttle.
1124
+
1125
+ :returns: The retrieved :py:class:`Labware` object. This will always be the main labware,
1126
+ even if the Flex Stacker contains labware on an adapter. To get the adapter object,
1127
+ call :py:class:`Labware.parent` on the returned labware.
1128
+
1129
+ """
1130
+ self._core.retrieve()
1131
+
1132
+ labware_core = self._protocol_core.get_labware_on_module(self._core)
1133
+ if labware_core is not None and labware_core.is_adapter():
1134
+ adapter_core = labware_core
1135
+ adapter = Labware(
1136
+ core=adapter_core,
1137
+ api_version=self._api_version,
1138
+ protocol_core=self._protocol_core,
1139
+ core_map=self._core_map,
1140
+ )
1141
+ self._core_map.add(adapter_core, adapter)
1142
+ labware_core = self._protocol_core.get_labware_on_labware(adapter_core)
1143
+
1144
+ # the core retrieve command should have already raised the error
1145
+ # if labware_core is None, this is just to satisfy the type checker
1146
+ assert labware_core is not None, "Retrieve failed to return labware"
1147
+ # check core map first
1148
+ try:
1149
+ labware = self._core_map.get(labware_core)
1150
+ except KeyError:
1151
+ # If the labware is not already in the core map,
1152
+ # create a new Labware object
1153
+ labware = Labware(
1154
+ core=labware_core,
1155
+ api_version=self._api_version,
1156
+ protocol_core=self._protocol_core,
1157
+ core_map=self._core_map,
1158
+ )
1159
+ self._core_map.add(labware_core, labware)
1160
+ return labware
1161
+
1162
+ @requires_version(2, 23)
1163
+ def store(self) -> None:
1164
+ """Move the labware currently on the Flex Stacker shuttle into the Flex Stacker."""
1165
+ self._core.store()
1166
+
1167
+ @requires_version(2, 23)
1168
+ def set_stored_labware(
1169
+ self,
1170
+ load_name: str,
1171
+ namespace: str | None = None,
1172
+ version: int | None = None,
1173
+ adapter: str | None = None,
1174
+ lid: str | None = None,
1175
+ count: int | None = None,
1176
+ ) -> None:
1177
+ """Configure what kind of labware the Flex Stacker will store.
1178
+
1179
+ :param str load_name: A string to use for looking up a labware definition.
1180
+ You can find the ``load_name`` for any Opentrons-verified labware on the
1181
+ `Labware Library <https://labware.opentrons.com>`__.
1182
+ :param str namespace: The namespace that the labware definition belongs to.
1183
+ If unspecified, the API will automatically search two namespaces:
1184
+
1185
+ - ``"opentrons"``, to load standard Opentrons labware definitions.
1186
+ - ``"custom_beta"``, to load custom labware definitions created with the
1187
+ `Custom Labware Creator <https://labware.opentrons.com/create>`__.
1188
+
1189
+ You might need to specify an explicit ``namespace`` if you have a custom
1190
+ definition whose ``load_name`` is the same as an Opentrons-verified
1191
+ definition, and you want to explicitly choose one or the other.
1192
+ :param version: The version of the labware definition. You should normally
1193
+ leave this unspecified to let ``load_labware()`` choose a version
1194
+ automatically.
1195
+ :param adapter: An adapter to load the labware on top of. Accepts the same
1196
+ values as the ``load_name`` parameter of :py:meth:`.load_adapter`. The
1197
+ adapter will use the same namespace as the labware, and the API will
1198
+ choose the adapter's version automatically.
1199
+ :param lid: A lid to load the on top of the main labware. Accepts the same
1200
+ values as the ``load_name`` parameter of :py:meth:`.load_lid_stack`. The
1201
+ lid will use the same namespace as the labware, and the API will
1202
+ choose the lid's version automatically.
1203
+ :param count: The number of labware that the Flex Stacker should start the protocol
1204
+ storing. If not specified, this will be the maximum amount of this kind of
1205
+ labware that the Flex Stacker is capable of storing.
1206
+
1207
+ """
1208
+ self._core.set_stored_labware(
1209
+ main_load_name=load_name,
1210
+ main_namespace=namespace,
1211
+ main_version=version,
1212
+ lid_load_name=lid,
1213
+ lid_namespace=namespace,
1214
+ lid_version=version,
1215
+ adapter_load_name=adapter,
1216
+ adapter_namespace=namespace,
1217
+ adapter_version=version,
1218
+ count=count,
1219
+ )
1220
+
1221
+ @requires_version(2, 23)
1222
+ def fill(self, message: str, count: int | None = None) -> None:
1223
+ """Pause the protocol to add more labware to the Flex Stacker.
1224
+
1225
+ :param message: A message to display in the Opentrons App to note what kind of labware to add.
1226
+ :param count: The amount of labware the Flex Stacker should hold after this command is executed.
1227
+ If not specified, the Flex Stacker should be full after this command is executed.
1228
+ """
1229
+ self._core.fill(message, count)
1230
+
1231
+ @requires_version(2, 23)
1232
+ def empty(self, message: str) -> None:
1233
+ """Pause the protocol to remove labware from the Flex Stacker.
1234
+
1235
+ :param message: A message to display in the Opentrons App to note what should be removed from
1236
+ the Flex Stacker.
1237
+ """
1238
+ self._core.empty(
1239
+ message,
1240
+ )