opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.0a0__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.
- opentrons/cli/analyze.py +71 -7
- opentrons/config/__init__.py +9 -0
- opentrons/config/advanced_settings.py +22 -0
- opentrons/config/defaults_ot3.py +14 -36
- opentrons/config/feature_flags.py +4 -0
- opentrons/config/types.py +6 -17
- opentrons/drivers/absorbance_reader/abstract.py +27 -3
- opentrons/drivers/absorbance_reader/async_byonoy.py +207 -154
- opentrons/drivers/absorbance_reader/driver.py +24 -15
- opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
- opentrons/drivers/absorbance_reader/simulator.py +32 -6
- opentrons/drivers/types.py +23 -1
- opentrons/execute.py +2 -2
- opentrons/hardware_control/api.py +18 -10
- opentrons/hardware_control/backends/controller.py +3 -2
- opentrons/hardware_control/backends/flex_protocol.py +11 -5
- opentrons/hardware_control/backends/ot3controller.py +18 -50
- opentrons/hardware_control/backends/ot3simulator.py +7 -6
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
- opentrons/hardware_control/module_control.py +43 -2
- opentrons/hardware_control/modules/__init__.py +7 -1
- opentrons/hardware_control/modules/absorbance_reader.py +230 -83
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/heater_shaker.py +8 -3
- opentrons/hardware_control/modules/magdeck.py +12 -3
- opentrons/hardware_control/modules/mod_abc.py +27 -2
- opentrons/hardware_control/modules/tempdeck.py +15 -7
- opentrons/hardware_control/modules/thermocycler.py +69 -3
- opentrons/hardware_control/modules/types.py +11 -5
- opentrons/hardware_control/modules/update.py +11 -5
- opentrons/hardware_control/modules/utils.py +3 -1
- opentrons/hardware_control/ot3_calibration.py +6 -6
- opentrons/hardware_control/ot3api.py +126 -89
- opentrons/hardware_control/poller.py +15 -11
- opentrons/hardware_control/protocols/__init__.py +1 -7
- opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
- opentrons/hardware_control/protocols/liquid_handler.py +5 -0
- opentrons/motion_planning/__init__.py +2 -0
- opentrons/motion_planning/waypoints.py +32 -0
- opentrons/protocol_api/__init__.py +2 -1
- opentrons/protocol_api/_liquid.py +87 -1
- opentrons/protocol_api/_parameter_context.py +10 -1
- opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
- opentrons/protocol_api/core/engine/instrument.py +29 -25
- opentrons/protocol_api/core/engine/labware.py +10 -2
- opentrons/protocol_api/core/engine/module_core.py +129 -17
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +355 -0
- opentrons/protocol_api/core/engine/protocol.py +55 -2
- opentrons/protocol_api/core/instrument.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +5 -2
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/module.py +22 -4
- opentrons/protocol_api/core/protocol.py +5 -2
- opentrons/protocol_api/instrument_context.py +52 -20
- opentrons/protocol_api/labware.py +13 -1
- opentrons/protocol_api/module_contexts.py +68 -13
- opentrons/protocol_api/protocol_context.py +38 -4
- opentrons/protocol_api/validation.py +5 -3
- opentrons/protocol_engine/__init__.py +10 -9
- opentrons/protocol_engine/actions/__init__.py +5 -0
- opentrons/protocol_engine/actions/actions.py +42 -25
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/sync_client.py +7 -1
- opentrons/protocol_engine/clients/transports.py +1 -1
- opentrons/protocol_engine/commands/__init__.py +0 -4
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +161 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +53 -9
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +160 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +196 -0
- opentrons/protocol_engine/commands/aspirate.py +29 -16
- opentrons/protocol_engine/commands/aspirate_in_place.py +32 -15
- opentrons/protocol_engine/commands/blow_out.py +63 -14
- opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
- opentrons/protocol_engine/commands/command.py +28 -17
- opentrons/protocol_engine/commands/command_unions.py +37 -24
- opentrons/protocol_engine/commands/comment.py +5 -3
- opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
- opentrons/protocol_engine/commands/custom.py +5 -3
- opentrons/protocol_engine/commands/dispense.py +42 -20
- opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
- opentrons/protocol_engine/commands/drop_tip.py +68 -15
- opentrons/protocol_engine/commands/drop_tip_in_place.py +52 -11
- opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
- opentrons/protocol_engine/commands/home.py +11 -5
- opentrons/protocol_engine/commands/liquid_probe.py +146 -88
- opentrons/protocol_engine/commands/load_labware.py +19 -5
- opentrons/protocol_engine/commands/load_liquid.py +18 -7
- opentrons/protocol_engine/commands/load_module.py +43 -6
- opentrons/protocol_engine/commands/load_pipette.py +18 -17
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
- opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
- opentrons/protocol_engine/commands/move_labware.py +106 -19
- opentrons/protocol_engine/commands/move_relative.py +15 -3
- opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
- opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
- opentrons/protocol_engine/commands/move_to_well.py +37 -10
- opentrons/protocol_engine/commands/pick_up_tip.py +50 -29
- opentrons/protocol_engine/commands/pipetting_common.py +39 -15
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
- opentrons/protocol_engine/commands/reload_labware.py +13 -4
- opentrons/protocol_engine/commands/retract_axis.py +6 -3
- opentrons/protocol_engine/commands/save_position.py +2 -3
- opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
- opentrons/protocol_engine/commands/set_status_bar.py +5 -3
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
- opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
- opentrons/protocol_engine/commands/touch_tip.py +19 -7
- opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +194 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +75 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +5 -3
- opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
- opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
- opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
- opentrons/protocol_engine/create_protocol_engine.py +41 -8
- opentrons/protocol_engine/engine_support.py +2 -1
- opentrons/protocol_engine/error_recovery_policy.py +14 -3
- opentrons/protocol_engine/errors/__init__.py +18 -0
- opentrons/protocol_engine/errors/exceptions.py +114 -2
- opentrons/protocol_engine/execution/__init__.py +2 -0
- opentrons/protocol_engine/execution/command_executor.py +22 -13
- opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
- opentrons/protocol_engine/execution/door_watcher.py +1 -1
- opentrons/protocol_engine/execution/equipment.py +2 -1
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +4 -2
- opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
- opentrons/protocol_engine/execution/labware_movement.py +6 -3
- opentrons/protocol_engine/execution/movement.py +8 -3
- opentrons/protocol_engine/execution/pipetting.py +7 -4
- opentrons/protocol_engine/execution/queue_worker.py +6 -2
- opentrons/protocol_engine/execution/run_control.py +1 -1
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
- opentrons/protocol_engine/execution/tip_handler.py +77 -43
- opentrons/protocol_engine/notes/__init__.py +14 -2
- opentrons/protocol_engine/notes/notes.py +18 -1
- opentrons/protocol_engine/plugins.py +1 -1
- opentrons/protocol_engine/protocol_engine.py +54 -31
- opentrons/protocol_engine/resources/__init__.py +2 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +58 -5
- opentrons/protocol_engine/resources/file_provider.py +157 -0
- opentrons/protocol_engine/resources/fixture_validation.py +5 -0
- opentrons/protocol_engine/resources/labware_validation.py +10 -0
- opentrons/protocol_engine/state/__init__.py +0 -70
- opentrons/protocol_engine/state/addressable_areas.py +1 -1
- opentrons/protocol_engine/state/command_history.py +21 -2
- opentrons/protocol_engine/state/commands.py +110 -31
- opentrons/protocol_engine/state/files.py +59 -0
- opentrons/protocol_engine/state/frustum_helpers.py +440 -0
- opentrons/protocol_engine/state/geometry.py +359 -15
- opentrons/protocol_engine/state/labware.py +166 -63
- opentrons/protocol_engine/state/liquids.py +1 -1
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +19 -3
- opentrons/protocol_engine/state/modules.py +167 -85
- opentrons/protocol_engine/state/motion.py +16 -9
- opentrons/protocol_engine/state/pipettes.py +157 -317
- opentrons/protocol_engine/state/state.py +30 -1
- opentrons/protocol_engine/state/state_summary.py +3 -0
- opentrons/protocol_engine/state/tips.py +69 -114
- opentrons/protocol_engine/state/update_types.py +408 -0
- opentrons/protocol_engine/state/wells.py +236 -0
- opentrons/protocol_engine/types.py +90 -0
- opentrons/protocol_reader/file_format_validator.py +83 -15
- opentrons/protocol_runner/json_translator.py +21 -5
- opentrons/protocol_runner/legacy_command_mapper.py +27 -6
- opentrons/protocol_runner/legacy_context_plugin.py +27 -71
- opentrons/protocol_runner/protocol_runner.py +6 -3
- opentrons/protocol_runner/run_orchestrator.py +26 -6
- opentrons/protocols/advanced_control/mix.py +3 -5
- opentrons/protocols/advanced_control/transfers.py +125 -56
- opentrons/protocols/api_support/constants.py +1 -1
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/labware_like.py +4 -4
- opentrons/protocols/api_support/tip_tracker.py +2 -2
- opentrons/protocols/api_support/types.py +15 -2
- opentrons/protocols/api_support/util.py +30 -42
- opentrons/protocols/duration/errors.py +1 -1
- opentrons/protocols/duration/estimator.py +50 -29
- opentrons/protocols/execution/dev_types.py +2 -2
- opentrons/protocols/execution/execute_json_v4.py +15 -10
- opentrons/protocols/execution/execute_python.py +8 -3
- opentrons/protocols/geometry/planning.py +12 -12
- opentrons/protocols/labware.py +17 -33
- opentrons/simulate.py +3 -3
- opentrons/types.py +30 -3
- opentrons/util/logging_config.py +34 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/METADATA +5 -4
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/RECORD +227 -215
- opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
- opentrons/protocol_engine/commands/configuring_common.py +0 -26
- opentrons/protocol_runner/thread_async_queue.py +0 -174
- /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
- /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/LICENSE +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/WHEEL +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/top_level.txt +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Actions can be passed to the ActionDispatcher, where they will trigger
|
|
4
4
|
reactions in objects that subscribe to the pipeline, like the StateStore.
|
|
5
5
|
"""
|
|
6
|
-
|
|
6
|
+
import dataclasses
|
|
7
7
|
from datetime import datetime
|
|
8
8
|
from enum import Enum
|
|
9
9
|
from typing import List, Optional, Union
|
|
@@ -18,10 +18,10 @@ from ..commands import (
|
|
|
18
18
|
Command,
|
|
19
19
|
CommandCreate,
|
|
20
20
|
CommandDefinedErrorData,
|
|
21
|
-
CommandPrivateResult,
|
|
22
21
|
)
|
|
23
22
|
from ..error_recovery_policy import ErrorRecoveryPolicy, ErrorRecoveryType
|
|
24
23
|
from ..notes.notes import CommandNote
|
|
24
|
+
from ..state.update_types import StateUpdate
|
|
25
25
|
from ..types import (
|
|
26
26
|
LabwareOffsetCreate,
|
|
27
27
|
ModuleDefinition,
|
|
@@ -31,7 +31,7 @@ from ..types import (
|
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
@dataclass(frozen=True)
|
|
34
|
+
@dataclasses.dataclass(frozen=True)
|
|
35
35
|
class PlayAction:
|
|
36
36
|
"""Start or resume processing commands in the engine."""
|
|
37
37
|
|
|
@@ -50,28 +50,28 @@ class PauseSource(str, Enum):
|
|
|
50
50
|
PROTOCOL = "protocol"
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
@dataclass(frozen=True)
|
|
53
|
+
@dataclasses.dataclass(frozen=True)
|
|
54
54
|
class PauseAction:
|
|
55
55
|
"""Pause processing commands in the engine."""
|
|
56
56
|
|
|
57
57
|
source: PauseSource
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
@dataclass(frozen=True)
|
|
60
|
+
@dataclasses.dataclass(frozen=True)
|
|
61
61
|
class StopAction:
|
|
62
62
|
"""Request engine execution to stop soon."""
|
|
63
63
|
|
|
64
64
|
from_estop: bool = False
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
@dataclass(frozen=True)
|
|
67
|
+
@dataclasses.dataclass(frozen=True)
|
|
68
68
|
class ResumeFromRecoveryAction:
|
|
69
69
|
"""See `ProtocolEngine.resume_from_recovery()`."""
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
state_update: StateUpdate
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
@dataclass(frozen=True)
|
|
74
|
+
@dataclasses.dataclass(frozen=True)
|
|
75
75
|
class FinishErrorDetails:
|
|
76
76
|
"""Error details for the payload of a FinishAction or HardwareStoppedAction."""
|
|
77
77
|
|
|
@@ -80,7 +80,7 @@ class FinishErrorDetails:
|
|
|
80
80
|
created_at: datetime
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
@dataclass(frozen=True)
|
|
83
|
+
@dataclasses.dataclass(frozen=True)
|
|
84
84
|
class FinishAction:
|
|
85
85
|
"""Gracefully stop processing commands in the engine."""
|
|
86
86
|
|
|
@@ -95,7 +95,7 @@ class FinishAction:
|
|
|
95
95
|
"""The fatal error that caused the run to fail."""
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
@dataclass(frozen=True)
|
|
98
|
+
@dataclasses.dataclass(frozen=True)
|
|
99
99
|
class HardwareStoppedAction:
|
|
100
100
|
"""An action dispatched after hardware has been stopped for good, for this engine instance."""
|
|
101
101
|
|
|
@@ -105,14 +105,14 @@ class HardwareStoppedAction:
|
|
|
105
105
|
"""The error that happened while doing post-run finish steps (homing and dropping tips)."""
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
@dataclass(frozen=True)
|
|
108
|
+
@dataclasses.dataclass(frozen=True)
|
|
109
109
|
class DoorChangeAction:
|
|
110
110
|
"""Handle events coming in from hardware control."""
|
|
111
111
|
|
|
112
112
|
door_state: DoorState
|
|
113
113
|
|
|
114
114
|
|
|
115
|
-
@dataclass(frozen=True)
|
|
115
|
+
@dataclasses.dataclass(frozen=True)
|
|
116
116
|
class QueueCommandAction:
|
|
117
117
|
"""Add a command request to the queue."""
|
|
118
118
|
|
|
@@ -123,7 +123,7 @@ class QueueCommandAction:
|
|
|
123
123
|
failed_command_id: Optional[str] = None
|
|
124
124
|
|
|
125
125
|
|
|
126
|
-
@dataclass(frozen=True)
|
|
126
|
+
@dataclasses.dataclass(frozen=True)
|
|
127
127
|
class RunCommandAction:
|
|
128
128
|
"""Mark a given command as running.
|
|
129
129
|
|
|
@@ -135,7 +135,7 @@ class RunCommandAction:
|
|
|
135
135
|
started_at: datetime
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
@dataclass(frozen=True)
|
|
138
|
+
@dataclasses.dataclass(frozen=True)
|
|
139
139
|
class SucceedCommandAction:
|
|
140
140
|
"""Mark a given command as succeeded.
|
|
141
141
|
|
|
@@ -145,10 +145,15 @@ class SucceedCommandAction:
|
|
|
145
145
|
command: Command
|
|
146
146
|
"""The command in its new succeeded state."""
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
state_update: StateUpdate = dataclasses.field(
|
|
149
|
+
# todo(mm, 2024-08-26): This has a default only to make it easier to transition
|
|
150
|
+
# old tests while https://opentrons.atlassian.net/browse/EXEC-639 is in
|
|
151
|
+
# progress. Make this mandatory when that's completed.
|
|
152
|
+
default_factory=StateUpdate
|
|
153
|
+
)
|
|
149
154
|
|
|
150
155
|
|
|
151
|
-
@dataclass(frozen=True)
|
|
156
|
+
@dataclasses.dataclass(frozen=True)
|
|
152
157
|
class FailCommandAction:
|
|
153
158
|
"""Mark a given command as failed.
|
|
154
159
|
|
|
@@ -196,7 +201,7 @@ class FailCommandAction:
|
|
|
196
201
|
"""The command to fail, in its prior `running` state."""
|
|
197
202
|
|
|
198
203
|
|
|
199
|
-
@dataclass(frozen=True)
|
|
204
|
+
@dataclasses.dataclass(frozen=True)
|
|
200
205
|
class AddLabwareOffsetAction:
|
|
201
206
|
"""Add a labware offset, to apply to subsequent `LoadLabwareCommand`s."""
|
|
202
207
|
|
|
@@ -205,28 +210,28 @@ class AddLabwareOffsetAction:
|
|
|
205
210
|
request: LabwareOffsetCreate
|
|
206
211
|
|
|
207
212
|
|
|
208
|
-
@dataclass(frozen=True)
|
|
213
|
+
@dataclasses.dataclass(frozen=True)
|
|
209
214
|
class AddLabwareDefinitionAction:
|
|
210
215
|
"""Add a labware definition, to apply to subsequent `LoadLabwareCommand`s."""
|
|
211
216
|
|
|
212
217
|
definition: LabwareDefinition
|
|
213
218
|
|
|
214
219
|
|
|
215
|
-
@dataclass(frozen=True)
|
|
220
|
+
@dataclasses.dataclass(frozen=True)
|
|
216
221
|
class AddLiquidAction:
|
|
217
222
|
"""Add a liquid, to apply to subsequent `LoadLiquid`s."""
|
|
218
223
|
|
|
219
224
|
liquid: Liquid
|
|
220
225
|
|
|
221
226
|
|
|
222
|
-
@dataclass(frozen=True)
|
|
227
|
+
@dataclasses.dataclass(frozen=True)
|
|
223
228
|
class SetDeckConfigurationAction:
|
|
224
229
|
"""See `ProtocolEngine.set_deck_configuration()`."""
|
|
225
230
|
|
|
226
231
|
deck_configuration: Optional[DeckConfigurationType]
|
|
227
232
|
|
|
228
233
|
|
|
229
|
-
@dataclass(frozen=True)
|
|
234
|
+
@dataclasses.dataclass(frozen=True)
|
|
230
235
|
class AddAddressableAreaAction:
|
|
231
236
|
"""Add a single addressable area to state.
|
|
232
237
|
|
|
@@ -238,7 +243,7 @@ class AddAddressableAreaAction:
|
|
|
238
243
|
addressable_area: AddressableAreaLocation
|
|
239
244
|
|
|
240
245
|
|
|
241
|
-
@dataclass(frozen=True)
|
|
246
|
+
@dataclasses.dataclass(frozen=True)
|
|
242
247
|
class AddModuleAction:
|
|
243
248
|
"""Add an attached module directly to state without a location."""
|
|
244
249
|
|
|
@@ -248,14 +253,14 @@ class AddModuleAction:
|
|
|
248
253
|
module_live_data: LiveData
|
|
249
254
|
|
|
250
255
|
|
|
251
|
-
@dataclass(frozen=True)
|
|
256
|
+
@dataclasses.dataclass(frozen=True)
|
|
252
257
|
class ResetTipsAction:
|
|
253
258
|
"""Reset the tip tracking state of a given tip rack."""
|
|
254
259
|
|
|
255
260
|
labware_id: str
|
|
256
261
|
|
|
257
262
|
|
|
258
|
-
@dataclass(frozen=True)
|
|
263
|
+
@dataclasses.dataclass(frozen=True)
|
|
259
264
|
class SetPipetteMovementSpeedAction:
|
|
260
265
|
"""Set the speed of a pipette's X/Y/Z movements. Does not affect plunger speed.
|
|
261
266
|
|
|
@@ -266,7 +271,18 @@ class SetPipetteMovementSpeedAction:
|
|
|
266
271
|
speed: Optional[float]
|
|
267
272
|
|
|
268
273
|
|
|
269
|
-
@dataclass(frozen=True)
|
|
274
|
+
@dataclasses.dataclass(frozen=True)
|
|
275
|
+
class AddAbsorbanceReaderLidAction:
|
|
276
|
+
"""Add the absorbance reader lid id to the absorbance reader module substate.
|
|
277
|
+
|
|
278
|
+
This action is dispatched the absorbance reader module is first loaded.
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
module_id: str
|
|
282
|
+
lid_id: str
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@dataclasses.dataclass(frozen=True)
|
|
270
286
|
class SetErrorRecoveryPolicyAction:
|
|
271
287
|
"""See `ProtocolEngine.set_error_recovery_policy()`."""
|
|
272
288
|
|
|
@@ -293,5 +309,6 @@ Action = Union[
|
|
|
293
309
|
AddLiquidAction,
|
|
294
310
|
ResetTipsAction,
|
|
295
311
|
SetPipetteMovementSpeedAction,
|
|
312
|
+
AddAbsorbanceReaderLidAction,
|
|
296
313
|
SetErrorRecoveryPolicyAction,
|
|
297
314
|
]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# noqa: D100
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from .actions import (
|
|
6
|
+
Action,
|
|
7
|
+
ResumeFromRecoveryAction,
|
|
8
|
+
SucceedCommandAction,
|
|
9
|
+
FailCommandAction,
|
|
10
|
+
)
|
|
11
|
+
from ..commands.command import DefinedErrorData
|
|
12
|
+
from ..error_recovery_policy import ErrorRecoveryType
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from ..state.update_types import StateUpdate
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_state_updates(action: Action) -> list[StateUpdate]:
|
|
19
|
+
"""Extract all the StateUpdates that the StateStores should apply when they apply an action."""
|
|
20
|
+
if isinstance(action, SucceedCommandAction):
|
|
21
|
+
return [action.state_update]
|
|
22
|
+
|
|
23
|
+
elif isinstance(action, FailCommandAction) and isinstance(
|
|
24
|
+
action.error, DefinedErrorData
|
|
25
|
+
):
|
|
26
|
+
if action.type == ErrorRecoveryType.ASSUME_FALSE_POSITIVE_AND_CONTINUE:
|
|
27
|
+
return [
|
|
28
|
+
action.error.state_update,
|
|
29
|
+
action.error.state_update_if_false_positive,
|
|
30
|
+
]
|
|
31
|
+
else:
|
|
32
|
+
return [action.error.state_update]
|
|
33
|
+
|
|
34
|
+
elif isinstance(action, ResumeFromRecoveryAction):
|
|
35
|
+
return [action.state_update]
|
|
36
|
+
|
|
37
|
+
else:
|
|
38
|
+
return []
|
|
@@ -7,7 +7,7 @@ from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
|
7
7
|
|
|
8
8
|
from .. import commands
|
|
9
9
|
from ..commands.command_unions import CREATE_TYPES_BY_PARAMS_TYPE
|
|
10
|
-
from ..state import StateView
|
|
10
|
+
from ..state.state import StateView
|
|
11
11
|
from ..types import (
|
|
12
12
|
Liquid,
|
|
13
13
|
LabwareOffsetCreate,
|
|
@@ -119,6 +119,12 @@ class SyncClient:
|
|
|
119
119
|
"add_addressable_area", addressable_area_name=addressable_area_name
|
|
120
120
|
)
|
|
121
121
|
|
|
122
|
+
def add_absorbance_reader_lid(self, module_id: str, lid_id: str) -> None:
|
|
123
|
+
"""Add an absorbance reader lid to the module state."""
|
|
124
|
+
self._transport.call_method(
|
|
125
|
+
"add_absorbance_reader_lid", module_id=module_id, lid_id=lid_id
|
|
126
|
+
)
|
|
127
|
+
|
|
122
128
|
def add_liquid(
|
|
123
129
|
self, name: str, color: Optional[str], description: Optional[str]
|
|
124
130
|
) -> Liquid:
|
|
@@ -10,7 +10,7 @@ from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
|
10
10
|
from ..protocol_engine import ProtocolEngine
|
|
11
11
|
from ..errors import ProtocolCommandFailedError
|
|
12
12
|
from ..error_recovery_policy import ErrorRecoveryType
|
|
13
|
-
from ..state import StateView
|
|
13
|
+
from ..state.state import StateView
|
|
14
14
|
from ..commands import Command, CommandCreate, CommandResult, CommandStatus
|
|
15
15
|
|
|
16
16
|
|
|
@@ -38,7 +38,6 @@ from .command_unions import (
|
|
|
38
38
|
CommandCreate,
|
|
39
39
|
CommandResult,
|
|
40
40
|
CommandType,
|
|
41
|
-
CommandPrivateResult,
|
|
42
41
|
CommandDefinedErrorData,
|
|
43
42
|
)
|
|
44
43
|
|
|
@@ -153,7 +152,6 @@ from .load_pipette import (
|
|
|
153
152
|
LoadPipetteCreate,
|
|
154
153
|
LoadPipetteResult,
|
|
155
154
|
LoadPipetteCommandType,
|
|
156
|
-
LoadPipettePrivateResult,
|
|
157
155
|
)
|
|
158
156
|
|
|
159
157
|
from .move_labware import (
|
|
@@ -306,7 +304,6 @@ from .configure_nozzle_layout import (
|
|
|
306
304
|
ConfigureNozzleLayoutCreate,
|
|
307
305
|
ConfigureNozzleLayoutParams,
|
|
308
306
|
ConfigureNozzleLayoutResult,
|
|
309
|
-
ConfigureNozzleLayoutPrivateResult,
|
|
310
307
|
ConfigureNozzleLayoutCommandType,
|
|
311
308
|
)
|
|
312
309
|
|
|
@@ -569,7 +566,6 @@ __all__ = [
|
|
|
569
566
|
"ConfigureNozzleLayoutParams",
|
|
570
567
|
"ConfigureNozzleLayoutResult",
|
|
571
568
|
"ConfigureNozzleLayoutCommandType",
|
|
572
|
-
"ConfigureNozzleLayoutPrivateResult",
|
|
573
569
|
# get pipette tip presence bundle
|
|
574
570
|
"GetTipPresence",
|
|
575
571
|
"GetTipPresenceCreate",
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
"""Command models for Absorbance Reader commands."""
|
|
2
|
+
from .close_lid import (
|
|
3
|
+
CloseLidCommandType,
|
|
4
|
+
CloseLidParams,
|
|
5
|
+
CloseLidResult,
|
|
6
|
+
CloseLid,
|
|
7
|
+
CloseLidCreate,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from .open_lid import (
|
|
11
|
+
OpenLidCommandType,
|
|
12
|
+
OpenLidParams,
|
|
13
|
+
OpenLidResult,
|
|
14
|
+
OpenLid,
|
|
15
|
+
OpenLidCreate,
|
|
16
|
+
)
|
|
2
17
|
|
|
3
18
|
from .initialize import (
|
|
4
19
|
InitializeCommandType,
|
|
@@ -8,15 +23,29 @@ from .initialize import (
|
|
|
8
23
|
InitializeCreate,
|
|
9
24
|
)
|
|
10
25
|
|
|
11
|
-
from .
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
from .read import (
|
|
27
|
+
ReadAbsorbanceCommandType,
|
|
28
|
+
ReadAbsorbanceParams,
|
|
29
|
+
ReadAbsorbanceResult,
|
|
30
|
+
ReadAbsorbance,
|
|
31
|
+
ReadAbsorbanceCreate,
|
|
17
32
|
)
|
|
18
33
|
|
|
34
|
+
|
|
19
35
|
__all__ = [
|
|
36
|
+
"MoveLidResult",
|
|
37
|
+
# absorbanace_reader/closeLid
|
|
38
|
+
"CloseLidCommandType",
|
|
39
|
+
"CloseLidParams",
|
|
40
|
+
"CloseLidResult",
|
|
41
|
+
"CloseLid",
|
|
42
|
+
"CloseLidCreate",
|
|
43
|
+
# absorbanace_reader/openLid
|
|
44
|
+
"OpenLidCommandType",
|
|
45
|
+
"OpenLidParams",
|
|
46
|
+
"OpenLidResult",
|
|
47
|
+
"OpenLid",
|
|
48
|
+
"OpenLidCreate",
|
|
20
49
|
# absorbanace_reader/initialize
|
|
21
50
|
"InitializeCommandType",
|
|
22
51
|
"InitializeParams",
|
|
@@ -24,9 +53,10 @@ __all__ = [
|
|
|
24
53
|
"Initialize",
|
|
25
54
|
"InitializeCreate",
|
|
26
55
|
# absorbanace_reader/measure
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
56
|
+
"ReadAbsorbanceCommandType",
|
|
57
|
+
"ReadAbsorbanceParams",
|
|
58
|
+
"ReadAbsorbanceResult",
|
|
59
|
+
"ReadAbsorbance",
|
|
60
|
+
"ReadAbsorbanceCreate",
|
|
61
|
+
# union type
|
|
32
62
|
]
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""Command models to close the lid on an Absorbance Reader."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from typing import Optional, Literal, TYPE_CHECKING
|
|
4
|
+
from typing_extensions import Type
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
9
|
+
from ...errors.error_occurrence import ErrorOccurrence
|
|
10
|
+
from ...errors import CannotPerformModuleAction
|
|
11
|
+
from opentrons.protocol_engine.types import AddressableAreaLocation
|
|
12
|
+
|
|
13
|
+
from opentrons.protocol_engine.resources import labware_validation
|
|
14
|
+
from ...state.update_types import StateUpdate
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
from opentrons.drivers.types import AbsorbanceReaderLidStatus
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
21
|
+
from opentrons.protocol_engine.execution import (
|
|
22
|
+
EquipmentHandler,
|
|
23
|
+
LabwareMovementHandler,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
CloseLidCommandType = Literal["absorbanceReader/closeLid"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CloseLidParams(BaseModel):
|
|
31
|
+
"""Input parameters to close the lid on an absorbance reading."""
|
|
32
|
+
|
|
33
|
+
moduleId: str = Field(..., description="Unique ID of the absorbance reader.")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CloseLidResult(BaseModel):
|
|
37
|
+
"""Result data from closing the lid on an aborbance reading."""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class CloseLidImpl(AbstractCommandImpl[CloseLidParams, SuccessData[CloseLidResult]]):
|
|
41
|
+
"""Execution implementation of closing the lid on an Absorbance Reader."""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
state_view: StateView,
|
|
46
|
+
equipment: EquipmentHandler,
|
|
47
|
+
labware_movement: LabwareMovementHandler,
|
|
48
|
+
**unused_dependencies: object,
|
|
49
|
+
) -> None:
|
|
50
|
+
self._state_view = state_view
|
|
51
|
+
self._equipment = equipment
|
|
52
|
+
self._labware_movement = labware_movement
|
|
53
|
+
|
|
54
|
+
async def execute(self, params: CloseLidParams) -> SuccessData[CloseLidResult]:
|
|
55
|
+
"""Execute the close lid command."""
|
|
56
|
+
mod_substate = self._state_view.modules.get_absorbance_reader_substate(
|
|
57
|
+
module_id=params.moduleId
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# lid should currently be on the module
|
|
61
|
+
assert mod_substate.lid_id is not None
|
|
62
|
+
loaded_lid = self._state_view.labware.get(mod_substate.lid_id)
|
|
63
|
+
assert labware_validation.is_absorbance_reader_lid(loaded_lid.loadName)
|
|
64
|
+
|
|
65
|
+
hardware_lid_status = AbsorbanceReaderLidStatus.OFF
|
|
66
|
+
# If the lid is closed, if the lid is open No-op out
|
|
67
|
+
if not self._state_view.config.use_virtual_modules:
|
|
68
|
+
abs_reader = self._equipment.get_module_hardware_api(mod_substate.module_id)
|
|
69
|
+
|
|
70
|
+
if abs_reader is not None:
|
|
71
|
+
result = await abs_reader.get_current_lid_status()
|
|
72
|
+
hardware_lid_status = result
|
|
73
|
+
else:
|
|
74
|
+
raise CannotPerformModuleAction(
|
|
75
|
+
"Could not reach the Hardware API for Opentrons Plate Reader Module."
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# If the lid is already ON, no-op losing lid
|
|
79
|
+
if hardware_lid_status is AbsorbanceReaderLidStatus.ON:
|
|
80
|
+
# The lid is already On, so we can no-op and return the lids current location data
|
|
81
|
+
assert isinstance(loaded_lid.location, AddressableAreaLocation)
|
|
82
|
+
new_location = loaded_lid.location
|
|
83
|
+
new_offset_id = self._equipment.find_applicable_labware_offset_id(
|
|
84
|
+
labware_definition_uri=loaded_lid.definitionUri,
|
|
85
|
+
labware_location=loaded_lid.location,
|
|
86
|
+
)
|
|
87
|
+
else:
|
|
88
|
+
# Allow propagation of ModuleNotAttachedError.
|
|
89
|
+
_ = self._equipment.get_module_hardware_api(mod_substate.module_id)
|
|
90
|
+
|
|
91
|
+
current_location = self._state_view.modules.absorbance_reader_dock_location(
|
|
92
|
+
params.moduleId
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# we need to move the lid onto the module reader
|
|
96
|
+
absorbance_model = self._state_view.modules.get_requested_model(
|
|
97
|
+
params.moduleId
|
|
98
|
+
)
|
|
99
|
+
assert absorbance_model is not None
|
|
100
|
+
new_location = AddressableAreaLocation(
|
|
101
|
+
addressableAreaName=self._state_view.modules.ensure_and_convert_module_fixture_location(
|
|
102
|
+
deck_slot=self._state_view.modules.get_location(
|
|
103
|
+
params.moduleId
|
|
104
|
+
).slotName,
|
|
105
|
+
deck_type=self._state_view.config.deck_type,
|
|
106
|
+
model=absorbance_model,
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
lid_gripper_offsets = self._state_view.labware.get_labware_gripper_offsets(
|
|
111
|
+
loaded_lid.id, None
|
|
112
|
+
)
|
|
113
|
+
if lid_gripper_offsets is None:
|
|
114
|
+
raise ValueError(
|
|
115
|
+
"Gripper Offset values for Absorbance Reader Lid labware must not be None."
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Skips gripper moves when using virtual gripper
|
|
119
|
+
await self._labware_movement.move_labware_with_gripper(
|
|
120
|
+
labware_id=loaded_lid.id,
|
|
121
|
+
current_location=current_location,
|
|
122
|
+
new_location=new_location,
|
|
123
|
+
user_offset_data=lid_gripper_offsets,
|
|
124
|
+
post_drop_slide_offset=None,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
new_offset_id = self._equipment.find_applicable_labware_offset_id(
|
|
128
|
+
labware_definition_uri=loaded_lid.definitionUri,
|
|
129
|
+
labware_location=new_location,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
state_update = StateUpdate()
|
|
133
|
+
state_update.set_labware_location(
|
|
134
|
+
labware_id=loaded_lid.id,
|
|
135
|
+
new_location=new_location,
|
|
136
|
+
new_offset_id=new_offset_id,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return SuccessData(
|
|
140
|
+
public=CloseLidResult(),
|
|
141
|
+
state_update=state_update,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class CloseLid(BaseCommand[CloseLidParams, CloseLidResult, ErrorOccurrence]):
|
|
146
|
+
"""A command to close the lid on an Absorbance Reader."""
|
|
147
|
+
|
|
148
|
+
commandType: CloseLidCommandType = "absorbanceReader/closeLid"
|
|
149
|
+
params: CloseLidParams
|
|
150
|
+
result: Optional[CloseLidResult]
|
|
151
|
+
|
|
152
|
+
_ImplementationCls: Type[CloseLidImpl] = CloseLidImpl
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class CloseLidCreate(BaseCommandCreate[CloseLidParams]):
|
|
156
|
+
"""A request to execute an Absorbance Reader close lid command."""
|
|
157
|
+
|
|
158
|
+
commandType: CloseLidCommandType = "absorbanceReader/closeLid"
|
|
159
|
+
params: CloseLidParams
|
|
160
|
+
|
|
161
|
+
_CommandCls: Type[CloseLid] = CloseLid
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
"""Command models to initialize an Absorbance Reader."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
-
from typing import Optional, Literal, TYPE_CHECKING
|
|
3
|
+
from typing import List, Optional, Literal, TYPE_CHECKING
|
|
4
4
|
from typing_extensions import Type
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
8
|
+
from opentrons.drivers.types import ABSMeasurementMode
|
|
9
|
+
from opentrons.protocol_engine.types import ABSMeasureMode
|
|
10
|
+
|
|
8
11
|
from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
9
12
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
10
13
|
|
|
11
14
|
if TYPE_CHECKING:
|
|
12
|
-
from opentrons.protocol_engine.state import StateView
|
|
15
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
13
16
|
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
14
17
|
|
|
15
18
|
|
|
@@ -20,7 +23,13 @@ class InitializeParams(BaseModel):
|
|
|
20
23
|
"""Input parameters to initialize an absorbance reading."""
|
|
21
24
|
|
|
22
25
|
moduleId: str = Field(..., description="Unique ID of the absorbance reader.")
|
|
23
|
-
|
|
26
|
+
measureMode: ABSMeasureMode = Field(
|
|
27
|
+
..., description="Initialize single or multi measurement mode."
|
|
28
|
+
)
|
|
29
|
+
sampleWavelengths: List[int] = Field(..., description="Sample wavelengths in nm.")
|
|
30
|
+
referenceWavelength: Optional[int] = Field(
|
|
31
|
+
None, description="Optional reference wavelength in nm."
|
|
32
|
+
)
|
|
24
33
|
|
|
25
34
|
|
|
26
35
|
class InitializeResult(BaseModel):
|
|
@@ -28,7 +37,7 @@ class InitializeResult(BaseModel):
|
|
|
28
37
|
|
|
29
38
|
|
|
30
39
|
class InitializeImpl(
|
|
31
|
-
AbstractCommandImpl[InitializeParams, SuccessData[InitializeResult
|
|
40
|
+
AbstractCommandImpl[InitializeParams, SuccessData[InitializeResult]]
|
|
32
41
|
):
|
|
33
42
|
"""Execution implementation of initializing an Absorbance Reader."""
|
|
34
43
|
|
|
@@ -41,9 +50,7 @@ class InitializeImpl(
|
|
|
41
50
|
self._state_view = state_view
|
|
42
51
|
self._equipment = equipment
|
|
43
52
|
|
|
44
|
-
async def execute(
|
|
45
|
-
self, params: InitializeParams
|
|
46
|
-
) -> SuccessData[InitializeResult, None]:
|
|
53
|
+
async def execute(self, params: InitializeParams) -> SuccessData[InitializeResult]:
|
|
47
54
|
"""Initiate a single absorbance measurement."""
|
|
48
55
|
abs_reader_substate = self._state_view.modules.get_absorbance_reader_substate(
|
|
49
56
|
module_id=params.moduleId
|
|
@@ -54,11 +61,48 @@ class InitializeImpl(
|
|
|
54
61
|
)
|
|
55
62
|
|
|
56
63
|
if abs_reader is not None:
|
|
57
|
-
|
|
64
|
+
# Validate the parameters before initializing.
|
|
65
|
+
sample_wavelengths = set(params.sampleWavelengths)
|
|
66
|
+
sample_wavelengths_len = len(params.sampleWavelengths)
|
|
67
|
+
reference_wavelength = params.referenceWavelength
|
|
68
|
+
supported_wavelengths = set(abs_reader.supported_wavelengths)
|
|
69
|
+
unsupported_wavelengths = sample_wavelengths.difference(
|
|
70
|
+
supported_wavelengths
|
|
71
|
+
)
|
|
72
|
+
if unsupported_wavelengths:
|
|
73
|
+
raise ValueError(f"Unsupported wavelengths: {unsupported_wavelengths}")
|
|
74
|
+
|
|
75
|
+
if params.measureMode == "single":
|
|
76
|
+
if sample_wavelengths_len != 1:
|
|
77
|
+
raise ValueError(
|
|
78
|
+
f"single requires one sample wavelength, provided {sample_wavelengths}"
|
|
79
|
+
)
|
|
80
|
+
if (
|
|
81
|
+
reference_wavelength is not None
|
|
82
|
+
and reference_wavelength not in supported_wavelengths
|
|
83
|
+
):
|
|
84
|
+
raise ValueError(
|
|
85
|
+
f"Reference wavelength {reference_wavelength} not supported {supported_wavelengths}"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if params.measureMode == "multi":
|
|
89
|
+
if sample_wavelengths_len < 1 or sample_wavelengths_len > 6:
|
|
90
|
+
raise ValueError(
|
|
91
|
+
f"multi requires 1-6 sample wavelengths, provided {sample_wavelengths}"
|
|
92
|
+
)
|
|
93
|
+
if reference_wavelength is not None:
|
|
94
|
+
raise RuntimeError(
|
|
95
|
+
"Reference wavelength cannot be used with multi mode."
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
await abs_reader.set_sample_wavelength(
|
|
99
|
+
ABSMeasurementMode(params.measureMode),
|
|
100
|
+
params.sampleWavelengths,
|
|
101
|
+
reference_wavelength=params.referenceWavelength,
|
|
102
|
+
)
|
|
58
103
|
|
|
59
104
|
return SuccessData(
|
|
60
105
|
public=InitializeResult(),
|
|
61
|
-
private=None,
|
|
62
106
|
)
|
|
63
107
|
|
|
64
108
|
|