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
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Protocol engine types to deal with locating things on the deck."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from typing import Literal, Union, TypeGuard
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
|
+
|
|
9
|
+
from opentrons.types import DeckSlotName, StagingSlotName
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DeckSlotLocation(BaseModel):
|
|
13
|
+
"""The location of something placed in a single deck slot."""
|
|
14
|
+
|
|
15
|
+
slotName: DeckSlotName = Field(
|
|
16
|
+
...,
|
|
17
|
+
description=(
|
|
18
|
+
# This description should be kept in sync with LegacyLabwareOffsetLocation.slotName.
|
|
19
|
+
"A slot on the robot's deck."
|
|
20
|
+
"\n\n"
|
|
21
|
+
'The plain numbers like `"5"` are for the OT-2,'
|
|
22
|
+
' and the coordinates like `"C2"` are for the Flex.'
|
|
23
|
+
"\n\n"
|
|
24
|
+
"When you provide one of these values, you can use either style."
|
|
25
|
+
" It will automatically be converted to match the robot."
|
|
26
|
+
"\n\n"
|
|
27
|
+
"When one of these values is returned, it will always match the robot."
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class StagingSlotLocation(BaseModel):
|
|
33
|
+
"""The location of something placed in a single staging slot."""
|
|
34
|
+
|
|
35
|
+
slotName: StagingSlotName = Field(
|
|
36
|
+
...,
|
|
37
|
+
description=(
|
|
38
|
+
# This description should be kept in sync with LegacyLabwareOffsetLocation.slotName.
|
|
39
|
+
"A slot on the robot's staging area."
|
|
40
|
+
"\n\n"
|
|
41
|
+
"These apply only to the Flex. The OT-2 has no staging slots."
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class AddressableAreaLocation(BaseModel):
|
|
47
|
+
"""The location of something place in an addressable area. This is a superset of deck slots."""
|
|
48
|
+
|
|
49
|
+
addressableAreaName: str = Field(
|
|
50
|
+
...,
|
|
51
|
+
description=(
|
|
52
|
+
"The name of the addressable area that you want to use."
|
|
53
|
+
" Valid values are the `id`s of `addressableArea`s in the"
|
|
54
|
+
" [deck definition](https://github.com/Opentrons/opentrons/tree/edge/shared-data/deck)."
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ModuleLocation(BaseModel):
|
|
60
|
+
"""The location of something placed atop a hardware module."""
|
|
61
|
+
|
|
62
|
+
moduleId: str = Field(
|
|
63
|
+
...,
|
|
64
|
+
description="The ID of a loaded module from a prior `loadModule` command.",
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class OnLabwareLocation(BaseModel):
|
|
69
|
+
"""The location of something placed atop another labware."""
|
|
70
|
+
|
|
71
|
+
labwareId: str = Field(
|
|
72
|
+
...,
|
|
73
|
+
description="The ID of a loaded Labware from a prior `loadLabware` command.",
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class InStackerHopperLocation(BaseModel):
|
|
78
|
+
"""The location of a labware in a stacker hopper."""
|
|
79
|
+
|
|
80
|
+
kind: Literal["inStackerHopper"] = "inStackerHopper"
|
|
81
|
+
moduleId: str = Field(
|
|
82
|
+
..., description="The ID of the stacker in which this labware is."
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
_OffDeckLocationType = Literal["offDeck"]
|
|
87
|
+
_SystemLocationType = Literal["systemLocation"]
|
|
88
|
+
OFF_DECK_LOCATION: _OffDeckLocationType = "offDeck"
|
|
89
|
+
SYSTEM_LOCATION: _SystemLocationType = "systemLocation"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def labware_location_is_off_deck(
|
|
93
|
+
location: LabwareLocation,
|
|
94
|
+
) -> TypeGuard[_OffDeckLocationType]:
|
|
95
|
+
"""Check if a location is an off deck location."""
|
|
96
|
+
return isinstance(location, str) and location == OFF_DECK_LOCATION
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def labware_location_is_system(
|
|
100
|
+
location: LabwareLocation,
|
|
101
|
+
) -> TypeGuard[_SystemLocationType]:
|
|
102
|
+
"""Check if a location is the system location."""
|
|
103
|
+
return isinstance(location, str) and location == SYSTEM_LOCATION
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class OnLabwareLocationSequenceComponent(BaseModel):
|
|
107
|
+
"""Labware on another labware."""
|
|
108
|
+
|
|
109
|
+
kind: Literal["onLabware"] = "onLabware"
|
|
110
|
+
labwareId: str
|
|
111
|
+
lidId: str | SkipJsonSchema[None] = Field(None)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class OnModuleLocationSequenceComponent(BaseModel):
|
|
115
|
+
"""Labware on a module."""
|
|
116
|
+
|
|
117
|
+
kind: Literal["onModule"] = "onModule"
|
|
118
|
+
moduleId: str
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class OnAddressableAreaLocationSequenceComponent(BaseModel):
|
|
122
|
+
"""Labware on an addressable area."""
|
|
123
|
+
|
|
124
|
+
kind: Literal["onAddressableArea"] = "onAddressableArea"
|
|
125
|
+
addressableAreaName: str
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class OnCutoutFixtureLocationSequenceComponent(BaseModel):
|
|
129
|
+
"""Something on a deck cutout fixture."""
|
|
130
|
+
|
|
131
|
+
kind: Literal["onCutoutFixture"] = "onCutoutFixture"
|
|
132
|
+
possibleCutoutFixtureIds: list[str]
|
|
133
|
+
cutoutId: str
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class NotOnDeckLocationSequenceComponent(BaseModel):
|
|
137
|
+
"""Labware on a system location."""
|
|
138
|
+
|
|
139
|
+
kind: Literal["notOnDeck"] = "notOnDeck"
|
|
140
|
+
logicalLocationName: _OffDeckLocationType | _SystemLocationType
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
LabwareLocationSequence = list[
|
|
144
|
+
OnLabwareLocationSequenceComponent
|
|
145
|
+
| OnModuleLocationSequenceComponent
|
|
146
|
+
| OnAddressableAreaLocationSequenceComponent
|
|
147
|
+
| NotOnDeckLocationSequenceComponent
|
|
148
|
+
| OnCutoutFixtureLocationSequenceComponent
|
|
149
|
+
| InStackerHopperLocation
|
|
150
|
+
]
|
|
151
|
+
"""Labware location specifier."""
|
|
152
|
+
|
|
153
|
+
LabwareLocation = Union[
|
|
154
|
+
DeckSlotLocation,
|
|
155
|
+
ModuleLocation,
|
|
156
|
+
OnLabwareLocation,
|
|
157
|
+
_OffDeckLocationType,
|
|
158
|
+
_SystemLocationType,
|
|
159
|
+
AddressableAreaLocation,
|
|
160
|
+
InStackerHopperLocation,
|
|
161
|
+
]
|
|
162
|
+
"""Union of all locations where it's legal to keep a labware."""
|
|
163
|
+
|
|
164
|
+
LoadableLabwareLocation = Union[
|
|
165
|
+
DeckSlotLocation,
|
|
166
|
+
ModuleLocation,
|
|
167
|
+
OnLabwareLocation,
|
|
168
|
+
_OffDeckLocationType,
|
|
169
|
+
_SystemLocationType,
|
|
170
|
+
AddressableAreaLocation,
|
|
171
|
+
]
|
|
172
|
+
"""Union of all locations where it's legal to load a labware."""
|
|
173
|
+
|
|
174
|
+
OnDeckLabwareLocation = Union[
|
|
175
|
+
DeckSlotLocation, ModuleLocation, OnLabwareLocation, AddressableAreaLocation
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
NonStackedLocation = Union[
|
|
179
|
+
DeckSlotLocation,
|
|
180
|
+
AddressableAreaLocation,
|
|
181
|
+
ModuleLocation,
|
|
182
|
+
_OffDeckLocationType,
|
|
183
|
+
_SystemLocationType,
|
|
184
|
+
]
|
|
185
|
+
"""Union of all locations where it's legal to keep a labware that can't be stacked on another labware"""
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# TODO(mm, 2022-11-07): Deduplicate with Vec3f.
|
|
189
|
+
class DeckPoint(BaseModel):
|
|
190
|
+
"""Coordinates of a point in deck space."""
|
|
191
|
+
|
|
192
|
+
x: float
|
|
193
|
+
y: float
|
|
194
|
+
z: float
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
"""Protocol engine types to do with modules."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import (
|
|
7
|
+
TypeGuard,
|
|
8
|
+
Literal,
|
|
9
|
+
Optional,
|
|
10
|
+
List,
|
|
11
|
+
Dict,
|
|
12
|
+
Any,
|
|
13
|
+
NamedTuple,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from pydantic import BaseModel, Field
|
|
17
|
+
|
|
18
|
+
from opentrons.hardware_control.modules import (
|
|
19
|
+
ModuleType as ModuleType,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from .location import DeckSlotLocation
|
|
23
|
+
from .labware_offset_vector import LabwareOffsetVector
|
|
24
|
+
from .labware_movement import LabwareMovementOffsetData
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# TODO(mc, 2022-01-18): use opentrons_shared_data.module.types.ModuleModel
|
|
28
|
+
class ModuleModel(str, Enum):
|
|
29
|
+
"""All available modules' models."""
|
|
30
|
+
|
|
31
|
+
TEMPERATURE_MODULE_V1 = "temperatureModuleV1"
|
|
32
|
+
TEMPERATURE_MODULE_V2 = "temperatureModuleV2"
|
|
33
|
+
MAGNETIC_MODULE_V1 = "magneticModuleV1"
|
|
34
|
+
MAGNETIC_MODULE_V2 = "magneticModuleV2"
|
|
35
|
+
THERMOCYCLER_MODULE_V1 = "thermocyclerModuleV1"
|
|
36
|
+
THERMOCYCLER_MODULE_V2 = "thermocyclerModuleV2"
|
|
37
|
+
HEATER_SHAKER_MODULE_V1 = "heaterShakerModuleV1"
|
|
38
|
+
MAGNETIC_BLOCK_V1 = "magneticBlockV1"
|
|
39
|
+
ABSORBANCE_READER_V1 = "absorbanceReaderV1"
|
|
40
|
+
FLEX_STACKER_MODULE_V1 = "flexStackerModuleV1"
|
|
41
|
+
|
|
42
|
+
def as_type(self) -> ModuleType:
|
|
43
|
+
"""Get the ModuleType of this model."""
|
|
44
|
+
if ModuleModel.is_temperature_module_model(self):
|
|
45
|
+
return ModuleType.TEMPERATURE
|
|
46
|
+
elif ModuleModel.is_magnetic_module_model(self):
|
|
47
|
+
return ModuleType.MAGNETIC
|
|
48
|
+
elif ModuleModel.is_thermocycler_module_model(self):
|
|
49
|
+
return ModuleType.THERMOCYCLER
|
|
50
|
+
elif ModuleModel.is_heater_shaker_module_model(self):
|
|
51
|
+
return ModuleType.HEATER_SHAKER
|
|
52
|
+
elif ModuleModel.is_magnetic_block(self):
|
|
53
|
+
return ModuleType.MAGNETIC_BLOCK
|
|
54
|
+
elif ModuleModel.is_absorbance_reader(self):
|
|
55
|
+
return ModuleType.ABSORBANCE_READER
|
|
56
|
+
elif ModuleModel.is_flex_stacker(self):
|
|
57
|
+
return ModuleType.FLEX_STACKER
|
|
58
|
+
|
|
59
|
+
assert False, f"Invalid ModuleModel {self}"
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def is_temperature_module_model(
|
|
63
|
+
cls, model: ModuleModel
|
|
64
|
+
) -> TypeGuard[TemperatureModuleModel]:
|
|
65
|
+
"""Whether a given model is a Temperature Module."""
|
|
66
|
+
return model in [cls.TEMPERATURE_MODULE_V1, cls.TEMPERATURE_MODULE_V2]
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def is_magnetic_module_model(
|
|
70
|
+
cls, model: ModuleModel
|
|
71
|
+
) -> TypeGuard[MagneticModuleModel]:
|
|
72
|
+
"""Whether a given model is a Magnetic Module."""
|
|
73
|
+
return model in [cls.MAGNETIC_MODULE_V1, cls.MAGNETIC_MODULE_V2]
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def is_thermocycler_module_model(
|
|
77
|
+
cls, model: ModuleModel
|
|
78
|
+
) -> TypeGuard[ThermocyclerModuleModel]:
|
|
79
|
+
"""Whether a given model is a Thermocycler Module."""
|
|
80
|
+
return model in [cls.THERMOCYCLER_MODULE_V1, cls.THERMOCYCLER_MODULE_V2]
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def is_heater_shaker_module_model(
|
|
84
|
+
cls, model: ModuleModel
|
|
85
|
+
) -> TypeGuard[HeaterShakerModuleModel]:
|
|
86
|
+
"""Whether a given model is a Heater-Shaker Module."""
|
|
87
|
+
return model == cls.HEATER_SHAKER_MODULE_V1
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def is_magnetic_block(cls, model: ModuleModel) -> TypeGuard[MagneticBlockModel]:
|
|
91
|
+
"""Whether a given model is a Magnetic block."""
|
|
92
|
+
return model == cls.MAGNETIC_BLOCK_V1
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def is_absorbance_reader(
|
|
96
|
+
cls, model: ModuleModel
|
|
97
|
+
) -> TypeGuard[AbsorbanceReaderModel]:
|
|
98
|
+
"""Whether a given model is an Absorbance Plate Reader."""
|
|
99
|
+
return model == cls.ABSORBANCE_READER_V1
|
|
100
|
+
|
|
101
|
+
@classmethod
|
|
102
|
+
def is_flex_stacker(cls, model: ModuleModel) -> TypeGuard[FlexStackerModuleModel]:
|
|
103
|
+
"""Whether a given model is a Flex Stacker.."""
|
|
104
|
+
return model == cls.FLEX_STACKER_MODULE_V1
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
TemperatureModuleModel = Literal[
|
|
108
|
+
ModuleModel.TEMPERATURE_MODULE_V1, ModuleModel.TEMPERATURE_MODULE_V2
|
|
109
|
+
]
|
|
110
|
+
MagneticModuleModel = Literal[
|
|
111
|
+
ModuleModel.MAGNETIC_MODULE_V1, ModuleModel.MAGNETIC_MODULE_V2
|
|
112
|
+
]
|
|
113
|
+
ThermocyclerModuleModel = Literal[
|
|
114
|
+
ModuleModel.THERMOCYCLER_MODULE_V1, ModuleModel.THERMOCYCLER_MODULE_V2
|
|
115
|
+
]
|
|
116
|
+
HeaterShakerModuleModel = Literal[ModuleModel.HEATER_SHAKER_MODULE_V1]
|
|
117
|
+
MagneticBlockModel = Literal[ModuleModel.MAGNETIC_BLOCK_V1]
|
|
118
|
+
AbsorbanceReaderModel = Literal[ModuleModel.ABSORBANCE_READER_V1]
|
|
119
|
+
FlexStackerModuleModel = Literal[ModuleModel.FLEX_STACKER_MODULE_V1]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class ModuleDimensions(BaseModel):
|
|
123
|
+
"""Dimension type for modules."""
|
|
124
|
+
|
|
125
|
+
bareOverallHeight: float
|
|
126
|
+
overLabwareHeight: float
|
|
127
|
+
lidHeight: Optional[float] = None
|
|
128
|
+
maxStackerFillHeight: Optional[float] = None
|
|
129
|
+
maxStackerRetrievableHeight: Optional[float] = None
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# TODO(mm, 2022-11-07): Deduplicate with Vec3f.
|
|
133
|
+
class ModuleCalibrationPoint(BaseModel):
|
|
134
|
+
"""Calibration Point type for module definition."""
|
|
135
|
+
|
|
136
|
+
x: float
|
|
137
|
+
y: float
|
|
138
|
+
z: float
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# TODO(mm, 2023-04-13): Move to shared-data, so this binding can be maintained alongside the JSON
|
|
142
|
+
# schema that it's sourced from. We already do that for labware definitions and JSON protocols.
|
|
143
|
+
class ModuleDefinition(BaseModel):
|
|
144
|
+
"""A module definition conforming to module definition schema v3."""
|
|
145
|
+
|
|
146
|
+
# Note: This field is misleading.
|
|
147
|
+
#
|
|
148
|
+
# This class only models v3 definitions ("module/schemas/3"), not v2 ("module/schemas/2").
|
|
149
|
+
# labwareOffset is required to have a z-component, for example.
|
|
150
|
+
#
|
|
151
|
+
# When parsing from a schema v3 JSON definition into this model,
|
|
152
|
+
# the definition's `"$otSharedSchema": "module/schemas/3"` field will be thrown away
|
|
153
|
+
# because it has a dollar sign, which doesn't match this field.
|
|
154
|
+
# Then, this field will default to "module/schemas/2", because no value was provided.
|
|
155
|
+
#
|
|
156
|
+
# We should fix this field once Jira RSS-221 is resolved. RSS-221 makes it difficult to fix
|
|
157
|
+
# because robot-server has been storing and loading these bad fields in its database.
|
|
158
|
+
otSharedSchema: str = Field("module/schemas/2", description="The current schema.")
|
|
159
|
+
|
|
160
|
+
moduleType: ModuleType = Field(
|
|
161
|
+
...,
|
|
162
|
+
description="Module type (Temperature/Magnetic/Thermocycler)",
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
model: ModuleModel = Field(..., description="Model name of the module")
|
|
166
|
+
|
|
167
|
+
labwareOffset: LabwareOffsetVector = Field(
|
|
168
|
+
...,
|
|
169
|
+
description="Labware offset in x, y, z.",
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
dimensions: ModuleDimensions = Field(..., description="Module dimension")
|
|
173
|
+
|
|
174
|
+
calibrationPoint: ModuleCalibrationPoint = Field(
|
|
175
|
+
...,
|
|
176
|
+
description="Calibration point of module.",
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
displayName: str = Field(..., description="Display name.")
|
|
180
|
+
|
|
181
|
+
quirks: List[str] = Field(..., description="Module quirks")
|
|
182
|
+
|
|
183
|
+
# In releases prior to https://github.com/Opentrons/opentrons/pull/11873 (v6.3.0),
|
|
184
|
+
# the matrices in slotTransforms were 3x3.
|
|
185
|
+
# After, they are 4x4, even though there was no schema version bump.
|
|
186
|
+
#
|
|
187
|
+
# Because old objects of this class, with the 3x3 matrices, were stored in robot-server's
|
|
188
|
+
# database, this field needs to stay typed loosely enough to support both sizes.
|
|
189
|
+
# We can fix this once Jira RSS-221 is resolved.
|
|
190
|
+
slotTransforms: Dict[str, Any] = Field(
|
|
191
|
+
...,
|
|
192
|
+
description="Dictionary of transforms for each slot.",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
compatibleWith: List[ModuleModel] = Field(
|
|
196
|
+
...,
|
|
197
|
+
description="List of module models this model is compatible with.",
|
|
198
|
+
)
|
|
199
|
+
gripperOffsets: Optional[Dict[str, LabwareMovementOffsetData]] = Field(
|
|
200
|
+
default_factory=dict,
|
|
201
|
+
description="Offsets to use for labware movement using gripper",
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class LoadedModule(BaseModel):
|
|
206
|
+
"""A module that has been loaded."""
|
|
207
|
+
|
|
208
|
+
id: str
|
|
209
|
+
model: ModuleModel
|
|
210
|
+
location: Optional[DeckSlotLocation] = None
|
|
211
|
+
serialNumber: Optional[str] = None
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class SpeedRange(NamedTuple):
|
|
215
|
+
"""Minimum and maximum allowed speeds for a shaking module."""
|
|
216
|
+
|
|
217
|
+
min: int
|
|
218
|
+
max: int
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class TemperatureRange(NamedTuple):
|
|
222
|
+
"""Minimum and maximum allowed temperatures for a heating module."""
|
|
223
|
+
|
|
224
|
+
min: float
|
|
225
|
+
max: float
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class HeaterShakerLatchStatus(Enum):
|
|
229
|
+
"""Heater-Shaker latch status for determining pipette and labware movement errors."""
|
|
230
|
+
|
|
231
|
+
CLOSED = "closed"
|
|
232
|
+
OPEN = "open"
|
|
233
|
+
UNKNOWN = "unknown"
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@dataclass(frozen=True)
|
|
237
|
+
class HeaterShakerMovementRestrictors:
|
|
238
|
+
"""Shaking status, latch status and slot location for determining movement restrictions."""
|
|
239
|
+
|
|
240
|
+
plate_shaking: bool
|
|
241
|
+
latch_status: HeaterShakerLatchStatus
|
|
242
|
+
deck_slot: int
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
ABSMeasureMode = Literal["single", "multi"]
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# TODO(mm, 2022-11-07): Deduplicate with Vec3f.
|
|
249
|
+
class ModuleOffsetVector(BaseModel):
|
|
250
|
+
"""Offset, in deck coordinates, from nominal to actual position of labware on a module."""
|
|
251
|
+
|
|
252
|
+
x: float
|
|
253
|
+
y: float
|
|
254
|
+
z: float
|
|
255
|
+
|
|
256
|
+
def __add__(self, other: Any) -> ModuleOffsetVector:
|
|
257
|
+
"""Adds two vectors together."""
|
|
258
|
+
if not isinstance(other, (LabwareOffsetVector, ModuleOffsetVector)):
|
|
259
|
+
return NotImplemented
|
|
260
|
+
return ModuleOffsetVector(
|
|
261
|
+
x=self.x + other.x, y=self.y + other.y, z=self.z + other.z
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def __radd__(self, other: Any) -> ModuleOffsetVector:
|
|
265
|
+
"""Adds two vectors together, the other way."""
|
|
266
|
+
if not isinstance(other, (LabwareOffsetVector, ModuleOffsetVector)):
|
|
267
|
+
return NotImplemented
|
|
268
|
+
return ModuleOffsetVector(
|
|
269
|
+
x=other.x + self.x, y=other.y + self.y, z=other.z + self.z
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
def __sub__(self, other: Any) -> ModuleOffsetVector:
|
|
273
|
+
"""Subtracts two vectors."""
|
|
274
|
+
if not isinstance(other, (LabwareOffsetVector, ModuleOffsetVector)):
|
|
275
|
+
return NotImplemented
|
|
276
|
+
return ModuleOffsetVector(
|
|
277
|
+
x=self.x - other.x, y=self.y - other.y, z=self.z - other.z
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def __rsub__(self, other: Any) -> ModuleOffsetVector:
|
|
281
|
+
"""Subtracts two vectors, the other way."""
|
|
282
|
+
if not isinstance(other, (LabwareOffsetVector, ModuleOffsetVector)):
|
|
283
|
+
return NotImplemented
|
|
284
|
+
return ModuleOffsetVector(
|
|
285
|
+
x=other.x - self.x, y=other.y - self.y, z=other.z - self.z
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
@dataclass
|
|
290
|
+
class ModuleOffsetData:
|
|
291
|
+
"""Module calibration offset data."""
|
|
292
|
+
|
|
293
|
+
moduleOffsetVector: ModuleOffsetVector
|
|
294
|
+
location: DeckSlotLocation
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class StackerFillEmptyStrategy(str, Enum):
|
|
298
|
+
"""Strategy to use for filling or emptying a stacker."""
|
|
299
|
+
|
|
300
|
+
MANUAL_WITH_PAUSE = "manualWithPause"
|
|
301
|
+
LOGICAL = "logical"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Protocol engine types to do with partial tip configurations."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal, Union
|
|
4
|
+
|
|
5
|
+
from pydantic import (
|
|
6
|
+
BaseModel,
|
|
7
|
+
Field,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
NOZZLE_NAME_REGEX = r"[A-Z]\d{1,2}"
|
|
11
|
+
PRIMARY_NOZZLE_LITERAL = Literal["A1", "H1", "A12", "H12"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AllNozzleLayoutConfiguration(BaseModel):
|
|
15
|
+
"""All basemodel to represent a reset to the nozzle configuration. Sending no parameters resets to default."""
|
|
16
|
+
|
|
17
|
+
style: Literal["ALL"] = "ALL"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SingleNozzleLayoutConfiguration(BaseModel):
|
|
21
|
+
"""Minimum information required for a new nozzle configuration."""
|
|
22
|
+
|
|
23
|
+
style: Literal["SINGLE"] = "SINGLE"
|
|
24
|
+
primaryNozzle: PRIMARY_NOZZLE_LITERAL = Field(
|
|
25
|
+
...,
|
|
26
|
+
description="The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class RowNozzleLayoutConfiguration(BaseModel):
|
|
31
|
+
"""Minimum information required for a new nozzle configuration."""
|
|
32
|
+
|
|
33
|
+
style: Literal["ROW"] = "ROW"
|
|
34
|
+
primaryNozzle: PRIMARY_NOZZLE_LITERAL = Field(
|
|
35
|
+
...,
|
|
36
|
+
description="The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ColumnNozzleLayoutConfiguration(BaseModel):
|
|
41
|
+
"""Information required for nozzle configurations of type ROW and COLUMN."""
|
|
42
|
+
|
|
43
|
+
style: Literal["COLUMN"] = "COLUMN"
|
|
44
|
+
primaryNozzle: PRIMARY_NOZZLE_LITERAL = Field(
|
|
45
|
+
...,
|
|
46
|
+
description="The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class QuadrantNozzleLayoutConfiguration(BaseModel):
|
|
51
|
+
"""Information required for nozzle configurations of type QUADRANT."""
|
|
52
|
+
|
|
53
|
+
style: Literal["QUADRANT"] = "QUADRANT"
|
|
54
|
+
primaryNozzle: PRIMARY_NOZZLE_LITERAL = Field(
|
|
55
|
+
...,
|
|
56
|
+
description="The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.",
|
|
57
|
+
)
|
|
58
|
+
frontRightNozzle: str = Field(
|
|
59
|
+
...,
|
|
60
|
+
pattern=NOZZLE_NAME_REGEX,
|
|
61
|
+
description="The front right nozzle in your configuration.",
|
|
62
|
+
)
|
|
63
|
+
backLeftNozzle: str = Field(
|
|
64
|
+
...,
|
|
65
|
+
pattern=NOZZLE_NAME_REGEX,
|
|
66
|
+
description="The back left nozzle in your configuration.",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
NozzleLayoutConfigurationType = Union[
|
|
71
|
+
AllNozzleLayoutConfiguration,
|
|
72
|
+
SingleNozzleLayoutConfiguration,
|
|
73
|
+
ColumnNozzleLayoutConfiguration,
|
|
74
|
+
RowNozzleLayoutConfiguration,
|
|
75
|
+
QuadrantNozzleLayoutConfiguration,
|
|
76
|
+
]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Protocol Engine types that have to do with runtime parameters."""
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional, Mapping, Union, Literal, Dict, List
|
|
7
|
+
from pydantic import (
|
|
8
|
+
BaseModel,
|
|
9
|
+
Field,
|
|
10
|
+
StrictBool,
|
|
11
|
+
StrictFloat,
|
|
12
|
+
StrictInt,
|
|
13
|
+
StrictStr,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# TODO (spp, 2024-04-02): move all RTP types to runner
|
|
18
|
+
class RTPBase(BaseModel):
|
|
19
|
+
"""Parameters defined in a protocol."""
|
|
20
|
+
|
|
21
|
+
displayName: StrictStr = Field(..., description="Display string for the parameter.")
|
|
22
|
+
variableName: StrictStr = Field(
|
|
23
|
+
..., description="Python variable name of the parameter."
|
|
24
|
+
)
|
|
25
|
+
description: Optional[StrictStr] = Field(
|
|
26
|
+
None, description="Detailed description of the parameter."
|
|
27
|
+
)
|
|
28
|
+
suffix: Optional[StrictStr] = Field(
|
|
29
|
+
None,
|
|
30
|
+
description="Units (like mL, mm/sec, etc) or a custom suffix for the parameter.",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class NumberParameter(RTPBase):
|
|
35
|
+
"""An integer parameter defined in a protocol."""
|
|
36
|
+
|
|
37
|
+
type: Literal["int", "float"] = Field(
|
|
38
|
+
..., description="String specifying whether the number is an int or float type."
|
|
39
|
+
)
|
|
40
|
+
min: Union[StrictInt, StrictFloat] = Field(
|
|
41
|
+
..., description="Minimum value that the number param is allowed to have."
|
|
42
|
+
)
|
|
43
|
+
max: Union[StrictInt, StrictFloat] = Field(
|
|
44
|
+
..., description="Maximum value that the number param is allowed to have."
|
|
45
|
+
)
|
|
46
|
+
value: Union[StrictInt, StrictFloat] = Field(
|
|
47
|
+
...,
|
|
48
|
+
description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.",
|
|
49
|
+
)
|
|
50
|
+
default: Union[StrictInt, StrictFloat] = Field(
|
|
51
|
+
...,
|
|
52
|
+
description="Default value of the parameter, to be used when there is no client-specified value.",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class BooleanParameter(RTPBase):
|
|
57
|
+
"""A boolean parameter defined in a protocol."""
|
|
58
|
+
|
|
59
|
+
type: Literal["bool"] = Field(
|
|
60
|
+
default="bool", description="String specifying the type of this parameter"
|
|
61
|
+
)
|
|
62
|
+
value: StrictBool = Field(
|
|
63
|
+
...,
|
|
64
|
+
description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.",
|
|
65
|
+
)
|
|
66
|
+
default: StrictBool = Field(
|
|
67
|
+
...,
|
|
68
|
+
description="Default value of the parameter, to be used when there is no client-specified value.",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class EnumChoice(BaseModel):
|
|
73
|
+
"""Components of choices used in RTP Enum Parameters."""
|
|
74
|
+
|
|
75
|
+
displayName: StrictStr = Field(
|
|
76
|
+
..., description="Display string for the param's choice."
|
|
77
|
+
)
|
|
78
|
+
value: Union[StrictInt, StrictFloat, StrictStr] = Field(
|
|
79
|
+
..., description="Enum value of the param's choice."
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class EnumParameter(RTPBase):
|
|
84
|
+
"""A string enum defined in a protocol."""
|
|
85
|
+
|
|
86
|
+
type: Literal["int", "float", "str"] = Field(
|
|
87
|
+
...,
|
|
88
|
+
description="String specifying whether the parameter is an int or float or string type.",
|
|
89
|
+
)
|
|
90
|
+
choices: List[EnumChoice] = Field(
|
|
91
|
+
..., description="List of valid choices for this parameter."
|
|
92
|
+
)
|
|
93
|
+
value: Union[StrictInt, StrictFloat, StrictStr] = Field(
|
|
94
|
+
...,
|
|
95
|
+
description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.",
|
|
96
|
+
)
|
|
97
|
+
default: Union[StrictInt, StrictFloat, StrictStr] = Field(
|
|
98
|
+
...,
|
|
99
|
+
description="Default value of the parameter, to be used when there is no client-specified value.",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class FileInfo(BaseModel):
|
|
104
|
+
"""A file UUID descriptor."""
|
|
105
|
+
|
|
106
|
+
id: str = Field(
|
|
107
|
+
...,
|
|
108
|
+
description="The UUID identifier of the file stored on the robot.",
|
|
109
|
+
)
|
|
110
|
+
name: str = Field(..., description="Name of the file, including the extension.")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class CSVParameter(RTPBase):
|
|
114
|
+
"""A CSV file parameter defined in a protocol."""
|
|
115
|
+
|
|
116
|
+
type: Literal["csv_file"] = Field(
|
|
117
|
+
default="csv_file", description="String specifying the type of this parameter"
|
|
118
|
+
)
|
|
119
|
+
file: Optional[FileInfo] = Field(
|
|
120
|
+
default=None,
|
|
121
|
+
description="ID of the CSV file stored on the robot; to be used for fetching the CSV file."
|
|
122
|
+
" For local analysis this will most likely be empty.",
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
RunTimeParameter = Union[NumberParameter, EnumParameter, BooleanParameter, CSVParameter]
|
|
127
|
+
|
|
128
|
+
PrimitiveRunTimeParamValuesType = Mapping[
|
|
129
|
+
StrictStr, Union[StrictInt, StrictFloat, StrictBool, StrictStr]
|
|
130
|
+
] # update value types as more RTP types are added
|
|
131
|
+
|
|
132
|
+
CSVRunTimeParamFilesType = Mapping[StrictStr, StrictStr]
|
|
133
|
+
CSVRuntimeParamPaths = Dict[str, Path]
|