opentrons 8.7.0a9__py3-none-any.whl → 8.8.0a7__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 (189) hide show
  1. opentrons/_version.py +2 -2
  2. opentrons/cli/analyze.py +4 -1
  3. opentrons/config/__init__.py +7 -0
  4. opentrons/drivers/asyncio/communication/serial_connection.py +126 -49
  5. opentrons/drivers/heater_shaker/abstract.py +5 -0
  6. opentrons/drivers/heater_shaker/driver.py +10 -0
  7. opentrons/drivers/heater_shaker/simulator.py +4 -0
  8. opentrons/drivers/thermocycler/abstract.py +6 -0
  9. opentrons/drivers/thermocycler/driver.py +61 -10
  10. opentrons/drivers/thermocycler/simulator.py +6 -0
  11. opentrons/drivers/vacuum_module/__init__.py +5 -0
  12. opentrons/drivers/vacuum_module/abstract.py +93 -0
  13. opentrons/drivers/vacuum_module/driver.py +208 -0
  14. opentrons/drivers/vacuum_module/errors.py +39 -0
  15. opentrons/drivers/vacuum_module/simulator.py +85 -0
  16. opentrons/drivers/vacuum_module/types.py +79 -0
  17. opentrons/execute.py +3 -0
  18. opentrons/hardware_control/api.py +24 -5
  19. opentrons/hardware_control/backends/controller.py +8 -2
  20. opentrons/hardware_control/backends/flex_protocol.py +1 -0
  21. opentrons/hardware_control/backends/ot3controller.py +35 -2
  22. opentrons/hardware_control/backends/ot3simulator.py +3 -1
  23. opentrons/hardware_control/backends/ot3utils.py +37 -0
  24. opentrons/hardware_control/backends/simulator.py +2 -1
  25. opentrons/hardware_control/backends/subsystem_manager.py +5 -2
  26. opentrons/hardware_control/emulation/abstract_emulator.py +6 -4
  27. opentrons/hardware_control/emulation/connection_handler.py +8 -5
  28. opentrons/hardware_control/emulation/heater_shaker.py +12 -3
  29. opentrons/hardware_control/emulation/settings.py +1 -1
  30. opentrons/hardware_control/emulation/thermocycler.py +67 -15
  31. opentrons/hardware_control/module_control.py +105 -10
  32. opentrons/hardware_control/modules/__init__.py +3 -0
  33. opentrons/hardware_control/modules/absorbance_reader.py +11 -4
  34. opentrons/hardware_control/modules/flex_stacker.py +38 -9
  35. opentrons/hardware_control/modules/heater_shaker.py +42 -5
  36. opentrons/hardware_control/modules/magdeck.py +8 -4
  37. opentrons/hardware_control/modules/mod_abc.py +14 -6
  38. opentrons/hardware_control/modules/tempdeck.py +25 -5
  39. opentrons/hardware_control/modules/thermocycler.py +68 -11
  40. opentrons/hardware_control/modules/types.py +20 -1
  41. opentrons/hardware_control/modules/utils.py +11 -4
  42. opentrons/hardware_control/motion_utilities.py +6 -6
  43. opentrons/hardware_control/nozzle_manager.py +3 -0
  44. opentrons/hardware_control/ot3api.py +85 -17
  45. opentrons/hardware_control/poller.py +22 -8
  46. opentrons/hardware_control/protocols/liquid_handler.py +6 -2
  47. opentrons/hardware_control/scripts/update_module_fw.py +5 -0
  48. opentrons/hardware_control/types.py +43 -2
  49. opentrons/legacy_commands/commands.py +58 -5
  50. opentrons/legacy_commands/module_commands.py +52 -0
  51. opentrons/legacy_commands/protocol_commands.py +53 -1
  52. opentrons/legacy_commands/types.py +155 -1
  53. opentrons/motion_planning/deck_conflict.py +17 -12
  54. opentrons/motion_planning/waypoints.py +15 -29
  55. opentrons/protocol_api/__init__.py +5 -1
  56. opentrons/protocol_api/_transfer_liquid_validation.py +17 -2
  57. opentrons/protocol_api/_types.py +8 -1
  58. opentrons/protocol_api/core/common.py +3 -1
  59. opentrons/protocol_api/core/engine/_default_labware_versions.py +33 -11
  60. opentrons/protocol_api/core/engine/deck_conflict.py +3 -1
  61. opentrons/protocol_api/core/engine/instrument.py +109 -26
  62. opentrons/protocol_api/core/engine/labware.py +8 -1
  63. opentrons/protocol_api/core/engine/module_core.py +95 -4
  64. opentrons/protocol_api/core/engine/protocol.py +51 -2
  65. opentrons/protocol_api/core/engine/stringify.py +2 -0
  66. opentrons/protocol_api/core/engine/tasks.py +48 -0
  67. opentrons/protocol_api/core/engine/well.py +8 -0
  68. opentrons/protocol_api/core/instrument.py +19 -2
  69. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +19 -2
  70. opentrons/protocol_api/core/legacy/legacy_module_core.py +33 -2
  71. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +23 -1
  72. opentrons/protocol_api/core/legacy/legacy_well_core.py +4 -0
  73. opentrons/protocol_api/core/legacy/tasks.py +19 -0
  74. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +19 -2
  75. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +14 -2
  76. opentrons/protocol_api/core/legacy_simulator/tasks.py +19 -0
  77. opentrons/protocol_api/core/module.py +58 -2
  78. opentrons/protocol_api/core/protocol.py +23 -2
  79. opentrons/protocol_api/core/tasks.py +31 -0
  80. opentrons/protocol_api/core/well.py +4 -0
  81. opentrons/protocol_api/instrument_context.py +388 -2
  82. opentrons/protocol_api/labware.py +10 -2
  83. opentrons/protocol_api/module_contexts.py +170 -6
  84. opentrons/protocol_api/protocol_context.py +87 -21
  85. opentrons/protocol_api/robot_context.py +41 -25
  86. opentrons/protocol_api/tasks.py +48 -0
  87. opentrons/protocol_api/validation.py +49 -3
  88. opentrons/protocol_engine/__init__.py +4 -0
  89. opentrons/protocol_engine/actions/__init__.py +6 -2
  90. opentrons/protocol_engine/actions/actions.py +31 -9
  91. opentrons/protocol_engine/clients/sync_client.py +42 -7
  92. opentrons/protocol_engine/commands/__init__.py +56 -0
  93. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +2 -15
  94. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +2 -15
  95. opentrons/protocol_engine/commands/absorbance_reader/read.py +22 -23
  96. opentrons/protocol_engine/commands/aspirate.py +1 -0
  97. opentrons/protocol_engine/commands/aspirate_while_tracking.py +52 -19
  98. opentrons/protocol_engine/commands/capture_image.py +302 -0
  99. opentrons/protocol_engine/commands/command.py +2 -0
  100. opentrons/protocol_engine/commands/command_unions.py +62 -0
  101. opentrons/protocol_engine/commands/create_timer.py +83 -0
  102. opentrons/protocol_engine/commands/dispense.py +1 -0
  103. opentrons/protocol_engine/commands/dispense_while_tracking.py +56 -19
  104. opentrons/protocol_engine/commands/drop_tip.py +32 -8
  105. opentrons/protocol_engine/commands/flex_stacker/common.py +35 -0
  106. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +7 -0
  107. opentrons/protocol_engine/commands/heater_shaker/__init__.py +14 -0
  108. opentrons/protocol_engine/commands/heater_shaker/common.py +20 -0
  109. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +5 -4
  110. opentrons/protocol_engine/commands/heater_shaker/set_shake_speed.py +136 -0
  111. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +31 -5
  112. opentrons/protocol_engine/commands/move_labware.py +3 -4
  113. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +1 -1
  114. opentrons/protocol_engine/commands/movement_common.py +31 -2
  115. opentrons/protocol_engine/commands/pick_up_tip.py +21 -11
  116. opentrons/protocol_engine/commands/pipetting_common.py +48 -3
  117. opentrons/protocol_engine/commands/set_tip_state.py +97 -0
  118. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +38 -7
  119. opentrons/protocol_engine/commands/thermocycler/__init__.py +16 -0
  120. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +6 -0
  121. opentrons/protocol_engine/commands/thermocycler/run_profile.py +8 -0
  122. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +44 -7
  123. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +43 -14
  124. opentrons/protocol_engine/commands/thermocycler/start_run_extended_profile.py +191 -0
  125. opentrons/protocol_engine/commands/touch_tip.py +1 -1
  126. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +6 -22
  127. opentrons/protocol_engine/commands/wait_for_tasks.py +98 -0
  128. opentrons/protocol_engine/create_protocol_engine.py +12 -0
  129. opentrons/protocol_engine/engine_support.py +3 -0
  130. opentrons/protocol_engine/errors/__init__.py +12 -0
  131. opentrons/protocol_engine/errors/exceptions.py +119 -0
  132. opentrons/protocol_engine/execution/__init__.py +4 -0
  133. opentrons/protocol_engine/execution/command_executor.py +62 -1
  134. opentrons/protocol_engine/execution/create_queue_worker.py +9 -2
  135. opentrons/protocol_engine/execution/labware_movement.py +13 -15
  136. opentrons/protocol_engine/execution/movement.py +2 -0
  137. opentrons/protocol_engine/execution/pipetting.py +19 -25
  138. opentrons/protocol_engine/execution/queue_worker.py +4 -0
  139. opentrons/protocol_engine/execution/run_control.py +8 -0
  140. opentrons/protocol_engine/execution/task_handler.py +157 -0
  141. opentrons/protocol_engine/protocol_engine.py +137 -36
  142. opentrons/protocol_engine/resources/__init__.py +4 -0
  143. opentrons/protocol_engine/resources/camera_provider.py +110 -0
  144. opentrons/protocol_engine/resources/concurrency_provider.py +27 -0
  145. opentrons/protocol_engine/resources/deck_configuration_provider.py +7 -0
  146. opentrons/protocol_engine/resources/file_provider.py +133 -58
  147. opentrons/protocol_engine/resources/labware_validation.py +10 -6
  148. opentrons/protocol_engine/slot_standardization.py +2 -0
  149. opentrons/protocol_engine/state/_well_math.py +60 -18
  150. opentrons/protocol_engine/state/addressable_areas.py +2 -0
  151. opentrons/protocol_engine/state/camera.py +54 -0
  152. opentrons/protocol_engine/state/commands.py +37 -14
  153. opentrons/protocol_engine/state/geometry.py +276 -379
  154. opentrons/protocol_engine/state/labware.py +62 -108
  155. opentrons/protocol_engine/state/labware_origin_math/errors.py +94 -0
  156. opentrons/protocol_engine/state/labware_origin_math/stackup_origin_to_labware_origin.py +1336 -0
  157. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +37 -0
  158. opentrons/protocol_engine/state/modules.py +30 -8
  159. opentrons/protocol_engine/state/motion.py +44 -0
  160. opentrons/protocol_engine/state/preconditions.py +59 -0
  161. opentrons/protocol_engine/state/state.py +44 -0
  162. opentrons/protocol_engine/state/state_summary.py +4 -0
  163. opentrons/protocol_engine/state/tasks.py +139 -0
  164. opentrons/protocol_engine/state/tips.py +177 -258
  165. opentrons/protocol_engine/state/update_types.py +26 -9
  166. opentrons/protocol_engine/types/__init__.py +23 -4
  167. opentrons/protocol_engine/types/command_preconditions.py +18 -0
  168. opentrons/protocol_engine/types/deck_configuration.py +5 -1
  169. opentrons/protocol_engine/types/instrument.py +8 -1
  170. opentrons/protocol_engine/types/labware.py +1 -13
  171. opentrons/protocol_engine/types/location.py +26 -2
  172. opentrons/protocol_engine/types/module.py +11 -1
  173. opentrons/protocol_engine/types/tasks.py +38 -0
  174. opentrons/protocol_engine/types/tip.py +9 -0
  175. opentrons/protocol_runner/create_simulating_orchestrator.py +29 -2
  176. opentrons/protocol_runner/protocol_runner.py +14 -1
  177. opentrons/protocol_runner/run_orchestrator.py +49 -2
  178. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +2 -2
  179. opentrons/protocols/api_support/definitions.py +1 -1
  180. opentrons/protocols/api_support/types.py +2 -1
  181. opentrons/simulate.py +51 -15
  182. opentrons/system/camera.py +334 -4
  183. opentrons/system/ffmpeg.py +110 -0
  184. {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/METADATA +4 -4
  185. {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/RECORD +188 -160
  186. opentrons/protocol_engine/state/_labware_origin_math.py +0 -636
  187. {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/WHEEL +0 -0
  188. {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/entry_points.txt +0 -0
  189. {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/licenses/LICENSE +0 -0
@@ -25,6 +25,10 @@ from .command_annotations import (
25
25
  CustomCommandAnnotation,
26
26
  CommandAnnotation,
27
27
  )
28
+ from .command_preconditions import (
29
+ CommandPreconditions,
30
+ PreconditionTypes,
31
+ )
28
32
  from .partial_tip_configuration import (
29
33
  AllNozzleLayoutConfiguration,
30
34
  SingleNozzleLayoutConfiguration,
@@ -83,6 +87,8 @@ from .location import (
83
87
  NonStackedLocation,
84
88
  DeckPoint,
85
89
  InStackerHopperLocation,
90
+ WASTE_CHUTE_LOCATION,
91
+ AccessibleByGripperLocation,
86
92
  OnLabwareLocationSequenceComponent,
87
93
  OnModuleLocationSequenceComponent,
88
94
  OnAddressableAreaLocationSequenceComponent,
@@ -92,6 +98,7 @@ from .location import (
92
98
  LoadableLabwareLocation,
93
99
  labware_location_is_system,
94
100
  labware_location_is_off_deck,
101
+ labware_location_is_in_waste_chute,
95
102
  )
96
103
  from .labware import (
97
104
  OverlapOffset,
@@ -100,7 +107,6 @@ from .labware import (
100
107
  LegacyLabwareOffsetCreate,
101
108
  LabwareOffsetCreateInternal,
102
109
  LoadedLabware,
103
- LabwareParentDefinition,
104
110
  LabwareWellId,
105
111
  GripSpecs,
106
112
  )
@@ -132,6 +138,7 @@ from .instrument import (
132
138
  CurrentWell,
133
139
  CurrentPipetteLocation,
134
140
  InstrumentOffsetVector,
141
+ GripperMoveType,
135
142
  )
136
143
  from .execution import EngineStatus, PostRunHardwareState
137
144
  from .liquid_level_detection import (
@@ -145,9 +152,10 @@ from .liquid_level_detection import (
145
152
  )
146
153
  from .liquid_handling import FlowRates
147
154
  from .labware_movement import LabwareMovementStrategy, LabwareMovementOffsetData
148
- from .tip import TipGeometry
155
+ from .tip import TipGeometry, TipRackWellState
149
156
  from .hardware_passthrough import MovementAxis, MotorAxis
150
157
  from .util import Vec3f, Dimensions
158
+ from .tasks import Task, TaskSummary, FinishedTask
151
159
 
152
160
  __all__ = [
153
161
  # Runtime parameters
@@ -165,6 +173,9 @@ __all__ = [
165
173
  "SecondOrderCommandAnnotation",
166
174
  "CustomCommandAnnotation",
167
175
  "CommandAnnotation",
176
+ # Command preconditions
177
+ "PreconditionTypes",
178
+ "CommandPreconditions",
168
179
  # Partial tip handling
169
180
  "AllNozzleLayoutConfiguration",
170
181
  "SingleNozzleLayoutConfiguration",
@@ -228,8 +239,10 @@ __all__ = [
228
239
  "NonStackedLocation",
229
240
  "DeckPoint",
230
241
  "OffDeckLocationType",
231
- "SystemLocationType",
242
+ "WasteChuteLocationType" "SystemLocationType",
232
243
  "InStackerHopperLocation",
244
+ "WASTE_CHUTE_LOCATION",
245
+ "AccessibleByGripperLocation",
233
246
  "OnLabwareLocationSequenceComponent",
234
247
  "OnModuleLocationSequenceComponent",
235
248
  "OnAddressableAreaLocationSequenceComponent",
@@ -239,6 +252,7 @@ __all__ = [
239
252
  "LoadableLabwareLocation",
240
253
  "labware_location_is_off_deck",
241
254
  "labware_location_is_system",
255
+ "labware_location_is_in_waste_chute",
242
256
  # Labware offset location
243
257
  "LegacyLabwareOffsetLocation",
244
258
  "LabwareOffsetLocationSequence",
@@ -256,7 +270,6 @@ __all__ = [
256
270
  "LabwareOffsetCreateInternal",
257
271
  "LoadedLabware",
258
272
  "LabwareOffsetVector",
259
- "LabwareParentDefinition",
260
273
  "LabwareWellId",
261
274
  "GripSpecs",
262
275
  # Liquids
@@ -286,6 +299,7 @@ __all__ = [
286
299
  "CurrentWell",
287
300
  "CurrentPipetteLocation",
288
301
  "InstrumentOffsetVector",
302
+ "GripperMoveType",
289
303
  # Liquid level detection types
290
304
  "LoadedVolumeInfo",
291
305
  "ProbedHeightInfo",
@@ -301,6 +315,7 @@ __all__ = [
301
315
  "LabwareMovementOffsetData",
302
316
  # Tips
303
317
  "TipGeometry",
318
+ "TipRackWellState",
304
319
  # Hardware passthrough
305
320
  "MovementAxis",
306
321
  "MotorAxis",
@@ -309,4 +324,8 @@ __all__ = [
309
324
  "Dimensions",
310
325
  # Convenience re-export
311
326
  "LabwareUri",
327
+ # Tasks
328
+ "Task",
329
+ "TaskSummary",
330
+ "FinishedTask",
312
331
  ]
@@ -0,0 +1,18 @@
1
+ """Protocol Engine types dealing with command preconditions."""
2
+ from enum import Enum
3
+ from pydantic import Field, BaseModel
4
+
5
+
6
+ class PreconditionTypes(str, Enum):
7
+ """Precondition types used for identification during state update."""
8
+
9
+ IS_CAMERA_USED = "isCameraUsed"
10
+
11
+
12
+ class CommandPreconditions(BaseModel):
13
+ """Preconditions of commands as described in protocol analysis."""
14
+
15
+ isCameraUsed: bool = Field(
16
+ default=False,
17
+ description="Parameter to determine if a Camera is used in a protocol.",
18
+ )
@@ -6,7 +6,10 @@ from enum import Enum
6
6
 
7
7
  from opentrons.types import DeckSlotName
8
8
 
9
- from opentrons_shared_data.module.types import ModuleType as SharedDataModuleType
9
+ from opentrons_shared_data.module.types import (
10
+ ModuleType as SharedDataModuleType,
11
+ ModuleOrientation,
12
+ )
10
13
  from opentrons_shared_data.deck.types import SlotDefV3
11
14
  from opentrons_shared_data.labware.types import LocatingFeatures
12
15
 
@@ -57,6 +60,7 @@ class AddressableArea:
57
60
  position: AddressableOffsetVector
58
61
  compatible_module_types: List[SharedDataModuleType]
59
62
  features: LocatingFeatures
63
+ orientation: ModuleOrientation
60
64
 
61
65
 
62
66
  # TODO make the below some sort of better type
@@ -1,5 +1,5 @@
1
1
  """Protocol Engine types to do with instruments."""
2
-
2
+ import enum
3
3
  from typing import Union
4
4
 
5
5
  from dataclasses import dataclass
@@ -45,3 +45,10 @@ class InstrumentOffsetVector(BaseModel):
45
45
  x: float
46
46
  y: float
47
47
  z: float
48
+
49
+
50
+ class GripperMoveType(enum.Enum):
51
+ """Types of gripper movement."""
52
+
53
+ PICK_UP_LABWARE = enum.auto()
54
+ DROP_LABWARE = enum.auto()
@@ -2,16 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Optional, Union
5
+ from typing import Optional
6
6
  from dataclasses import dataclass
7
7
  from datetime import datetime
8
8
 
9
9
  from pydantic import BaseModel, Field
10
10
 
11
- from opentrons_shared_data.labware.labware_definition import (
12
- LabwareDefinition,
13
- )
14
-
15
11
  from .location import LabwareLocation
16
12
  from .labware_offset_location import (
17
13
  LegacyLabwareOffsetLocation,
@@ -19,8 +15,6 @@ from .labware_offset_location import (
19
15
  )
20
16
  from .labware_offset_vector import LabwareOffsetVector
21
17
  from .util import Vec3f
22
- from .module import ModuleDefinition
23
- from .deck_configuration import DeckLocationDefinition
24
18
 
25
19
 
26
20
  @dataclass(frozen=True)
@@ -126,12 +120,6 @@ class LoadedLabware(BaseModel):
126
120
  )
127
121
 
128
122
 
129
- LabwareParentDefinition = Union[
130
- DeckLocationDefinition, ModuleDefinition, LabwareDefinition
131
- ]
132
- """Information pertaining to a labware's parent (deck slot, module, or another labware) location."""
133
-
134
-
135
123
  @dataclass(frozen=True)
136
124
  class LabwareWellId:
137
125
  """Designates a well in a labware."""
@@ -85,8 +85,10 @@ class InStackerHopperLocation(BaseModel):
85
85
 
86
86
  _OffDeckLocationType = Literal["offDeck"]
87
87
  _SystemLocationType = Literal["systemLocation"]
88
+ _WasteChuteLocationType = Literal["wasteChuteLocation"]
88
89
  OFF_DECK_LOCATION: _OffDeckLocationType = "offDeck"
89
90
  SYSTEM_LOCATION: _SystemLocationType = "systemLocation"
91
+ WASTE_CHUTE_LOCATION: _WasteChuteLocationType = "wasteChuteLocation"
90
92
 
91
93
 
92
94
  def labware_location_is_off_deck(
@@ -103,6 +105,13 @@ def labware_location_is_system(
103
105
  return isinstance(location, str) and location == SYSTEM_LOCATION
104
106
 
105
107
 
108
+ def labware_location_is_in_waste_chute(
109
+ location: LabwareLocation,
110
+ ) -> TypeGuard[_WasteChuteLocationType]:
111
+ """Check if a location is the waste chute."""
112
+ return isinstance(location, str) and location == WASTE_CHUTE_LOCATION
113
+
114
+
106
115
  class OnLabwareLocationSequenceComponent(BaseModel):
107
116
  """Labware on another labware."""
108
117
 
@@ -137,7 +146,7 @@ class NotOnDeckLocationSequenceComponent(BaseModel):
137
146
  """Labware on a system location."""
138
147
 
139
148
  kind: Literal["notOnDeck"] = "notOnDeck"
140
- logicalLocationName: _OffDeckLocationType | _SystemLocationType
149
+ logicalLocationName: _OffDeckLocationType | _SystemLocationType | _WasteChuteLocationType
141
150
 
142
151
 
143
152
  LabwareLocationSequence = list[
@@ -158,6 +167,7 @@ LabwareLocation = Union[
158
167
  _SystemLocationType,
159
168
  AddressableAreaLocation,
160
169
  InStackerHopperLocation,
170
+ _WasteChuteLocationType,
161
171
  ]
162
172
  """Union of all locations where it's legal to keep a labware."""
163
173
 
@@ -168,11 +178,15 @@ LoadableLabwareLocation = Union[
168
178
  _OffDeckLocationType,
169
179
  _SystemLocationType,
170
180
  AddressableAreaLocation,
181
+ _WasteChuteLocationType,
171
182
  ]
172
183
  """Union of all locations where it's legal to load a labware."""
173
184
 
174
185
  OnDeckLabwareLocation = Union[
175
- DeckSlotLocation, ModuleLocation, OnLabwareLocation, AddressableAreaLocation
186
+ DeckSlotLocation,
187
+ ModuleLocation,
188
+ OnLabwareLocation,
189
+ AddressableAreaLocation,
176
190
  ]
177
191
 
178
192
  NonStackedLocation = Union[
@@ -181,9 +195,19 @@ NonStackedLocation = Union[
181
195
  ModuleLocation,
182
196
  _OffDeckLocationType,
183
197
  _SystemLocationType,
198
+ _WasteChuteLocationType,
184
199
  ]
185
200
  """Union of all locations where it's legal to keep a labware that can't be stacked on another labware"""
186
201
 
202
+ AccessibleByGripperLocation = Union[
203
+ DeckSlotLocation,
204
+ ModuleLocation,
205
+ OnLabwareLocation,
206
+ AddressableAreaLocation,
207
+ _WasteChuteLocationType,
208
+ ]
209
+ """Union of all locations that a gripper can move things to."""
210
+
187
211
 
188
212
  # TODO(mm, 2022-11-07): Deduplicate with Vec3f.
189
213
  class DeckPoint(BaseModel):
@@ -21,6 +21,7 @@ from opentrons_shared_data.labware.types import LocatingFeatures
21
21
 
22
22
  from opentrons.hardware_control.modules import (
23
23
  ModuleType as ModuleType,
24
+ ModuleModel as HardwareModuleModel,
24
25
  )
25
26
 
26
27
  from .location import DeckSlotLocation
@@ -43,6 +44,11 @@ class ModuleModel(str, Enum):
43
44
  ABSORBANCE_READER_V1 = "absorbanceReaderV1"
44
45
  FLEX_STACKER_MODULE_V1 = "flexStackerModuleV1"
45
46
 
47
+ @classmethod
48
+ def from_hardware(cls, hardware_model: HardwareModuleModel) -> "ModuleModel":
49
+ """Convert from the hardware model representation."""
50
+ return cls(hardware_model.value)
51
+
46
52
  def as_type(self) -> ModuleType:
47
53
  """Get the ModuleType of this model."""
48
54
  if ModuleModel.is_temperature_module_model(self):
@@ -193,6 +199,10 @@ class ModuleDefinition(BaseModel):
193
199
  ...,
194
200
  )
195
201
 
202
+ orientation: Dict[str, str] = Field(
203
+ ...,
204
+ )
205
+
196
206
  compatibleWith: List[ModuleModel] = Field(
197
207
  ...,
198
208
  )
@@ -293,7 +303,7 @@ class StackerStoredLabwareGroup(BaseModel):
293
303
 
294
304
  @dataclass
295
305
  class StackerPoolDefinition:
296
- """Represents an internal configuraiton of stored labware."""
306
+ """Represents an internal configuration of stored labware."""
297
307
 
298
308
  primaryLabwareDefinition: LabwareDefinition
299
309
  adapterLabwareDefinition: LabwareDefinition | SkipJsonSchema[None] = None
@@ -0,0 +1,38 @@
1
+ """Types for Tasks."""
2
+ from datetime import datetime
3
+ from opentrons.protocol_engine.errors import ErrorOccurrence
4
+ from dataclasses import dataclass
5
+ import asyncio
6
+
7
+
8
+ @dataclass
9
+ class _BaseTask:
10
+ """A base task representation."""
11
+
12
+ id: str
13
+ createdAt: datetime
14
+
15
+
16
+ @dataclass
17
+ class Task(_BaseTask):
18
+ """A task representation."""
19
+
20
+ asyncioTask: asyncio.Task[None]
21
+
22
+
23
+ @dataclass
24
+ class FinishedTask(_BaseTask):
25
+ """A finished task representation."""
26
+
27
+ finishedAt: datetime
28
+ error: ErrorOccurrence | None
29
+
30
+
31
+ @dataclass
32
+ class TaskSummary:
33
+ """Task info for use in summary lists."""
34
+
35
+ id: str
36
+ createdAt: datetime
37
+ finishedAt: datetime | None = None
38
+ error: ErrorOccurrence | None = None
@@ -1,6 +1,7 @@
1
1
  """Protocol Engine types to deal with tips."""
2
2
 
3
3
  from dataclasses import dataclass
4
+ from enum import Enum
4
5
 
5
6
 
6
7
  @dataclass(frozen=True)
@@ -16,3 +17,11 @@ class TipGeometry:
16
17
  length: float
17
18
  diameter: float
18
19
  volume: float
20
+
21
+
22
+ class TipRackWellState(Enum):
23
+ """The state of a single tip in a tip rack's well."""
24
+
25
+ CLEAN = "clean"
26
+ USED = "used"
27
+ EMPTY = "empty"
@@ -16,11 +16,38 @@ from opentrons_shared_data.robot.types import RobotType
16
16
  from .python_protocol_wrappers import SimulatingContextCreator
17
17
  from .run_orchestrator import RunOrchestrator
18
18
  from .protocol_runner import create_protocol_runner, LiveRunner
19
+ from ..protocol_engine.types import (
20
+ PostRunHardwareState,
21
+ )
22
+
23
+
24
+ class SimulatingRunOrchestrator(RunOrchestrator):
25
+ """A RunOrchestrator that cleans up its simulating hardware controller.
26
+
27
+ This should only be created and returned by create_simulating_orchestrator, unless
28
+ you are sure it's appropriate to clean up the hardware controller.
29
+ """
30
+
31
+ async def finish(
32
+ self,
33
+ error: Exception | None = None,
34
+ drop_tips_after_run: bool = True,
35
+ set_run_status: bool = True,
36
+ post_run_hardware_state: PostRunHardwareState = PostRunHardwareState.HOME_AND_STAY_ENGAGED,
37
+ ) -> None:
38
+ """Finish the run and clean up the simulating hardware controller."""
39
+ await super().finish(
40
+ error=error,
41
+ drop_tips_after_run=drop_tips_after_run,
42
+ set_run_status=set_run_status,
43
+ post_run_hardware_state=post_run_hardware_state,
44
+ )
45
+ await self._hardware_api.clean_up()
19
46
 
20
47
 
21
48
  async def create_simulating_orchestrator(
22
49
  robot_type: RobotType, protocol_config: ProtocolConfig
23
- ) -> RunOrchestrator:
50
+ ) -> SimulatingRunOrchestrator:
24
51
  """Create a RunOrchestrator wired to a simulating HardwareControlAPI.
25
52
 
26
53
  Example:
@@ -96,7 +123,7 @@ async def create_simulating_orchestrator(
96
123
  hardware_api=simulating_hardware_api,
97
124
  )
98
125
 
99
- return RunOrchestrator(
126
+ return SimulatingRunOrchestrator(
100
127
  hardware_api=simulating_hardware_api,
101
128
  json_or_python_protocol_runner=runner,
102
129
  protocol_engine=protocol_engine,
@@ -24,7 +24,7 @@ from opentrons.protocol_engine import (
24
24
  Command,
25
25
  commands as pe_commands,
26
26
  )
27
- from opentrons.protocol_engine.types import CommandAnnotation
27
+ from opentrons.protocol_engine.types import CommandAnnotation, CommandPreconditions
28
28
  from opentrons.protocols.parse import PythonParseMode
29
29
  from opentrons.util.async_helpers import asyncio_yield
30
30
  from opentrons.util.broker import Broker
@@ -58,6 +58,7 @@ class RunResult(NamedTuple):
58
58
  state_summary: StateSummary
59
59
  parameters: List[RunTimeParameter]
60
60
  command_annotations: List[CommandAnnotation]
61
+ command_preconditions: Optional[CommandPreconditions]
61
62
 
62
63
 
63
64
  class AbstractRunner(ABC):
@@ -284,11 +285,15 @@ class PythonAndLegacyRunner(AbstractRunner):
284
285
  run_data = self._protocol_engine.state_view.get_summary()
285
286
  commands = self._protocol_engine.state_view.commands.get_all()
286
287
  parameters = self.run_time_parameters
288
+ preconditions = (
289
+ self._protocol_engine.state_view.preconditions.get_precondition()
290
+ )
287
291
  return RunResult(
288
292
  commands=commands,
289
293
  state_summary=run_data,
290
294
  parameters=parameters,
291
295
  command_annotations=[],
296
+ command_preconditions=preconditions,
292
297
  )
293
298
 
294
299
 
@@ -403,11 +408,15 @@ class JsonRunner(AbstractRunner):
403
408
 
404
409
  run_data = self._protocol_engine.state_view.get_summary()
405
410
  commands = self._protocol_engine.state_view.commands.get_all()
411
+ preconditions = (
412
+ self._protocol_engine.state_view.preconditions.get_precondition()
413
+ )
406
414
  return RunResult(
407
415
  commands=commands,
408
416
  state_summary=run_data,
409
417
  parameters=[],
410
418
  command_annotations=self._command_annotations,
419
+ command_preconditions=preconditions,
411
420
  )
412
421
 
413
422
  async def _add_and_execute_commands(self) -> None:
@@ -479,11 +488,15 @@ class LiveRunner(AbstractRunner):
479
488
 
480
489
  run_data = self._protocol_engine.state_view.get_summary()
481
490
  commands = self._protocol_engine.state_view.commands.get_all()
491
+ preconditions = (
492
+ self._protocol_engine.state_view.preconditions.get_precondition()
493
+ )
482
494
  return RunResult(
483
495
  commands=commands,
484
496
  state_summary=run_data,
485
497
  parameters=[],
486
498
  command_annotations=[],
499
+ command_preconditions=preconditions,
487
500
  )
488
501
 
489
502
 
@@ -15,7 +15,10 @@ from opentrons_shared_data.robot.types import RobotType
15
15
 
16
16
  from . import protocol_runner, RunResult, JsonRunner, PythonAndLegacyRunner
17
17
  from ..hardware_control import HardwareControlAPI
18
- from ..hardware_control.modules import AbstractModule as HardwareModuleAPI
18
+ from ..hardware_control.modules import (
19
+ AbstractModule as HardwareModuleAPI,
20
+ ModuleModel as HardwareModuleModel,
21
+ )
19
22
  from ..protocol_engine import (
20
23
  ProtocolEngine,
21
24
  CommandCreate,
@@ -40,7 +43,9 @@ from ..protocol_engine.types import (
40
43
  CSVRuntimeParamPaths,
41
44
  CommandAnnotation,
42
45
  ModuleModel,
46
+ CommandPreconditions,
43
47
  )
48
+ from ..protocol_engine.resources.camera_provider import CameraProvider, CameraSettings
44
49
  from ..protocol_engine.error_recovery_policy import ErrorRecoveryPolicy
45
50
 
46
51
  from ..protocol_reader import JsonProtocolConfig, PythonProtocolConfig, ProtocolSource
@@ -81,15 +86,16 @@ class RunOrchestrator:
81
86
  _protocol_live_runner: protocol_runner.LiveRunner
82
87
  _hardware_api: HardwareControlAPI
83
88
  _protocol_engine: ProtocolEngine
89
+ _camera_provider: Optional[CameraProvider] = None
84
90
 
85
91
  def __init__(
86
92
  self,
87
93
  protocol_engine: ProtocolEngine,
88
- # todo(mm, 2024-07-05): This hardware_api param looks unused?
89
94
  hardware_api: HardwareControlAPI,
90
95
  fixit_runner: protocol_runner.LiveRunner,
91
96
  setup_runner: protocol_runner.LiveRunner,
92
97
  protocol_live_runner: protocol_runner.LiveRunner,
98
+ camera_provider: Optional[CameraProvider] = None,
93
99
  json_or_python_protocol_runner: Optional[
94
100
  Union[protocol_runner.PythonAndLegacyRunner, protocol_runner.JsonRunner]
95
101
  ] = None,
@@ -104,6 +110,7 @@ class RunOrchestrator:
104
110
  setup_runner: LiveRunner for setup commands.
105
111
  protocol_live_runner: LiveRunner for protocol commands.
106
112
  json_or_python_protocol_runner: JsonRunner/PythonAndLegacyRunner for protocol commands.
113
+ camera_provider: Provides callbacks to Camera interface.
107
114
  run_id: run id if any, associated to the runner/engine.
108
115
  """
109
116
  self._run_id = run_id
@@ -112,9 +119,12 @@ class RunOrchestrator:
112
119
  self._setup_runner = setup_runner
113
120
  self._fixit_runner = fixit_runner
114
121
  self._protocol_live_runner = protocol_live_runner
122
+ self._camera_provider = camera_provider
115
123
  self._fixit_runner.prepare()
116
124
  self._setup_runner.prepare()
117
125
  self._protocol_engine.set_and_start_queue_worker(self.command_generator)
126
+ # used by SimulatingRunOrchestrator to clean up the simulating hardware controller
127
+ self._hardware_api = hardware_api
118
128
 
119
129
  @property
120
130
  def run_id(self) -> str:
@@ -128,6 +138,7 @@ class RunOrchestrator:
128
138
  cls,
129
139
  hardware_api: HardwareControlAPI,
130
140
  protocol_engine: ProtocolEngine,
141
+ camera_provider: Optional[CameraProvider] = None,
131
142
  protocol_config: Optional[
132
143
  Union[JsonProtocolConfig, PythonProtocolConfig]
133
144
  ] = None,
@@ -165,6 +176,7 @@ class RunOrchestrator:
165
176
  hardware_api=hardware_api,
166
177
  protocol_engine=protocol_engine,
167
178
  protocol_live_runner=protocol_live_runner,
179
+ camera_provider=camera_provider,
168
180
  )
169
181
 
170
182
  def play(self, deck_configuration: Optional[DeckConfigurationType] = None) -> None:
@@ -233,6 +245,10 @@ class RunOrchestrator:
233
245
  """Get protocol run data."""
234
246
  return self._protocol_engine.state_view.get_summary()
235
247
 
248
+ def get_preconditions(self) -> CommandPreconditions:
249
+ """Get the preconditions of a protocol run."""
250
+ return self._protocol_engine.state_view.preconditions.get_precondition()
251
+
236
252
  def get_loaded_labware_definitions(self) -> List[LabwareDefinition]:
237
253
  """Get loaded labware definitions."""
238
254
  return self._protocol_engine.state_view.labware.get_loaded_labware_definitions()
@@ -359,6 +375,13 @@ class RunOrchestrator:
359
375
  """Add a new labware definition to state."""
360
376
  return self._protocol_engine.add_labware_definition(definition)
361
377
 
378
+ def add_camera_enablement_settings(
379
+ self,
380
+ enablement_settings: CameraSettings,
381
+ ) -> CameraSettings:
382
+ """Add new camera enablement settings."""
383
+ return self._protocol_engine.add_camera_enablement_settings(enablement_settings)
384
+
362
385
  async def add_command_and_wait_for_interval(
363
386
  self,
364
387
  command: CommandCreate,
@@ -380,6 +403,30 @@ class RunOrchestrator:
380
403
  """Handle an E-stop event from the hardware API."""
381
404
  return self._protocol_engine.estop()
382
405
 
406
+ async def asynchronous_module_error(
407
+ self, module_model: HardwareModuleModel, module_serial: str | None
408
+ ) -> bool:
409
+ """Handle an asynchronous module error reported by hardware.
410
+
411
+ If this function returns true, the caller should call finish() immediately; if it returns
412
+ False, the caller should not call finish() until it otherwise would.
413
+ """
414
+ return await self._protocol_engine.async_module_error(
415
+ module_model=ModuleModel.from_hardware(module_model), serial=module_serial
416
+ )
417
+
418
+ async def module_disconnected(
419
+ self, module_model: HardwareModuleModel, module_serial: str | None
420
+ ) -> bool:
421
+ """Handle an unexpected module disconnection.
422
+
423
+ If this function returns true, the caller should call finish() immediately; if it returns
424
+ False, the caller should not call finish() until it otherwise would.
425
+ """
426
+ return await self._protocol_engine.module_disconnected(
427
+ module_model=ModuleModel.from_hardware(module_model), serial=module_serial
428
+ )
429
+
383
430
  async def use_attached_modules(
384
431
  self, modules_by_id: Dict[str, HardwareModuleAPI]
385
432
  ) -> None:
@@ -72,7 +72,7 @@ def raise_if_location_inside_liquid(
72
72
  def group_wells_for_multi_channel_transfer(
73
73
  targets: Sequence[Well],
74
74
  nozzle_map: NozzleMapInterface,
75
- target_name: Literal["source", "destination"],
75
+ target_name: Literal["source", "destination", "tip"],
76
76
  ) -> List[Well]:
77
77
  """Takes a list of wells and a nozzle map and returns a list of target wells to address every well given
78
78
 
@@ -108,7 +108,7 @@ def group_wells_for_multi_channel_transfer(
108
108
  def _group_wells_for_nozzle_configuration( # noqa: C901
109
109
  targets: List[Well],
110
110
  nozzle_map: NozzleMapInterface,
111
- target_name: Literal["source", "destination"],
111
+ target_name: Literal["source", "destination", "tip"],
112
112
  ) -> List[Well]:
113
113
  """Groups wells together for a column, row, or full 96 configuration and returns a reduced list of target wells."""
114
114
  grouped_wells = []
@@ -1,6 +1,6 @@
1
1
  from .types import APIVersion
2
2
 
3
- MAX_SUPPORTED_VERSION = APIVersion(2, 26)
3
+ MAX_SUPPORTED_VERSION = APIVersion(2, 27)
4
4
  """The maximum supported protocol API version in this release."""
5
5
 
6
6
  MIN_SUPPORTED_VERSION = APIVersion(2, 0)
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import NamedTuple, TypedDict
2
+ from typing import NamedTuple, TypedDict, Optional
3
3
 
4
4
 
5
5
  class APIVersion(NamedTuple):
@@ -30,3 +30,4 @@ class ThermocyclerStep(ThermocyclerStepBase, total=False):
30
30
 
31
31
  hold_time_seconds: float
32
32
  hold_time_minutes: float
33
+ ramp_rate: Optional[float]