opentrons 8.3.1a1__py2.py3-none-any.whl → 8.4.0a1__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/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 +19 -3
- opentrons/legacy_commands/helpers.py +15 -0
- opentrons/legacy_commands/types.py +3 -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 +1233 -65
- 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/protocol.py +253 -11
- opentrons/protocol_api/core/engine/stringify.py +19 -8
- opentrons/protocol_api/core/engine/transfer_components_executor.py +853 -0
- opentrons/protocol_api/core/engine/well.py +60 -5
- opentrons/protocol_api/core/instrument.py +65 -19
- 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 +69 -21
- 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 +25 -1
- 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 +67 -21
- opentrons/protocol_api/core/module.py +43 -0
- opentrons/protocol_api/core/protocol.py +33 -0
- opentrons/protocol_api/core/well.py +21 -1
- opentrons/protocol_api/instrument_context.py +246 -123
- opentrons/protocol_api/labware.py +75 -11
- opentrons/protocol_api/module_contexts.py +140 -0
- opentrons/protocol_api/protocol_context.py +156 -16
- 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 +30 -0
- 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 +237 -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 +69 -0
- 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 +240 -0
- opentrons/protocol_engine/commands/drop_tip.py +23 -1
- opentrons/protocol_engine/commands/evotip_dispense.py +6 -7
- opentrons/protocol_engine/commands/evotip_seal_pipette.py +24 -29
- opentrons/protocol_engine/commands/evotip_unseal_pipette.py +1 -7
- 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 +288 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +31 -2
- opentrons/protocol_engine/commands/labware_handling_common.py +24 -0
- opentrons/protocol_engine/commands/liquid_probe.py +21 -12
- 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/pick_up_tip.py +5 -2
- opentrons/protocol_engine/commands/pipetting_common.py +154 -7
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +17 -2
- opentrons/protocol_engine/commands/reload_labware.py +6 -19
- 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/errors/__init__.py +8 -0
- opentrons/protocol_engine/errors/exceptions.py +50 -0
- opentrons/protocol_engine/execution/equipment.py +123 -106
- opentrons/protocol_engine/execution/labware_movement.py +8 -6
- opentrons/protocol_engine/execution/pipetting.py +233 -26
- opentrons/protocol_engine/execution/tip_handler.py +14 -5
- opentrons/protocol_engine/labware_offset_standardization.py +173 -0
- opentrons/protocol_engine/protocol_engine.py +22 -13
- opentrons/protocol_engine/resources/deck_configuration_provider.py +94 -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 +26 -10
- opentrons/protocol_engine/state/geometry.py +683 -100
- 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 +178 -52
- 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 +54 -8
- opentrons/protocol_engine/types/__init__.py +292 -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 +110 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +108 -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 +137 -0
- opentrons/protocol_engine/types/location.py +193 -0
- opentrons/protocol_engine/types/module.py +269 -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 +107 -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 +5 -6
- opentrons/protocols/models/__init__.py +0 -21
- opentrons/simulate.py +4 -2
- opentrons/types.py +15 -6
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/METADATA +4 -4
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/RECORD +188 -148
- 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.1a1.dist-info → opentrons-8.4.0a1.dist-info}/LICENSE +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/WHEEL +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/entry_points.txt +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/top_level.txt +0 -0
|
@@ -14,13 +14,15 @@ from typing import (
|
|
|
14
14
|
from math import isinf, isnan
|
|
15
15
|
from typing_extensions import TypeGuard
|
|
16
16
|
|
|
17
|
-
from opentrons_shared_data.labware.labware_definition import
|
|
18
|
-
|
|
17
|
+
from opentrons_shared_data.labware.labware_definition import (
|
|
18
|
+
LabwareDefinition,
|
|
19
|
+
LabwareRole,
|
|
20
|
+
)
|
|
21
|
+
from opentrons_shared_data.pipette.types import PipetteNameType, PIPETTE_API_NAMES_MAP
|
|
19
22
|
from opentrons_shared_data.robot.types import RobotType
|
|
20
23
|
|
|
21
24
|
from opentrons.protocols.api_support.types import APIVersion, ThermocyclerStep
|
|
22
25
|
from opentrons.protocols.api_support.util import APIVersionError
|
|
23
|
-
from opentrons.protocols.models import LabwareDefinition
|
|
24
26
|
from opentrons.protocols.advanced_control.transfers.common import TransferTipPolicyV2
|
|
25
27
|
from opentrons.types import (
|
|
26
28
|
Mount,
|
|
@@ -39,6 +41,7 @@ from opentrons.hardware_control.modules.types import (
|
|
|
39
41
|
HeaterShakerModuleModel,
|
|
40
42
|
MagneticBlockModel,
|
|
41
43
|
AbsorbanceReaderModel,
|
|
44
|
+
FlexStackerModuleModel,
|
|
42
45
|
)
|
|
43
46
|
|
|
44
47
|
from .disposal_locations import TrashBin, WasteChute
|
|
@@ -56,29 +59,8 @@ _STAGING_DECK_SLOT_VERSION_GATE = APIVersion(2, 16)
|
|
|
56
59
|
# The first APIVersion where Python protocols can load lids as stacks and treat them as attributes of a parent labware.
|
|
57
60
|
LID_STACK_VERSION_GATE = APIVersion(2, 23)
|
|
58
61
|
|
|
59
|
-
#
|
|
60
|
-
|
|
61
|
-
_PIPETTE_NAMES_MAP = {
|
|
62
|
-
"p10_single": PipetteNameType.P10_SINGLE,
|
|
63
|
-
"p10_multi": PipetteNameType.P10_MULTI,
|
|
64
|
-
"p20_single_gen2": PipetteNameType.P20_SINGLE_GEN2,
|
|
65
|
-
"p20_multi_gen2": PipetteNameType.P20_MULTI_GEN2,
|
|
66
|
-
"p50_single": PipetteNameType.P50_SINGLE,
|
|
67
|
-
"p50_multi": PipetteNameType.P50_MULTI,
|
|
68
|
-
"p300_single": PipetteNameType.P300_SINGLE,
|
|
69
|
-
"p300_multi": PipetteNameType.P300_MULTI,
|
|
70
|
-
"p300_single_gen2": PipetteNameType.P300_SINGLE_GEN2,
|
|
71
|
-
"p300_multi_gen2": PipetteNameType.P300_MULTI_GEN2,
|
|
72
|
-
"p1000_single": PipetteNameType.P1000_SINGLE,
|
|
73
|
-
"p1000_single_gen2": PipetteNameType.P1000_SINGLE_GEN2,
|
|
74
|
-
"flex_1channel_50": PipetteNameType.P50_SINGLE_FLEX,
|
|
75
|
-
"flex_8channel_50": PipetteNameType.P50_MULTI_FLEX,
|
|
76
|
-
"flex_1channel_1000": PipetteNameType.P1000_SINGLE_FLEX,
|
|
77
|
-
"flex_8channel_1000": PipetteNameType.P1000_MULTI_FLEX,
|
|
78
|
-
"flex_8channel_1000_em": PipetteNameType.P1000_MULTI_EM,
|
|
79
|
-
"flex_96channel_1000": PipetteNameType.P1000_96,
|
|
80
|
-
"flex_96channel_200": PipetteNameType.P200_96,
|
|
81
|
-
}
|
|
62
|
+
# The first APIVersion where Python protocols can use the Flex Stacker module.
|
|
63
|
+
FLEX_STACKER_VERSION_GATE = APIVersion(2, 23)
|
|
82
64
|
|
|
83
65
|
|
|
84
66
|
class InvalidPipetteMountError(ValueError):
|
|
@@ -192,7 +174,7 @@ def ensure_pipette_name(pipette_name: str) -> PipetteNameType:
|
|
|
192
174
|
pipette_name = ensure_lowercase_name(pipette_name)
|
|
193
175
|
|
|
194
176
|
try:
|
|
195
|
-
return
|
|
177
|
+
return PIPETTE_API_NAMES_MAP[pipette_name]
|
|
196
178
|
except KeyError:
|
|
197
179
|
raise ValueError(
|
|
198
180
|
f"Cannot resolve {pipette_name} to pipette, must be given valid pipette name."
|
|
@@ -411,6 +393,7 @@ _MODULE_MODELS: Dict[str, ModuleModel] = {
|
|
|
411
393
|
"heaterShakerModuleV1": HeaterShakerModuleModel.HEATER_SHAKER_V1,
|
|
412
394
|
"magneticBlockV1": MagneticBlockModel.MAGNETIC_BLOCK_V1,
|
|
413
395
|
"absorbanceReaderV1": AbsorbanceReaderModel.ABSORBANCE_READER_V1,
|
|
396
|
+
"flexStackerModuleV1": FlexStackerModuleModel.FLEX_STACKER_V1,
|
|
414
397
|
}
|
|
415
398
|
|
|
416
399
|
|
|
@@ -644,6 +627,16 @@ def ensure_positive_float(value: Union[int, float]) -> float:
|
|
|
644
627
|
return float_value
|
|
645
628
|
|
|
646
629
|
|
|
630
|
+
def ensure_greater_than_zero_float(value: Union[int, float]) -> float:
|
|
631
|
+
"""Ensure value is a positive and real float value."""
|
|
632
|
+
float_value = ensure_float(value)
|
|
633
|
+
if isnan(float_value) or isinf(float_value):
|
|
634
|
+
raise ValueError("Value must be a defined, non-infinite number.")
|
|
635
|
+
if float_value <= 0:
|
|
636
|
+
raise ValueError("Value must be a positive float greater than 0.")
|
|
637
|
+
return float_value
|
|
638
|
+
|
|
639
|
+
|
|
647
640
|
def ensure_positive_int(value: int) -> int:
|
|
648
641
|
"""Ensure value is a positive integer."""
|
|
649
642
|
if not isinstance(value, int):
|
|
@@ -711,20 +704,18 @@ def ensure_valid_flat_wells_list_for_transfer_v2(
|
|
|
711
704
|
)
|
|
712
705
|
|
|
713
706
|
|
|
714
|
-
def
|
|
715
|
-
|
|
716
|
-
) -> Union[Location,
|
|
717
|
-
"""Ensure that the
|
|
707
|
+
def ensure_valid_trash_location_for_transfer_v2(
|
|
708
|
+
trash_location: Union[Location, Well, TrashBin, WasteChute]
|
|
709
|
+
) -> Union[Location, TrashBin, WasteChute]:
|
|
710
|
+
"""Ensure that the trash location is valid for v2 transfer."""
|
|
718
711
|
from .labware import Well
|
|
719
712
|
|
|
720
|
-
if (
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
):
|
|
725
|
-
|
|
726
|
-
elif isinstance(tip_drop_location, Location):
|
|
727
|
-
_, maybe_well = tip_drop_location.labware.get_parent_labware_and_well()
|
|
713
|
+
if isinstance(trash_location, TrashBin) or isinstance(trash_location, WasteChute):
|
|
714
|
+
return trash_location
|
|
715
|
+
elif isinstance(trash_location, Well):
|
|
716
|
+
return trash_location.top()
|
|
717
|
+
elif isinstance(trash_location, Location):
|
|
718
|
+
_, maybe_well = trash_location.labware.get_parent_labware_and_well()
|
|
728
719
|
|
|
729
720
|
if maybe_well is None:
|
|
730
721
|
raise TypeError(
|
|
@@ -734,11 +725,30 @@ def ensure_valid_tip_drop_location_for_transfer_v2(
|
|
|
734
725
|
" since that is where a tip is dropped."
|
|
735
726
|
" However, the given location doesn't refer to any well."
|
|
736
727
|
)
|
|
737
|
-
return
|
|
728
|
+
return trash_location
|
|
738
729
|
else:
|
|
739
730
|
raise TypeError(
|
|
740
731
|
f"If specified, location should be an instance of"
|
|
741
732
|
f" `types.Location` (e.g. the return value from `Well.top()`)"
|
|
742
733
|
f" or `Well` (e.g. `reservoir.wells()[0]`) or an instance of `TrashBin` or `WasteChute`."
|
|
743
|
-
f" However, it is '{
|
|
734
|
+
f" However, it is '{trash_location}'."
|
|
744
735
|
)
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
def convert_flex_stacker_load_slot(slot_name: StagingSlotName) -> DeckSlotName:
|
|
739
|
+
"""
|
|
740
|
+
Ensure a Flex Stacker load location to a deck slot location.
|
|
741
|
+
|
|
742
|
+
Args:
|
|
743
|
+
slot_name: The input staging slot location.
|
|
744
|
+
|
|
745
|
+
Returns:
|
|
746
|
+
A `DeckSlotName` on the deck.
|
|
747
|
+
"""
|
|
748
|
+
_map = {
|
|
749
|
+
StagingSlotName.SLOT_A4: DeckSlotName.SLOT_A3,
|
|
750
|
+
StagingSlotName.SLOT_B4: DeckSlotName.SLOT_B3,
|
|
751
|
+
StagingSlotName.SLOT_C4: DeckSlotName.SLOT_C3,
|
|
752
|
+
StagingSlotName.SLOT_D4: DeckSlotName.SLOT_D3,
|
|
753
|
+
}
|
|
754
|
+
return _map[slot_name]
|
|
@@ -26,21 +26,30 @@ from .plugins import AbstractPlugin
|
|
|
26
26
|
|
|
27
27
|
from .types import (
|
|
28
28
|
LabwareOffset,
|
|
29
|
+
LegacyLabwareOffsetCreate,
|
|
29
30
|
LabwareOffsetCreate,
|
|
30
31
|
LabwareOffsetVector,
|
|
31
|
-
|
|
32
|
+
LegacyLabwareOffsetLocation,
|
|
33
|
+
LabwareOffsetLocationSequence,
|
|
34
|
+
OnLabwareOffsetLocationSequenceComponent,
|
|
35
|
+
OnModuleOffsetLocationSequenceComponent,
|
|
36
|
+
OnAddressableAreaOffsetLocationSequenceComponent,
|
|
37
|
+
LabwareOffsetLocationSequenceComponents,
|
|
32
38
|
LabwareMovementStrategy,
|
|
33
39
|
AddressableOffsetVector,
|
|
34
40
|
DeckPoint,
|
|
35
41
|
DeckType,
|
|
36
42
|
DeckSlotLocation,
|
|
43
|
+
InStackerHopperLocation,
|
|
37
44
|
ModuleLocation,
|
|
38
45
|
OnLabwareLocation,
|
|
39
46
|
AddressableAreaLocation,
|
|
40
47
|
OFF_DECK_LOCATION,
|
|
48
|
+
SYSTEM_LOCATION,
|
|
41
49
|
Dimensions,
|
|
42
50
|
EngineStatus,
|
|
43
51
|
LabwareLocation,
|
|
52
|
+
LoadableLabwareLocation,
|
|
44
53
|
NonStackedLocation,
|
|
45
54
|
LoadedLabware,
|
|
46
55
|
LoadedModule,
|
|
@@ -94,8 +103,15 @@ __all__ = [
|
|
|
94
103
|
# public value interfaces and models
|
|
95
104
|
"LabwareOffset",
|
|
96
105
|
"LabwareOffsetCreate",
|
|
106
|
+
"LegacyLabwareOffsetCreate",
|
|
107
|
+
"LabwareOffsetLocationSequence",
|
|
97
108
|
"LabwareOffsetVector",
|
|
98
|
-
"
|
|
109
|
+
"OnLabwareOffsetLocationSequenceComponent",
|
|
110
|
+
"OnModuleOffsetLocationSequenceComponent",
|
|
111
|
+
"OnAddressableAreaOffsetLocationSequenceComponent",
|
|
112
|
+
"LabwareOffsetLocationSequenceComponents",
|
|
113
|
+
"LegacyLabwareOffsetCreate",
|
|
114
|
+
"LegacyLabwareOffsetLocation",
|
|
99
115
|
"LabwareMovementStrategy",
|
|
100
116
|
"AddressableOffsetVector",
|
|
101
117
|
"DeckSlotLocation",
|
|
@@ -104,10 +120,13 @@ __all__ = [
|
|
|
104
120
|
"ModuleLocation",
|
|
105
121
|
"OnLabwareLocation",
|
|
106
122
|
"AddressableAreaLocation",
|
|
123
|
+
"InStackerHopperLocation",
|
|
107
124
|
"OFF_DECK_LOCATION",
|
|
125
|
+
"SYSTEM_LOCATION",
|
|
108
126
|
"Dimensions",
|
|
109
127
|
"EngineStatus",
|
|
110
128
|
"LabwareLocation",
|
|
129
|
+
"LoadableLabwareLocation",
|
|
111
130
|
"NonStackedLocation",
|
|
112
131
|
"LoadedLabware",
|
|
113
132
|
"LoadedModule",
|
|
@@ -8,12 +8,12 @@ from datetime import datetime
|
|
|
8
8
|
from enum import Enum
|
|
9
9
|
from typing import List, Optional, Union
|
|
10
10
|
|
|
11
|
-
from
|
|
11
|
+
from opentrons_shared_data.errors import EnumeratedError
|
|
12
|
+
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
13
|
+
|
|
12
14
|
from opentrons.hardware_control.types import DoorState
|
|
13
15
|
from opentrons.hardware_control.modules import LiveData
|
|
14
16
|
|
|
15
|
-
from opentrons_shared_data.errors import EnumeratedError
|
|
16
|
-
|
|
17
17
|
from ..commands import (
|
|
18
18
|
Command,
|
|
19
19
|
CommandCreate,
|
|
@@ -23,7 +23,7 @@ from ..error_recovery_policy import ErrorRecoveryPolicy, ErrorRecoveryType
|
|
|
23
23
|
from ..notes.notes import CommandNote
|
|
24
24
|
from ..state.update_types import StateUpdate
|
|
25
25
|
from ..types import (
|
|
26
|
-
|
|
26
|
+
LabwareOffsetCreateInternal,
|
|
27
27
|
ModuleDefinition,
|
|
28
28
|
Liquid,
|
|
29
29
|
DeckConfigurationType,
|
|
@@ -206,7 +206,7 @@ class AddLabwareOffsetAction:
|
|
|
206
206
|
|
|
207
207
|
labware_offset_id: str
|
|
208
208
|
created_at: datetime
|
|
209
|
-
request:
|
|
209
|
+
request: LabwareOffsetCreateInternal
|
|
210
210
|
|
|
211
211
|
|
|
212
212
|
@dataclasses.dataclass(frozen=True)
|
|
@@ -107,6 +107,12 @@ class SyncClient:
|
|
|
107
107
|
) -> commands.LoadLiquidClassResult:
|
|
108
108
|
pass
|
|
109
109
|
|
|
110
|
+
@overload
|
|
111
|
+
def execute_command_without_recovery(
|
|
112
|
+
self, params: commands.GetNextTipParams
|
|
113
|
+
) -> commands.GetNextTipResult:
|
|
114
|
+
pass
|
|
115
|
+
|
|
110
116
|
def execute_command_without_recovery(
|
|
111
117
|
self, params: commands.CommandParams
|
|
112
118
|
) -> commands.CommandResult:
|
|
@@ -14,6 +14,7 @@ and/or schema generation.
|
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
from . import absorbance_reader
|
|
17
|
+
from . import flex_stacker
|
|
17
18
|
from . import heater_shaker
|
|
18
19
|
from . import magnetic_module
|
|
19
20
|
from . import temperature_module
|
|
@@ -60,6 +61,14 @@ from .aspirate import (
|
|
|
60
61
|
AspirateCommandType,
|
|
61
62
|
)
|
|
62
63
|
|
|
64
|
+
from .aspirate_while_tracking import (
|
|
65
|
+
AspirateWhileTracking,
|
|
66
|
+
AspirateWhileTrackingParams,
|
|
67
|
+
AspirateWhileTrackingCreate,
|
|
68
|
+
AspirateWhileTrackingResult,
|
|
69
|
+
AspirateWhileTrackingCommandType,
|
|
70
|
+
)
|
|
71
|
+
|
|
63
72
|
from .aspirate_in_place import (
|
|
64
73
|
AspirateInPlace,
|
|
65
74
|
AspirateInPlaceParams,
|
|
@@ -92,6 +101,14 @@ from .dispense import (
|
|
|
92
101
|
DispenseCommandType,
|
|
93
102
|
)
|
|
94
103
|
|
|
104
|
+
from .dispense_while_tracking import (
|
|
105
|
+
DispenseWhileTracking,
|
|
106
|
+
DispenseWhileTrackingParams,
|
|
107
|
+
DispenseWhileTrackingCreate,
|
|
108
|
+
DispenseWhileTrackingResult,
|
|
109
|
+
DispenseWhileTrackingCommandType,
|
|
110
|
+
)
|
|
111
|
+
|
|
95
112
|
from .dispense_in_place import (
|
|
96
113
|
DispenseInPlace,
|
|
97
114
|
DispenseInPlaceParams,
|
|
@@ -435,6 +452,12 @@ __all__ = [
|
|
|
435
452
|
"AspirateParams",
|
|
436
453
|
"AspirateResult",
|
|
437
454
|
"AspirateCommandType",
|
|
455
|
+
# aspirate while tracking command models
|
|
456
|
+
"AspirateWhileTracking",
|
|
457
|
+
"AspirateWhileTrackingCreate",
|
|
458
|
+
"AspirateWhileTrackingParams",
|
|
459
|
+
"AspirateWhileTrackingResult",
|
|
460
|
+
"AspirateWhileTrackingCommandType",
|
|
438
461
|
# aspirate in place command models
|
|
439
462
|
"AspirateInPlace",
|
|
440
463
|
"AspirateInPlaceCreate",
|
|
@@ -459,6 +482,12 @@ __all__ = [
|
|
|
459
482
|
"DispenseParams",
|
|
460
483
|
"DispenseResult",
|
|
461
484
|
"DispenseCommandType",
|
|
485
|
+
# dispense while tracking command models
|
|
486
|
+
"DispenseWhileTracking",
|
|
487
|
+
"DispenseWhileTrackingCreate",
|
|
488
|
+
"DispenseWhileTrackingParams",
|
|
489
|
+
"DispenseWhileTrackingResult",
|
|
490
|
+
"DispenseWhileTrackingCommandType",
|
|
462
491
|
# dispense in place command models
|
|
463
492
|
"DispenseInPlace",
|
|
464
493
|
"DispenseInPlaceCreate",
|
|
@@ -636,6 +665,7 @@ __all__ = [
|
|
|
636
665
|
# hardware control command models
|
|
637
666
|
# hardware module command bundles
|
|
638
667
|
"absorbance_reader",
|
|
668
|
+
"flex_stacker",
|
|
639
669
|
"heater_shaker",
|
|
640
670
|
"magnetic_module",
|
|
641
671
|
"temperature_module",
|
|
@@ -14,6 +14,7 @@ from .pipetting_common import (
|
|
|
14
14
|
FlowRateMixin,
|
|
15
15
|
BaseLiquidHandlingResult,
|
|
16
16
|
OverpressureError,
|
|
17
|
+
DEFAULT_CORRECTION_VOLUME,
|
|
17
18
|
)
|
|
18
19
|
from .command import (
|
|
19
20
|
AbstractCommandImpl,
|
|
@@ -84,9 +85,8 @@ class AirGapInPlaceImplementation(
|
|
|
84
85
|
PipetteNotReadyToAirGapError: pipette plunger is not ready.
|
|
85
86
|
"""
|
|
86
87
|
ready_to_aspirate = self._pipetting.get_is_ready_to_aspirate(
|
|
87
|
-
pipette_id=params.pipetteId
|
|
88
|
+
pipette_id=params.pipetteId
|
|
88
89
|
)
|
|
89
|
-
|
|
90
90
|
if not ready_to_aspirate:
|
|
91
91
|
raise PipetteNotReadyToAspirateError(
|
|
92
92
|
"Pipette cannot air gap in place because of a previous blow out."
|
|
@@ -103,6 +103,7 @@ class AirGapInPlaceImplementation(
|
|
|
103
103
|
volume=params.volume,
|
|
104
104
|
flow_rate=params.flowRate,
|
|
105
105
|
command_note_adder=self._command_note_adder,
|
|
106
|
+
correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME,
|
|
106
107
|
)
|
|
107
108
|
except PipetteOverpressureError as e:
|
|
108
109
|
return DefinedErrorData(
|
|
@@ -12,6 +12,7 @@ from .pipetting_common import (
|
|
|
12
12
|
BaseLiquidHandlingResult,
|
|
13
13
|
aspirate_in_place,
|
|
14
14
|
prepare_for_aspirate,
|
|
15
|
+
DEFAULT_CORRECTION_VOLUME,
|
|
15
16
|
)
|
|
16
17
|
from .movement_common import (
|
|
17
18
|
LiquidHandlingWellLocationMixin,
|
|
@@ -47,7 +48,10 @@ AspirateCommandType = Literal["aspirate"]
|
|
|
47
48
|
|
|
48
49
|
|
|
49
50
|
class AspirateParams(
|
|
50
|
-
PipetteIdMixin,
|
|
51
|
+
PipetteIdMixin,
|
|
52
|
+
AspirateVolumeMixin,
|
|
53
|
+
FlowRateMixin,
|
|
54
|
+
LiquidHandlingWellLocationMixin,
|
|
51
55
|
):
|
|
52
56
|
"""Parameters required to aspirate from a specific well."""
|
|
53
57
|
|
|
@@ -148,7 +152,6 @@ class AspirateImplementation(AbstractCommandImpl[AspirateParams, _ExecuteReturn]
|
|
|
148
152
|
labware_id=labware_id,
|
|
149
153
|
well_name=well_name,
|
|
150
154
|
)
|
|
151
|
-
|
|
152
155
|
move_result = await move_to_well(
|
|
153
156
|
movement=self._movement,
|
|
154
157
|
model_utils=self._model_utils,
|
|
@@ -179,6 +182,7 @@ class AspirateImplementation(AbstractCommandImpl[AspirateParams, _ExecuteReturn]
|
|
|
179
182
|
command_note_adder=self._command_note_adder,
|
|
180
183
|
pipetting=self._pipetting,
|
|
181
184
|
model_utils=self._model_utils,
|
|
185
|
+
correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME,
|
|
182
186
|
)
|
|
183
187
|
state_update.append(aspirate_result.state_update)
|
|
184
188
|
if isinstance(aspirate_result, DefinedErrorData):
|
|
@@ -13,6 +13,7 @@ from .pipetting_common import (
|
|
|
13
13
|
BaseLiquidHandlingResult,
|
|
14
14
|
OverpressureError,
|
|
15
15
|
aspirate_in_place,
|
|
16
|
+
DEFAULT_CORRECTION_VOLUME,
|
|
16
17
|
)
|
|
17
18
|
from .command import (
|
|
18
19
|
AbstractCommandImpl,
|
|
@@ -82,7 +83,7 @@ class AspirateInPlaceImplementation(
|
|
|
82
83
|
PipetteNotReadyToAspirateError: pipette plunger is not ready.
|
|
83
84
|
"""
|
|
84
85
|
ready_to_aspirate = self._pipetting.get_is_ready_to_aspirate(
|
|
85
|
-
pipette_id=params.pipetteId
|
|
86
|
+
pipette_id=params.pipetteId
|
|
86
87
|
)
|
|
87
88
|
if not ready_to_aspirate:
|
|
88
89
|
raise PipetteNotReadyToAspirateError(
|
|
@@ -108,6 +109,7 @@ class AspirateInPlaceImplementation(
|
|
|
108
109
|
command_note_adder=self._command_note_adder,
|
|
109
110
|
pipetting=self._pipetting,
|
|
110
111
|
model_utils=self._model_utils,
|
|
112
|
+
correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME,
|
|
111
113
|
)
|
|
112
114
|
if isinstance(result, DefinedErrorData):
|
|
113
115
|
if (
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"""Aspirate command request, result, and implementation models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
5
|
+
from typing_extensions import Literal
|
|
6
|
+
|
|
7
|
+
from .pipetting_common import (
|
|
8
|
+
OverpressureError,
|
|
9
|
+
PipetteIdMixin,
|
|
10
|
+
AspirateVolumeMixin,
|
|
11
|
+
FlowRateMixin,
|
|
12
|
+
BaseLiquidHandlingResult,
|
|
13
|
+
aspirate_while_tracking,
|
|
14
|
+
)
|
|
15
|
+
from .movement_common import (
|
|
16
|
+
LiquidHandlingWellLocationMixin,
|
|
17
|
+
DestinationPositionResult,
|
|
18
|
+
StallOrCollisionError,
|
|
19
|
+
move_to_well,
|
|
20
|
+
)
|
|
21
|
+
from .command import (
|
|
22
|
+
AbstractCommandImpl,
|
|
23
|
+
BaseCommand,
|
|
24
|
+
BaseCommandCreate,
|
|
25
|
+
DefinedErrorData,
|
|
26
|
+
SuccessData,
|
|
27
|
+
)
|
|
28
|
+
from ..state.update_types import StateUpdate
|
|
29
|
+
from ..errors.exceptions import PipetteNotReadyToAspirateError
|
|
30
|
+
from opentrons.hardware_control import HardwareControlAPI
|
|
31
|
+
from ..state.update_types import CLEAR
|
|
32
|
+
from ..types import CurrentWell, DeckPoint
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from ..execution import PipettingHandler, GantryMover, MovementHandler
|
|
36
|
+
from ..resources import ModelUtils
|
|
37
|
+
from ..state.state import StateView
|
|
38
|
+
from ..notes import CommandNoteAdder
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
AspirateWhileTrackingCommandType = Literal["aspirateWhileTracking"]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class AspirateWhileTrackingParams(
|
|
45
|
+
PipetteIdMixin,
|
|
46
|
+
AspirateVolumeMixin,
|
|
47
|
+
FlowRateMixin,
|
|
48
|
+
LiquidHandlingWellLocationMixin,
|
|
49
|
+
):
|
|
50
|
+
"""Parameters required to aspirate from a specific well."""
|
|
51
|
+
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class AspirateWhileTrackingResult(BaseLiquidHandlingResult, DestinationPositionResult):
|
|
56
|
+
"""Result data from execution of an Aspirate command."""
|
|
57
|
+
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
_ExecuteReturn = Union[
|
|
62
|
+
SuccessData[AspirateWhileTrackingResult],
|
|
63
|
+
DefinedErrorData[OverpressureError] | DefinedErrorData[StallOrCollisionError],
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class AspirateWhileTrackingImplementation(
|
|
68
|
+
AbstractCommandImpl[AspirateWhileTrackingParams, _ExecuteReturn]
|
|
69
|
+
):
|
|
70
|
+
"""AspirateWhileTracking command implementation."""
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
pipetting: PipettingHandler,
|
|
75
|
+
state_view: StateView,
|
|
76
|
+
hardware_api: HardwareControlAPI,
|
|
77
|
+
command_note_adder: CommandNoteAdder,
|
|
78
|
+
model_utils: ModelUtils,
|
|
79
|
+
gantry_mover: GantryMover,
|
|
80
|
+
movement: MovementHandler,
|
|
81
|
+
**kwargs: object,
|
|
82
|
+
) -> None:
|
|
83
|
+
self._pipetting = pipetting
|
|
84
|
+
self._state_view = state_view
|
|
85
|
+
self._hardware_api = hardware_api
|
|
86
|
+
self._command_note_adder = command_note_adder
|
|
87
|
+
self._model_utils = model_utils
|
|
88
|
+
self._gantry_mover = gantry_mover
|
|
89
|
+
self._movement = movement
|
|
90
|
+
|
|
91
|
+
async def execute(self, params: AspirateWhileTrackingParams) -> _ExecuteReturn:
|
|
92
|
+
"""Move to and aspirate from the requested well.
|
|
93
|
+
|
|
94
|
+
Raises:
|
|
95
|
+
TipNotAttachedError: if no tip is attached to the pipette.
|
|
96
|
+
PipetteNotReadyToAspirateError: pipette plunger is not ready.
|
|
97
|
+
"""
|
|
98
|
+
ready_to_aspirate = self._state_view.pipettes.get_ready_to_aspirate(
|
|
99
|
+
pipette_id=params.pipetteId
|
|
100
|
+
)
|
|
101
|
+
if not ready_to_aspirate:
|
|
102
|
+
raise PipetteNotReadyToAspirateError(
|
|
103
|
+
"Pipette cannot aspirate while tracking because of a previous blow out."
|
|
104
|
+
" The first aspirate following a blow-out must be from a specific well"
|
|
105
|
+
" so the plunger can be reset in a known safe position."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
current_position = await self._gantry_mover.get_position(params.pipetteId)
|
|
109
|
+
current_location = self._state_view.pipettes.get_current_location()
|
|
110
|
+
|
|
111
|
+
state_update = StateUpdate()
|
|
112
|
+
current_well = CurrentWell(
|
|
113
|
+
pipette_id=params.pipetteId,
|
|
114
|
+
labware_id=params.labwareId,
|
|
115
|
+
well_name=params.wellName,
|
|
116
|
+
)
|
|
117
|
+
move_result = await move_to_well(
|
|
118
|
+
movement=self._movement,
|
|
119
|
+
model_utils=self._model_utils,
|
|
120
|
+
pipette_id=params.pipetteId,
|
|
121
|
+
labware_id=params.labwareId,
|
|
122
|
+
well_name=params.wellName,
|
|
123
|
+
well_location=params.wellLocation,
|
|
124
|
+
current_well=current_well,
|
|
125
|
+
operation_volume=-params.volume,
|
|
126
|
+
)
|
|
127
|
+
state_update.append(move_result.state_update)
|
|
128
|
+
if isinstance(move_result, DefinedErrorData):
|
|
129
|
+
return DefinedErrorData(
|
|
130
|
+
public=move_result.public, state_update=state_update
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
aspirate_result = await aspirate_while_tracking(
|
|
134
|
+
pipette_id=params.pipetteId,
|
|
135
|
+
labware_id=params.labwareId,
|
|
136
|
+
well_name=params.wellName,
|
|
137
|
+
volume=params.volume,
|
|
138
|
+
flow_rate=params.flowRate,
|
|
139
|
+
location_if_error={
|
|
140
|
+
"retryLocation": (
|
|
141
|
+
current_position.x,
|
|
142
|
+
current_position.y,
|
|
143
|
+
current_position.z,
|
|
144
|
+
)
|
|
145
|
+
},
|
|
146
|
+
command_note_adder=self._command_note_adder,
|
|
147
|
+
pipetting=self._pipetting,
|
|
148
|
+
model_utils=self._model_utils,
|
|
149
|
+
)
|
|
150
|
+
position_after_aspirate = await self._gantry_mover.get_position(
|
|
151
|
+
params.pipetteId
|
|
152
|
+
)
|
|
153
|
+
result_deck_point = DeckPoint.model_construct(
|
|
154
|
+
x=position_after_aspirate.x,
|
|
155
|
+
y=position_after_aspirate.y,
|
|
156
|
+
z=position_after_aspirate.z,
|
|
157
|
+
)
|
|
158
|
+
if isinstance(aspirate_result, DefinedErrorData):
|
|
159
|
+
if (
|
|
160
|
+
isinstance(current_location, CurrentWell)
|
|
161
|
+
and current_location.pipette_id == params.pipetteId
|
|
162
|
+
):
|
|
163
|
+
return DefinedErrorData(
|
|
164
|
+
public=aspirate_result.public,
|
|
165
|
+
state_update=aspirate_result.state_update.set_liquid_operated(
|
|
166
|
+
labware_id=current_location.labware_id,
|
|
167
|
+
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
168
|
+
current_location.labware_id,
|
|
169
|
+
current_location.well_name,
|
|
170
|
+
params.pipetteId,
|
|
171
|
+
),
|
|
172
|
+
volume_added=CLEAR,
|
|
173
|
+
),
|
|
174
|
+
state_update_if_false_positive=aspirate_result.state_update_if_false_positive,
|
|
175
|
+
)
|
|
176
|
+
else:
|
|
177
|
+
return aspirate_result
|
|
178
|
+
else:
|
|
179
|
+
if (
|
|
180
|
+
isinstance(current_location, CurrentWell)
|
|
181
|
+
and current_location.pipette_id == params.pipetteId
|
|
182
|
+
):
|
|
183
|
+
return SuccessData(
|
|
184
|
+
public=AspirateWhileTrackingResult(
|
|
185
|
+
volume=aspirate_result.public.volume,
|
|
186
|
+
position=result_deck_point,
|
|
187
|
+
),
|
|
188
|
+
state_update=aspirate_result.state_update.set_liquid_operated(
|
|
189
|
+
labware_id=current_location.labware_id,
|
|
190
|
+
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
191
|
+
current_location.labware_id,
|
|
192
|
+
current_location.well_name,
|
|
193
|
+
params.pipetteId,
|
|
194
|
+
),
|
|
195
|
+
volume_added=-aspirate_result.public.volume
|
|
196
|
+
* self._state_view.geometry.get_nozzles_per_well(
|
|
197
|
+
current_location.labware_id,
|
|
198
|
+
current_location.well_name,
|
|
199
|
+
params.pipetteId,
|
|
200
|
+
),
|
|
201
|
+
),
|
|
202
|
+
)
|
|
203
|
+
else:
|
|
204
|
+
return SuccessData(
|
|
205
|
+
public=AspirateWhileTrackingResult(
|
|
206
|
+
volume=aspirate_result.public.volume,
|
|
207
|
+
position=result_deck_point,
|
|
208
|
+
),
|
|
209
|
+
state_update=aspirate_result.state_update,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class AspirateWhileTracking(
|
|
214
|
+
BaseCommand[
|
|
215
|
+
AspirateWhileTrackingParams,
|
|
216
|
+
AspirateWhileTrackingResult,
|
|
217
|
+
OverpressureError | StallOrCollisionError,
|
|
218
|
+
]
|
|
219
|
+
):
|
|
220
|
+
"""AspirateWhileTracking command model."""
|
|
221
|
+
|
|
222
|
+
commandType: AspirateWhileTrackingCommandType = "aspirateWhileTracking"
|
|
223
|
+
params: AspirateWhileTrackingParams
|
|
224
|
+
result: Optional[AspirateWhileTrackingResult] = None
|
|
225
|
+
|
|
226
|
+
_ImplementationCls: Type[
|
|
227
|
+
AspirateWhileTrackingImplementation
|
|
228
|
+
] = AspirateWhileTrackingImplementation
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class AspirateWhileTrackingCreate(BaseCommandCreate[AspirateWhileTrackingParams]):
|
|
232
|
+
"""Create aspirateWhileTracking command request model."""
|
|
233
|
+
|
|
234
|
+
commandType: AspirateWhileTrackingCommandType = "aspirateWhileTracking"
|
|
235
|
+
params: AspirateWhileTrackingParams
|
|
236
|
+
|
|
237
|
+
_CommandCls: Type[AspirateWhileTracking] = AspirateWhileTracking
|
|
@@ -115,6 +115,8 @@ class BlowOutImplementation(AbstractCommandImpl[BlowOutParams, _ExecuteReturn]):
|
|
|
115
115
|
public=BlowOutResult(position=move_result.public.position),
|
|
116
116
|
state_update=StateUpdate.reduce(
|
|
117
117
|
move_result.state_update, blow_out_result.state_update
|
|
118
|
+
).set_pipette_ready_to_aspirate(
|
|
119
|
+
pipette_id=params.pipetteId, ready_to_aspirate=False
|
|
118
120
|
),
|
|
119
121
|
)
|
|
120
122
|
|