opentrons 8.3.2__py2.py3-none-any.whl → 8.4.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/calibration_storage/ot2/mark_bad_calibration.py +2 -0
- opentrons/calibration_storage/ot2/tip_length.py +6 -6
- opentrons/config/advanced_settings.py +9 -11
- opentrons/config/feature_flags.py +0 -4
- opentrons/config/reset.py +7 -2
- opentrons/drivers/asyncio/communication/__init__.py +2 -0
- opentrons/drivers/asyncio/communication/async_serial.py +4 -0
- opentrons/drivers/asyncio/communication/errors.py +41 -8
- opentrons/drivers/asyncio/communication/serial_connection.py +36 -10
- opentrons/drivers/flex_stacker/__init__.py +9 -3
- opentrons/drivers/flex_stacker/abstract.py +140 -15
- opentrons/drivers/flex_stacker/driver.py +593 -47
- opentrons/drivers/flex_stacker/errors.py +64 -0
- opentrons/drivers/flex_stacker/simulator.py +222 -24
- opentrons/drivers/flex_stacker/types.py +211 -15
- opentrons/drivers/flex_stacker/utils.py +19 -0
- opentrons/execute.py +4 -2
- opentrons/hardware_control/api.py +5 -0
- opentrons/hardware_control/backends/flex_protocol.py +4 -0
- opentrons/hardware_control/backends/ot3controller.py +12 -1
- opentrons/hardware_control/backends/ot3simulator.py +3 -0
- opentrons/hardware_control/backends/subsystem_manager.py +8 -4
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +10 -6
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +59 -6
- opentrons/hardware_control/modules/__init__.py +12 -1
- opentrons/hardware_control/modules/absorbance_reader.py +11 -9
- opentrons/hardware_control/modules/flex_stacker.py +498 -0
- opentrons/hardware_control/modules/heater_shaker.py +12 -10
- opentrons/hardware_control/modules/magdeck.py +5 -1
- opentrons/hardware_control/modules/tempdeck.py +5 -1
- opentrons/hardware_control/modules/thermocycler.py +15 -14
- opentrons/hardware_control/modules/types.py +191 -1
- opentrons/hardware_control/modules/utils.py +3 -0
- opentrons/hardware_control/motion_utilities.py +20 -0
- opentrons/hardware_control/ot3api.py +145 -15
- opentrons/hardware_control/protocols/liquid_handler.py +47 -1
- opentrons/hardware_control/types.py +6 -0
- opentrons/legacy_commands/commands.py +102 -5
- opentrons/legacy_commands/helpers.py +74 -1
- opentrons/legacy_commands/types.py +33 -2
- opentrons/protocol_api/__init__.py +2 -0
- opentrons/protocol_api/_liquid.py +39 -8
- opentrons/protocol_api/_liquid_properties.py +20 -19
- opentrons/protocol_api/_transfer_liquid_validation.py +91 -0
- opentrons/protocol_api/core/common.py +3 -1
- opentrons/protocol_api/core/engine/deck_conflict.py +11 -1
- opentrons/protocol_api/core/engine/instrument.py +1356 -107
- opentrons/protocol_api/core/engine/labware.py +8 -4
- opentrons/protocol_api/core/engine/load_labware_params.py +68 -10
- opentrons/protocol_api/core/engine/module_core.py +118 -2
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +6 -14
- opentrons/protocol_api/core/engine/protocol.py +253 -11
- opentrons/protocol_api/core/engine/stringify.py +19 -8
- opentrons/protocol_api/core/engine/transfer_components_executor.py +858 -0
- opentrons/protocol_api/core/engine/well.py +73 -5
- opentrons/protocol_api/core/instrument.py +71 -21
- opentrons/protocol_api/core/labware.py +6 -2
- opentrons/protocol_api/core/legacy/labware_offset_provider.py +7 -3
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +76 -49
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +8 -4
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +36 -0
- opentrons/protocol_api/core/legacy/legacy_well_core.py +27 -2
- opentrons/protocol_api/core/legacy/load_info.py +4 -12
- opentrons/protocol_api/core/legacy/module_geometry.py +6 -1
- opentrons/protocol_api/core/legacy/well_geometry.py +3 -3
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +73 -23
- opentrons/protocol_api/core/module.py +43 -0
- opentrons/protocol_api/core/protocol.py +33 -0
- opentrons/protocol_api/core/well.py +23 -2
- opentrons/protocol_api/instrument_context.py +454 -150
- opentrons/protocol_api/labware.py +98 -50
- opentrons/protocol_api/module_contexts.py +140 -0
- opentrons/protocol_api/protocol_context.py +163 -19
- opentrons/protocol_api/validation.py +51 -41
- opentrons/protocol_engine/__init__.py +21 -2
- opentrons/protocol_engine/actions/actions.py +5 -5
- opentrons/protocol_engine/clients/sync_client.py +6 -0
- opentrons/protocol_engine/commands/__init__.py +66 -36
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +0 -1
- opentrons/protocol_engine/commands/air_gap_in_place.py +3 -2
- opentrons/protocol_engine/commands/aspirate.py +6 -2
- opentrons/protocol_engine/commands/aspirate_in_place.py +3 -1
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +210 -0
- opentrons/protocol_engine/commands/blow_out.py +2 -0
- opentrons/protocol_engine/commands/blow_out_in_place.py +4 -1
- opentrons/protocol_engine/commands/command_unions.py +102 -33
- opentrons/protocol_engine/commands/configure_for_volume.py +3 -0
- opentrons/protocol_engine/commands/dispense.py +3 -1
- opentrons/protocol_engine/commands/dispense_in_place.py +3 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
- opentrons/protocol_engine/commands/drop_tip.py +23 -1
- opentrons/protocol_engine/commands/flex_stacker/__init__.py +106 -0
- opentrons/protocol_engine/commands/flex_stacker/close_latch.py +72 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +15 -0
- opentrons/protocol_engine/commands/flex_stacker/empty.py +161 -0
- opentrons/protocol_engine/commands/flex_stacker/fill.py +164 -0
- opentrons/protocol_engine/commands/flex_stacker/open_latch.py +70 -0
- opentrons/protocol_engine/commands/flex_stacker/prepare_shuttle.py +112 -0
- opentrons/protocol_engine/commands/flex_stacker/retrieve.py +394 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +190 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +291 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +31 -2
- opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
- opentrons/protocol_engine/commands/liquid_probe.py +27 -13
- opentrons/protocol_engine/commands/load_labware.py +42 -39
- opentrons/protocol_engine/commands/load_lid.py +21 -13
- opentrons/protocol_engine/commands/load_lid_stack.py +130 -47
- opentrons/protocol_engine/commands/load_module.py +18 -17
- opentrons/protocol_engine/commands/load_pipette.py +3 -0
- opentrons/protocol_engine/commands/move_labware.py +139 -20
- opentrons/protocol_engine/commands/move_to_well.py +5 -11
- opentrons/protocol_engine/commands/pick_up_tip.py +5 -2
- opentrons/protocol_engine/commands/pipetting_common.py +159 -8
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +15 -5
- opentrons/protocol_engine/commands/{evotip_dispense.py → pressure_dispense.py} +33 -34
- opentrons/protocol_engine/commands/reload_labware.py +6 -19
- opentrons/protocol_engine/commands/{evotip_seal_pipette.py → seal_pipette_to_tip.py} +97 -76
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +3 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +6 -1
- opentrons/protocol_engine/commands/{evotip_unseal_pipette.py → unseal_pipette_from_tip.py} +31 -40
- opentrons/protocol_engine/errors/__init__.py +10 -0
- opentrons/protocol_engine/errors/exceptions.py +62 -0
- opentrons/protocol_engine/execution/equipment.py +123 -106
- opentrons/protocol_engine/execution/labware_movement.py +8 -6
- opentrons/protocol_engine/execution/pipetting.py +235 -25
- opentrons/protocol_engine/execution/tip_handler.py +82 -32
- opentrons/protocol_engine/labware_offset_standardization.py +194 -0
- opentrons/protocol_engine/protocol_engine.py +22 -13
- opentrons/protocol_engine/resources/deck_configuration_provider.py +98 -2
- opentrons/protocol_engine/resources/deck_data_provider.py +1 -1
- opentrons/protocol_engine/resources/labware_data_provider.py +32 -12
- opentrons/protocol_engine/resources/labware_validation.py +7 -5
- opentrons/protocol_engine/slot_standardization.py +11 -23
- opentrons/protocol_engine/state/addressable_areas.py +84 -46
- opentrons/protocol_engine/state/frustum_helpers.py +36 -14
- opentrons/protocol_engine/state/geometry.py +892 -227
- opentrons/protocol_engine/state/labware.py +252 -55
- opentrons/protocol_engine/state/module_substates/__init__.py +4 -0
- opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +68 -0
- opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +22 -0
- opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +13 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +20 -0
- opentrons/protocol_engine/state/modules.py +210 -67
- opentrons/protocol_engine/state/pipettes.py +54 -0
- opentrons/protocol_engine/state/state.py +1 -1
- opentrons/protocol_engine/state/tips.py +14 -0
- opentrons/protocol_engine/state/update_types.py +180 -25
- opentrons/protocol_engine/state/wells.py +55 -9
- opentrons/protocol_engine/types/__init__.py +300 -0
- opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
- opentrons/protocol_engine/types/command_annotations.py +53 -0
- opentrons/protocol_engine/types/deck_configuration.py +72 -0
- opentrons/protocol_engine/types/execution.py +96 -0
- opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
- opentrons/protocol_engine/types/instrument.py +47 -0
- opentrons/protocol_engine/types/instrument_sensors.py +47 -0
- opentrons/protocol_engine/types/labware.py +111 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +111 -0
- opentrons/protocol_engine/types/labware_offset_vector.py +33 -0
- opentrons/protocol_engine/types/liquid.py +40 -0
- opentrons/protocol_engine/types/liquid_class.py +59 -0
- opentrons/protocol_engine/types/liquid_handling.py +13 -0
- opentrons/protocol_engine/types/liquid_level_detection.py +131 -0
- opentrons/protocol_engine/types/location.py +194 -0
- opentrons/protocol_engine/types/module.py +301 -0
- opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
- opentrons/protocol_engine/types/run_time_parameters.py +133 -0
- opentrons/protocol_engine/types/tip.py +18 -0
- opentrons/protocol_engine/types/util.py +21 -0
- opentrons/protocol_engine/types/well_position.py +124 -0
- opentrons/protocol_reader/extract_labware_definitions.py +7 -3
- opentrons/protocol_reader/file_format_validator.py +5 -3
- opentrons/protocol_runner/json_translator.py +4 -2
- opentrons/protocol_runner/legacy_command_mapper.py +6 -2
- opentrons/protocol_runner/run_orchestrator.py +4 -1
- opentrons/protocols/advanced_control/transfers/common.py +48 -1
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +204 -0
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/instrument.py +16 -3
- opentrons/protocols/labware.py +27 -23
- opentrons/protocols/models/__init__.py +0 -21
- opentrons/simulate.py +4 -2
- opentrons/types.py +20 -7
- opentrons/util/logging_config.py +94 -25
- opentrons/util/logging_queue_handler.py +61 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/METADATA +4 -4
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/RECORD +192 -151
- opentrons/calibration_storage/ot2/models/defaults.py +0 -0
- opentrons/calibration_storage/ot3/models/defaults.py +0 -0
- opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
- opentrons/protocol_engine/types.py +0 -1311
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/LICENSE +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/WHEEL +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Structures to represent changes that commands want to make to engine state."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import dataclasses
|
|
4
6
|
import enum
|
|
5
7
|
import typing
|
|
@@ -16,6 +18,7 @@ from opentrons.protocol_engine.types import (
|
|
|
16
18
|
AspiratedFluid,
|
|
17
19
|
LiquidClassRecord,
|
|
18
20
|
ABSMeasureMode,
|
|
21
|
+
LiquidTrackingType,
|
|
19
22
|
)
|
|
20
23
|
from opentrons.types import MountType
|
|
21
24
|
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
@@ -58,6 +61,16 @@ Unfortunately, mypy doesn't let us write `Literal[CLEAR]`. Use this instead.
|
|
|
58
61
|
"""
|
|
59
62
|
|
|
60
63
|
|
|
64
|
+
class _SimulatedEnum(enum.Enum):
|
|
65
|
+
SIMULATED = enum.auto()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
SIMULATED: typing.Final = _SimulatedEnum.SIMULATED
|
|
69
|
+
"""A sentinel value to indicate that a liquid probe return value is simulated.
|
|
70
|
+
|
|
71
|
+
Useful to avoid throwing unnecessary errors in protocol analysis."""
|
|
72
|
+
|
|
73
|
+
|
|
61
74
|
@dataclasses.dataclass(frozen=True)
|
|
62
75
|
class Well:
|
|
63
76
|
"""Designates a well in a labware."""
|
|
@@ -104,6 +117,16 @@ class LabwareLocationUpdate:
|
|
|
104
117
|
"""The ID of the labware's new offset, for its new location."""
|
|
105
118
|
|
|
106
119
|
|
|
120
|
+
@dataclasses.dataclass
|
|
121
|
+
class BatchLabwareLocationUpdate:
|
|
122
|
+
"""An update to the locations of multiple labware."""
|
|
123
|
+
|
|
124
|
+
new_locations_by_id: dict[str, LabwareLocation]
|
|
125
|
+
"""The new locations of each ID."""
|
|
126
|
+
new_offset_ids_by_id: dict[str, str | None]
|
|
127
|
+
"""The new offsets of each id."""
|
|
128
|
+
|
|
129
|
+
|
|
107
130
|
@dataclasses.dataclass
|
|
108
131
|
class LoadedLabwareUpdate:
|
|
109
132
|
"""An update that loads a new labware."""
|
|
@@ -122,6 +145,23 @@ class LoadedLabwareUpdate:
|
|
|
122
145
|
definition: LabwareDefinition
|
|
123
146
|
|
|
124
147
|
|
|
148
|
+
@dataclasses.dataclass
|
|
149
|
+
class BatchLoadedLabwareUpdate:
|
|
150
|
+
"""An update that loads multiple new labware."""
|
|
151
|
+
|
|
152
|
+
new_locations_by_id: typing.Dict[str, LabwareLocation]
|
|
153
|
+
"""Each new labwares's initial location keyed by Labware ID."""
|
|
154
|
+
|
|
155
|
+
offset_ids_by_id: typing.Dict[str, str | None]
|
|
156
|
+
"""The ID of each labware's offset keyed by labware ID."""
|
|
157
|
+
|
|
158
|
+
display_names_by_id: typing.Dict[str, str | None]
|
|
159
|
+
"""The Display Name for each new labware keyed by labware ID"""
|
|
160
|
+
|
|
161
|
+
definitions_by_id: typing.Dict[str, LabwareDefinition]
|
|
162
|
+
"""The Labware Definition for each labware keyed by Labware ID."""
|
|
163
|
+
|
|
164
|
+
|
|
125
165
|
@dataclasses.dataclass
|
|
126
166
|
class LoadedLidStackUpdate:
|
|
127
167
|
"""An update that loads a new lid stack."""
|
|
@@ -135,13 +175,10 @@ class LoadedLidStackUpdate:
|
|
|
135
175
|
stack_location: LabwareLocation
|
|
136
176
|
"The initial location of the Lid Stack Object."
|
|
137
177
|
|
|
138
|
-
labware_ids: typing.List[str]
|
|
139
|
-
"""The unique IDs of the new lids."""
|
|
140
|
-
|
|
141
178
|
new_locations_by_id: typing.Dict[str, OnLabwareLocation]
|
|
142
179
|
"""Each lid's initial location keyed by Labware ID."""
|
|
143
180
|
|
|
144
|
-
definition: LabwareDefinition
|
|
181
|
+
definition: LabwareDefinition | None
|
|
145
182
|
"The Labware Definition of the Lid Labware(s) loaded."
|
|
146
183
|
|
|
147
184
|
|
|
@@ -149,10 +186,10 @@ class LoadedLidStackUpdate:
|
|
|
149
186
|
class LabwareLidUpdate:
|
|
150
187
|
"""An update that identifies a lid on a given parent labware."""
|
|
151
188
|
|
|
152
|
-
|
|
153
|
-
"""The unique
|
|
189
|
+
parent_labware_ids: typing.List[str]
|
|
190
|
+
"""The unique IDs of the parent labwares."""
|
|
154
191
|
|
|
155
|
-
|
|
192
|
+
lid_ids: typing.List[str | None]
|
|
156
193
|
"""The unique IDs of the new lids."""
|
|
157
194
|
|
|
158
195
|
|
|
@@ -201,6 +238,14 @@ class PipetteTipStateUpdate:
|
|
|
201
238
|
tip_geometry: TipGeometry | None
|
|
202
239
|
|
|
203
240
|
|
|
241
|
+
@dataclasses.dataclass
|
|
242
|
+
class PipetteAspirateReadyUpdate:
|
|
243
|
+
"""Update pipette ready state."""
|
|
244
|
+
|
|
245
|
+
pipette_id: str
|
|
246
|
+
ready_to_aspirate: bool
|
|
247
|
+
|
|
248
|
+
|
|
204
249
|
@dataclasses.dataclass
|
|
205
250
|
class TipsUsedUpdate:
|
|
206
251
|
"""Represents an update that marks tips in a tip rack as used."""
|
|
@@ -234,8 +279,8 @@ class LiquidProbedUpdate:
|
|
|
234
279
|
labware_id: str
|
|
235
280
|
well_name: str
|
|
236
281
|
last_probed: datetime
|
|
237
|
-
height:
|
|
238
|
-
volume:
|
|
282
|
+
height: LiquidTrackingType | ClearType
|
|
283
|
+
volume: LiquidTrackingType | ClearType
|
|
239
284
|
|
|
240
285
|
|
|
241
286
|
@dataclasses.dataclass
|
|
@@ -278,6 +323,7 @@ class PipetteEmptyFluidUpdate:
|
|
|
278
323
|
"""Sets the pipette to be valid and empty."""
|
|
279
324
|
|
|
280
325
|
pipette_id: str
|
|
326
|
+
clean_tip: bool
|
|
281
327
|
type: typing.Literal["empty"] = "empty"
|
|
282
328
|
|
|
283
329
|
|
|
@@ -311,9 +357,40 @@ class AbsorbanceReaderStateUpdate:
|
|
|
311
357
|
module_id: str
|
|
312
358
|
absorbance_reader_lid: AbsorbanceReaderLidUpdate | NoChangeType = NO_CHANGE
|
|
313
359
|
absorbance_reader_data: AbsorbanceReaderDataUpdate | NoChangeType = NO_CHANGE
|
|
314
|
-
initialize_absorbance_reader_update:
|
|
315
|
-
|
|
316
|
-
)
|
|
360
|
+
initialize_absorbance_reader_update: (
|
|
361
|
+
AbsorbanceReaderInitializeUpdate | NoChangeType
|
|
362
|
+
) = NO_CHANGE
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
@dataclasses.dataclass
|
|
366
|
+
class FlexStackerPoolConstraint:
|
|
367
|
+
"""The labware definitions that are contained in the pool."""
|
|
368
|
+
|
|
369
|
+
max_pool_count: int
|
|
370
|
+
primary_definition: LabwareDefinition
|
|
371
|
+
lid_definition: LabwareDefinition | None
|
|
372
|
+
adapter_definition: LabwareDefinition | None
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
@dataclasses.dataclass
|
|
376
|
+
class FlexStackerStateUpdate:
|
|
377
|
+
"""An update to the Flex Stacker module state."""
|
|
378
|
+
|
|
379
|
+
module_id: str
|
|
380
|
+
pool_constraint: FlexStackerPoolConstraint | NoChangeType = NO_CHANGE
|
|
381
|
+
pool_count: int | NoChangeType = NO_CHANGE
|
|
382
|
+
|
|
383
|
+
@classmethod
|
|
384
|
+
def create_or_override(
|
|
385
|
+
cls,
|
|
386
|
+
maybe_inst: FlexStackerStateUpdate | NoChangeType,
|
|
387
|
+
module_id: str,
|
|
388
|
+
) -> FlexStackerStateUpdate:
|
|
389
|
+
"""Build or default a state update."""
|
|
390
|
+
if maybe_inst == NO_CHANGE:
|
|
391
|
+
return FlexStackerStateUpdate(module_id=module_id)
|
|
392
|
+
else:
|
|
393
|
+
return maybe_inst
|
|
317
394
|
|
|
318
395
|
|
|
319
396
|
@dataclasses.dataclass
|
|
@@ -362,8 +439,12 @@ class StateUpdate:
|
|
|
362
439
|
|
|
363
440
|
labware_location: LabwareLocationUpdate | NoChangeType = NO_CHANGE
|
|
364
441
|
|
|
442
|
+
batch_labware_location: BatchLabwareLocationUpdate | NoChangeType = NO_CHANGE
|
|
443
|
+
|
|
365
444
|
loaded_labware: LoadedLabwareUpdate | NoChangeType = NO_CHANGE
|
|
366
445
|
|
|
446
|
+
batch_loaded_labware: BatchLoadedLabwareUpdate | NoChangeType = NO_CHANGE
|
|
447
|
+
|
|
367
448
|
loaded_lid_stack: LoadedLidStackUpdate | NoChangeType = NO_CHANGE
|
|
368
449
|
|
|
369
450
|
labware_lid: LabwareLidUpdate | NoChangeType = NO_CHANGE
|
|
@@ -380,12 +461,16 @@ class StateUpdate:
|
|
|
380
461
|
NO_CHANGE
|
|
381
462
|
)
|
|
382
463
|
|
|
464
|
+
flex_stacker_state_update: FlexStackerStateUpdate | NoChangeType = NO_CHANGE
|
|
465
|
+
|
|
383
466
|
liquid_class_loaded: LiquidClassLoadedUpdate | NoChangeType = NO_CHANGE
|
|
384
467
|
|
|
385
468
|
files_added: FilesAddedUpdate | NoChangeType = NO_CHANGE
|
|
386
469
|
|
|
387
470
|
addressable_area_used: AddressableAreaUsedUpdate | NoChangeType = NO_CHANGE
|
|
388
471
|
|
|
472
|
+
ready_to_aspirate: PipetteAspirateReadyUpdate | NoChangeType = NO_CHANGE
|
|
473
|
+
|
|
389
474
|
def append(self, other: Self) -> Self:
|
|
390
475
|
"""Apply another `StateUpdate` "on top of" this one.
|
|
391
476
|
|
|
@@ -493,6 +578,19 @@ class StateUpdate:
|
|
|
493
578
|
)
|
|
494
579
|
return self
|
|
495
580
|
|
|
581
|
+
def set_batch_labware_location(
|
|
582
|
+
self: Self,
|
|
583
|
+
*,
|
|
584
|
+
new_locations_by_id: typing.Dict[str, LabwareLocation],
|
|
585
|
+
new_offset_ids_by_id: typing.Dict[str, str | None],
|
|
586
|
+
) -> Self:
|
|
587
|
+
"""Update the location of multiple labware objects."""
|
|
588
|
+
self.batch_labware_location = BatchLabwareLocationUpdate(
|
|
589
|
+
new_locations_by_id=new_locations_by_id,
|
|
590
|
+
new_offset_ids_by_id=new_offset_ids_by_id,
|
|
591
|
+
)
|
|
592
|
+
return self
|
|
593
|
+
|
|
496
594
|
def set_loaded_labware(
|
|
497
595
|
self: Self,
|
|
498
596
|
definition: LabwareDefinition,
|
|
@@ -511,14 +609,29 @@ class StateUpdate:
|
|
|
511
609
|
)
|
|
512
610
|
return self
|
|
513
611
|
|
|
612
|
+
def set_batch_loaded_labware(
|
|
613
|
+
self: Self,
|
|
614
|
+
definitions_by_id: typing.Dict[str, LabwareDefinition],
|
|
615
|
+
offset_ids_by_id: typing.Dict[str, str | None],
|
|
616
|
+
display_names_by_id: typing.Dict[str, str | None],
|
|
617
|
+
new_locations_by_id: typing.Dict[str, LabwareLocation],
|
|
618
|
+
) -> Self:
|
|
619
|
+
"""Add a set of new labwares to state. See `BatchLoadedLabwareUpdate`."""
|
|
620
|
+
self.batch_loaded_labware = BatchLoadedLabwareUpdate(
|
|
621
|
+
new_locations_by_id=new_locations_by_id,
|
|
622
|
+
offset_ids_by_id=offset_ids_by_id,
|
|
623
|
+
display_names_by_id=display_names_by_id,
|
|
624
|
+
definitions_by_id=definitions_by_id,
|
|
625
|
+
)
|
|
626
|
+
return self
|
|
627
|
+
|
|
514
628
|
def set_loaded_lid_stack(
|
|
515
629
|
self: Self,
|
|
516
630
|
stack_id: str,
|
|
517
631
|
stack_object_definition: LabwareDefinition,
|
|
518
632
|
stack_location: LabwareLocation,
|
|
519
|
-
labware_definition: LabwareDefinition,
|
|
520
|
-
labware_ids: typing.List[str],
|
|
521
633
|
locations: typing.Dict[str, OnLabwareLocation],
|
|
634
|
+
labware_definition: LabwareDefinition | None,
|
|
522
635
|
) -> Self:
|
|
523
636
|
"""Add a new lid stack to state. See `LoadedLidStackUpdate`."""
|
|
524
637
|
self.loaded_lid_stack = LoadedLidStackUpdate(
|
|
@@ -526,20 +639,19 @@ class StateUpdate:
|
|
|
526
639
|
stack_object_definition=stack_object_definition,
|
|
527
640
|
stack_location=stack_location,
|
|
528
641
|
definition=labware_definition,
|
|
529
|
-
labware_ids=labware_ids,
|
|
530
642
|
new_locations_by_id=locations,
|
|
531
643
|
)
|
|
532
644
|
return self
|
|
533
645
|
|
|
534
|
-
def
|
|
646
|
+
def set_lids(
|
|
535
647
|
self: Self,
|
|
536
|
-
|
|
537
|
-
|
|
648
|
+
parent_labware_ids: typing.List[str],
|
|
649
|
+
lid_ids: typing.List[str | None],
|
|
538
650
|
) -> Self:
|
|
539
651
|
"""Update the labware parent of a loaded or moved lid. See `LabwareLidUpdate`."""
|
|
540
652
|
self.labware_lid = LabwareLidUpdate(
|
|
541
|
-
|
|
542
|
-
|
|
653
|
+
parent_labware_ids=parent_labware_ids,
|
|
654
|
+
lid_ids=lid_ids,
|
|
543
655
|
)
|
|
544
656
|
return self
|
|
545
657
|
|
|
@@ -617,8 +729,8 @@ class StateUpdate:
|
|
|
617
729
|
labware_id: str,
|
|
618
730
|
well_name: str,
|
|
619
731
|
last_probed: datetime,
|
|
620
|
-
height:
|
|
621
|
-
volume:
|
|
732
|
+
height: LiquidTrackingType | ClearType,
|
|
733
|
+
volume: LiquidTrackingType | ClearType,
|
|
622
734
|
) -> Self:
|
|
623
735
|
"""Add a liquid height and volume to well state. See `ProbeLiquidUpdate`."""
|
|
624
736
|
self.liquid_probed = LiquidProbedUpdate(
|
|
@@ -665,10 +777,10 @@ class StateUpdate:
|
|
|
665
777
|
)
|
|
666
778
|
return self
|
|
667
779
|
|
|
668
|
-
def set_fluid_empty(self: Self, pipette_id: str) -> Self:
|
|
669
|
-
"""Update record
|
|
780
|
+
def set_fluid_empty(self: Self, pipette_id: str, clean_tip: bool = False) -> Self:
|
|
781
|
+
"""Update record of fluid held inside a pipette. See `PipetteEmptyFluidUpdate`."""
|
|
670
782
|
self.pipette_aspirated_fluid = PipetteEmptyFluidUpdate(
|
|
671
|
-
type="empty", pipette_id=pipette_id
|
|
783
|
+
type="empty", pipette_id=pipette_id, clean_tip=clean_tip
|
|
672
784
|
)
|
|
673
785
|
return self
|
|
674
786
|
|
|
@@ -717,3 +829,46 @@ class StateUpdate:
|
|
|
717
829
|
addressable_area_name=addressable_area_name
|
|
718
830
|
)
|
|
719
831
|
return self
|
|
832
|
+
|
|
833
|
+
def update_flex_stacker_labware_pool_definition(
|
|
834
|
+
self,
|
|
835
|
+
module_id: str,
|
|
836
|
+
max_count: int,
|
|
837
|
+
primary_definition: LabwareDefinition,
|
|
838
|
+
adapter_definition: LabwareDefinition | None,
|
|
839
|
+
lid_definition: LabwareDefinition | None,
|
|
840
|
+
) -> Self:
|
|
841
|
+
"""Constrain the labware pool to a specific definition."""
|
|
842
|
+
self.flex_stacker_state_update = dataclasses.replace(
|
|
843
|
+
FlexStackerStateUpdate.create_or_override(
|
|
844
|
+
self.flex_stacker_state_update, module_id
|
|
845
|
+
),
|
|
846
|
+
pool_constraint=FlexStackerPoolConstraint(
|
|
847
|
+
max_pool_count=max_count,
|
|
848
|
+
primary_definition=primary_definition,
|
|
849
|
+
lid_definition=lid_definition,
|
|
850
|
+
adapter_definition=adapter_definition,
|
|
851
|
+
),
|
|
852
|
+
)
|
|
853
|
+
return self
|
|
854
|
+
|
|
855
|
+
def update_flex_stacker_labware_pool_count(
|
|
856
|
+
self, module_id: str, count: int
|
|
857
|
+
) -> Self:
|
|
858
|
+
"""Set the labware pool to a specific count."""
|
|
859
|
+
self.flex_stacker_state_update = dataclasses.replace(
|
|
860
|
+
FlexStackerStateUpdate.create_or_override(
|
|
861
|
+
self.flex_stacker_state_update, module_id
|
|
862
|
+
),
|
|
863
|
+
pool_count=count,
|
|
864
|
+
)
|
|
865
|
+
return self
|
|
866
|
+
|
|
867
|
+
def set_pipette_ready_to_aspirate(
|
|
868
|
+
self, pipette_id: str, ready_to_aspirate: bool
|
|
869
|
+
) -> Self:
|
|
870
|
+
"""Set the ready to aspirate state for a pipette."""
|
|
871
|
+
self.ready_to_aspirate = PipetteAspirateReadyUpdate(
|
|
872
|
+
pipette_id=pipette_id, ready_to_aspirate=ready_to_aspirate
|
|
873
|
+
)
|
|
874
|
+
return self
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
"""Basic well data state and store."""
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import (
|
|
5
|
+
Dict,
|
|
6
|
+
List,
|
|
7
|
+
Union,
|
|
8
|
+
Iterator,
|
|
9
|
+
Optional,
|
|
10
|
+
Tuple,
|
|
11
|
+
overload,
|
|
12
|
+
)
|
|
13
|
+
from datetime import datetime
|
|
5
14
|
|
|
6
15
|
from opentrons.protocol_engine.types import (
|
|
7
16
|
ProbedHeightInfo,
|
|
@@ -10,6 +19,10 @@ from opentrons.protocol_engine.types import (
|
|
|
10
19
|
WellInfoSummary,
|
|
11
20
|
WellLiquidInfo,
|
|
12
21
|
)
|
|
22
|
+
from opentrons.protocol_engine.types.liquid_level_detection import (
|
|
23
|
+
SimulatedProbeResult,
|
|
24
|
+
LiquidTrackingType,
|
|
25
|
+
)
|
|
13
26
|
|
|
14
27
|
from . import update_types
|
|
15
28
|
from ._abstract_store import HasState, HandlesActions
|
|
@@ -103,7 +116,7 @@ class WellStore(HasState[WellState], HandlesActions):
|
|
|
103
116
|
del self._state.loaded_volumes[labware_id][well_name]
|
|
104
117
|
else:
|
|
105
118
|
prev_loaded_vol_info = self._state.loaded_volumes[labware_id][well_name]
|
|
106
|
-
assert prev_loaded_vol_info.volume is not None
|
|
119
|
+
assert prev_loaded_vol_info.volume is not None, "volume info not loaded"
|
|
107
120
|
self._state.loaded_volumes[labware_id][well_name] = LoadedVolumeInfo(
|
|
108
121
|
volume=prev_loaded_vol_info.volume + volume_added,
|
|
109
122
|
last_loaded=prev_loaded_vol_info.last_loaded,
|
|
@@ -119,13 +132,28 @@ class WellStore(HasState[WellState], HandlesActions):
|
|
|
119
132
|
labware_id in self._state.probed_volumes
|
|
120
133
|
and well_name in self._state.probed_volumes[labware_id]
|
|
121
134
|
):
|
|
135
|
+
prev_probed_vol_info = self._state.probed_volumes[labware_id][well_name]
|
|
122
136
|
if volume_added is update_types.CLEAR:
|
|
123
137
|
del self._state.probed_volumes[labware_id][well_name]
|
|
138
|
+
elif isinstance(
|
|
139
|
+
prev_probed_vol_info.volume,
|
|
140
|
+
SimulatedProbeResult,
|
|
141
|
+
):
|
|
142
|
+
prev_probed_vol_info.volume.simulate_probed_aspirate_dispense(
|
|
143
|
+
volume_added
|
|
144
|
+
)
|
|
145
|
+
self._state.probed_volumes[labware_id][well_name] = ProbedVolumeInfo(
|
|
146
|
+
volume=prev_probed_vol_info.volume,
|
|
147
|
+
last_probed=prev_probed_vol_info.last_probed,
|
|
148
|
+
operations_since_probe=prev_probed_vol_info.operations_since_probe
|
|
149
|
+
+ 1,
|
|
150
|
+
)
|
|
151
|
+
return
|
|
124
152
|
else:
|
|
125
|
-
prev_probed_vol_info = self._state.probed_volumes[labware_id][well_name]
|
|
126
153
|
if prev_probed_vol_info.volume is None:
|
|
127
154
|
new_vol_info: float | None = None
|
|
128
155
|
else:
|
|
156
|
+
assert isinstance(prev_probed_vol_info.volume, float)
|
|
129
157
|
new_vol_info = prev_probed_vol_info.volume + volume_added
|
|
130
158
|
self._state.probed_volumes[labware_id][well_name] = ProbedVolumeInfo(
|
|
131
159
|
volume=new_vol_info,
|
|
@@ -177,6 +205,22 @@ class WellView:
|
|
|
177
205
|
probed_volume=probed_volume_info,
|
|
178
206
|
)
|
|
179
207
|
|
|
208
|
+
def get_last_liquid_update(
|
|
209
|
+
self, labware_id: str, well_name: str
|
|
210
|
+
) -> Optional[datetime]:
|
|
211
|
+
"""Return the timestamp of the last load or probe done on the well."""
|
|
212
|
+
info = self.get_well_liquid_info(labware_id, well_name)
|
|
213
|
+
update_times: List[datetime] = []
|
|
214
|
+
if info.loaded_volume is not None and info.loaded_volume.volume is not None:
|
|
215
|
+
update_times.append(info.loaded_volume.last_loaded)
|
|
216
|
+
if info.probed_height is not None and info.probed_height.height is not None:
|
|
217
|
+
update_times.append(info.probed_height.last_probed)
|
|
218
|
+
if info.probed_volume is not None and info.probed_volume.volume is not None:
|
|
219
|
+
update_times.append(info.probed_volume.last_probed)
|
|
220
|
+
if len(update_times) > 0:
|
|
221
|
+
return max(update_times)
|
|
222
|
+
return None
|
|
223
|
+
|
|
180
224
|
def get_all(self) -> List[WellInfoSummary]:
|
|
181
225
|
"""Get all well liquid info summaries."""
|
|
182
226
|
|
|
@@ -223,22 +267,24 @@ def _volume_from_info(info: Optional[LoadedVolumeInfo]) -> Optional[float]:
|
|
|
223
267
|
|
|
224
268
|
def _volume_from_info(
|
|
225
269
|
info: Union[ProbedVolumeInfo, LoadedVolumeInfo, None],
|
|
226
|
-
) ->
|
|
270
|
+
) -> Union[LiquidTrackingType, None]:
|
|
227
271
|
if info is None:
|
|
228
272
|
return None
|
|
229
273
|
return info.volume
|
|
230
274
|
|
|
231
275
|
|
|
232
|
-
def _height_from_info(
|
|
276
|
+
def _height_from_info(
|
|
277
|
+
info: Optional[ProbedHeightInfo],
|
|
278
|
+
) -> Union[LiquidTrackingType, None]:
|
|
233
279
|
if info is None:
|
|
234
280
|
return None
|
|
235
281
|
return info.height
|
|
236
282
|
|
|
237
283
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
def _none_from_clear(inval: MaybeClear | update_types.ClearType) -> MaybeClear | None:
|
|
284
|
+
def _none_from_clear(
|
|
285
|
+
inval: LiquidTrackingType | update_types.ClearType,
|
|
286
|
+
) -> LiquidTrackingType | None:
|
|
242
287
|
if inval == update_types.CLEAR:
|
|
243
288
|
return None
|
|
289
|
+
assert isinstance(inval, (SimulatedProbeResult, float, int))
|
|
244
290
|
return inval
|