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.
- opentrons/_version.py +2 -2
- opentrons/cli/analyze.py +4 -1
- opentrons/config/__init__.py +7 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +126 -49
- opentrons/drivers/heater_shaker/abstract.py +5 -0
- opentrons/drivers/heater_shaker/driver.py +10 -0
- opentrons/drivers/heater_shaker/simulator.py +4 -0
- opentrons/drivers/thermocycler/abstract.py +6 -0
- opentrons/drivers/thermocycler/driver.py +61 -10
- opentrons/drivers/thermocycler/simulator.py +6 -0
- opentrons/drivers/vacuum_module/__init__.py +5 -0
- opentrons/drivers/vacuum_module/abstract.py +93 -0
- opentrons/drivers/vacuum_module/driver.py +208 -0
- opentrons/drivers/vacuum_module/errors.py +39 -0
- opentrons/drivers/vacuum_module/simulator.py +85 -0
- opentrons/drivers/vacuum_module/types.py +79 -0
- opentrons/execute.py +3 -0
- opentrons/hardware_control/api.py +24 -5
- opentrons/hardware_control/backends/controller.py +8 -2
- opentrons/hardware_control/backends/flex_protocol.py +1 -0
- opentrons/hardware_control/backends/ot3controller.py +35 -2
- opentrons/hardware_control/backends/ot3simulator.py +3 -1
- opentrons/hardware_control/backends/ot3utils.py +37 -0
- opentrons/hardware_control/backends/simulator.py +2 -1
- opentrons/hardware_control/backends/subsystem_manager.py +5 -2
- opentrons/hardware_control/emulation/abstract_emulator.py +6 -4
- opentrons/hardware_control/emulation/connection_handler.py +8 -5
- opentrons/hardware_control/emulation/heater_shaker.py +12 -3
- opentrons/hardware_control/emulation/settings.py +1 -1
- opentrons/hardware_control/emulation/thermocycler.py +67 -15
- opentrons/hardware_control/module_control.py +105 -10
- opentrons/hardware_control/modules/__init__.py +3 -0
- opentrons/hardware_control/modules/absorbance_reader.py +11 -4
- opentrons/hardware_control/modules/flex_stacker.py +38 -9
- opentrons/hardware_control/modules/heater_shaker.py +42 -5
- opentrons/hardware_control/modules/magdeck.py +8 -4
- opentrons/hardware_control/modules/mod_abc.py +14 -6
- opentrons/hardware_control/modules/tempdeck.py +25 -5
- opentrons/hardware_control/modules/thermocycler.py +68 -11
- opentrons/hardware_control/modules/types.py +20 -1
- opentrons/hardware_control/modules/utils.py +11 -4
- opentrons/hardware_control/motion_utilities.py +6 -6
- opentrons/hardware_control/nozzle_manager.py +3 -0
- opentrons/hardware_control/ot3api.py +85 -17
- opentrons/hardware_control/poller.py +22 -8
- opentrons/hardware_control/protocols/liquid_handler.py +6 -2
- opentrons/hardware_control/scripts/update_module_fw.py +5 -0
- opentrons/hardware_control/types.py +43 -2
- opentrons/legacy_commands/commands.py +58 -5
- opentrons/legacy_commands/module_commands.py +52 -0
- opentrons/legacy_commands/protocol_commands.py +53 -1
- opentrons/legacy_commands/types.py +155 -1
- opentrons/motion_planning/deck_conflict.py +17 -12
- opentrons/motion_planning/waypoints.py +15 -29
- opentrons/protocol_api/__init__.py +5 -1
- opentrons/protocol_api/_transfer_liquid_validation.py +17 -2
- opentrons/protocol_api/_types.py +8 -1
- opentrons/protocol_api/core/common.py +3 -1
- opentrons/protocol_api/core/engine/_default_labware_versions.py +33 -11
- opentrons/protocol_api/core/engine/deck_conflict.py +3 -1
- opentrons/protocol_api/core/engine/instrument.py +109 -26
- opentrons/protocol_api/core/engine/labware.py +8 -1
- opentrons/protocol_api/core/engine/module_core.py +95 -4
- opentrons/protocol_api/core/engine/protocol.py +51 -2
- opentrons/protocol_api/core/engine/stringify.py +2 -0
- opentrons/protocol_api/core/engine/tasks.py +48 -0
- opentrons/protocol_api/core/engine/well.py +8 -0
- opentrons/protocol_api/core/instrument.py +19 -2
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +19 -2
- opentrons/protocol_api/core/legacy/legacy_module_core.py +33 -2
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +23 -1
- opentrons/protocol_api/core/legacy/legacy_well_core.py +4 -0
- opentrons/protocol_api/core/legacy/tasks.py +19 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +19 -2
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +14 -2
- opentrons/protocol_api/core/legacy_simulator/tasks.py +19 -0
- opentrons/protocol_api/core/module.py +58 -2
- opentrons/protocol_api/core/protocol.py +23 -2
- opentrons/protocol_api/core/tasks.py +31 -0
- opentrons/protocol_api/core/well.py +4 -0
- opentrons/protocol_api/instrument_context.py +388 -2
- opentrons/protocol_api/labware.py +10 -2
- opentrons/protocol_api/module_contexts.py +170 -6
- opentrons/protocol_api/protocol_context.py +87 -21
- opentrons/protocol_api/robot_context.py +41 -25
- opentrons/protocol_api/tasks.py +48 -0
- opentrons/protocol_api/validation.py +49 -3
- opentrons/protocol_engine/__init__.py +4 -0
- opentrons/protocol_engine/actions/__init__.py +6 -2
- opentrons/protocol_engine/actions/actions.py +31 -9
- opentrons/protocol_engine/clients/sync_client.py +42 -7
- opentrons/protocol_engine/commands/__init__.py +56 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +2 -15
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +2 -15
- opentrons/protocol_engine/commands/absorbance_reader/read.py +22 -23
- opentrons/protocol_engine/commands/aspirate.py +1 -0
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +52 -19
- opentrons/protocol_engine/commands/capture_image.py +302 -0
- opentrons/protocol_engine/commands/command.py +2 -0
- opentrons/protocol_engine/commands/command_unions.py +62 -0
- opentrons/protocol_engine/commands/create_timer.py +83 -0
- opentrons/protocol_engine/commands/dispense.py +1 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +56 -19
- opentrons/protocol_engine/commands/drop_tip.py +32 -8
- opentrons/protocol_engine/commands/flex_stacker/common.py +35 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +7 -0
- opentrons/protocol_engine/commands/heater_shaker/__init__.py +14 -0
- opentrons/protocol_engine/commands/heater_shaker/common.py +20 -0
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +5 -4
- opentrons/protocol_engine/commands/heater_shaker/set_shake_speed.py +136 -0
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +31 -5
- opentrons/protocol_engine/commands/move_labware.py +3 -4
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +1 -1
- opentrons/protocol_engine/commands/movement_common.py +31 -2
- opentrons/protocol_engine/commands/pick_up_tip.py +21 -11
- opentrons/protocol_engine/commands/pipetting_common.py +48 -3
- opentrons/protocol_engine/commands/set_tip_state.py +97 -0
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +38 -7
- opentrons/protocol_engine/commands/thermocycler/__init__.py +16 -0
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +6 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +8 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +44 -7
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +43 -14
- opentrons/protocol_engine/commands/thermocycler/start_run_extended_profile.py +191 -0
- opentrons/protocol_engine/commands/touch_tip.py +1 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +6 -22
- opentrons/protocol_engine/commands/wait_for_tasks.py +98 -0
- opentrons/protocol_engine/create_protocol_engine.py +12 -0
- opentrons/protocol_engine/engine_support.py +3 -0
- opentrons/protocol_engine/errors/__init__.py +12 -0
- opentrons/protocol_engine/errors/exceptions.py +119 -0
- opentrons/protocol_engine/execution/__init__.py +4 -0
- opentrons/protocol_engine/execution/command_executor.py +62 -1
- opentrons/protocol_engine/execution/create_queue_worker.py +9 -2
- opentrons/protocol_engine/execution/labware_movement.py +13 -15
- opentrons/protocol_engine/execution/movement.py +2 -0
- opentrons/protocol_engine/execution/pipetting.py +19 -25
- opentrons/protocol_engine/execution/queue_worker.py +4 -0
- opentrons/protocol_engine/execution/run_control.py +8 -0
- opentrons/protocol_engine/execution/task_handler.py +157 -0
- opentrons/protocol_engine/protocol_engine.py +137 -36
- opentrons/protocol_engine/resources/__init__.py +4 -0
- opentrons/protocol_engine/resources/camera_provider.py +110 -0
- opentrons/protocol_engine/resources/concurrency_provider.py +27 -0
- opentrons/protocol_engine/resources/deck_configuration_provider.py +7 -0
- opentrons/protocol_engine/resources/file_provider.py +133 -58
- opentrons/protocol_engine/resources/labware_validation.py +10 -6
- opentrons/protocol_engine/slot_standardization.py +2 -0
- opentrons/protocol_engine/state/_well_math.py +60 -18
- opentrons/protocol_engine/state/addressable_areas.py +2 -0
- opentrons/protocol_engine/state/camera.py +54 -0
- opentrons/protocol_engine/state/commands.py +37 -14
- opentrons/protocol_engine/state/geometry.py +276 -379
- opentrons/protocol_engine/state/labware.py +62 -108
- opentrons/protocol_engine/state/labware_origin_math/errors.py +94 -0
- opentrons/protocol_engine/state/labware_origin_math/stackup_origin_to_labware_origin.py +1336 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +37 -0
- opentrons/protocol_engine/state/modules.py +30 -8
- opentrons/protocol_engine/state/motion.py +44 -0
- opentrons/protocol_engine/state/preconditions.py +59 -0
- opentrons/protocol_engine/state/state.py +44 -0
- opentrons/protocol_engine/state/state_summary.py +4 -0
- opentrons/protocol_engine/state/tasks.py +139 -0
- opentrons/protocol_engine/state/tips.py +177 -258
- opentrons/protocol_engine/state/update_types.py +26 -9
- opentrons/protocol_engine/types/__init__.py +23 -4
- opentrons/protocol_engine/types/command_preconditions.py +18 -0
- opentrons/protocol_engine/types/deck_configuration.py +5 -1
- opentrons/protocol_engine/types/instrument.py +8 -1
- opentrons/protocol_engine/types/labware.py +1 -13
- opentrons/protocol_engine/types/location.py +26 -2
- opentrons/protocol_engine/types/module.py +11 -1
- opentrons/protocol_engine/types/tasks.py +38 -0
- opentrons/protocol_engine/types/tip.py +9 -0
- opentrons/protocol_runner/create_simulating_orchestrator.py +29 -2
- opentrons/protocol_runner/protocol_runner.py +14 -1
- opentrons/protocol_runner/run_orchestrator.py +49 -2
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +2 -2
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/types.py +2 -1
- opentrons/simulate.py +51 -15
- opentrons/system/camera.py +334 -4
- opentrons/system/ffmpeg.py +110 -0
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/METADATA +4 -4
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/RECORD +188 -160
- opentrons/protocol_engine/state/_labware_origin_math.py +0 -636
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/WHEEL +0 -0
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a7.dist-info}/entry_points.txt +0 -0
- {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
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
) ->
|
|
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
|
|
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
|
|
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,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]
|