opentrons 8.4.0a7__py2.py3-none-any.whl → 8.4.0a8__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/protocol_api/core/engine/instrument.py +4 -4
- opentrons/protocol_api/core/instrument.py +1 -1
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +1 -1
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +1 -1
- opentrons/protocol_api/instrument_context.py +24 -11
- opentrons/protocol_engine/commands/liquid_probe.py +6 -0
- opentrons/protocol_engine/commands/seal_pipette_to_tip.py +44 -23
- opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +8 -11
- opentrons/protocol_engine/errors/__init__.py +2 -0
- opentrons/protocol_engine/errors/exceptions.py +12 -0
- opentrons/protocol_engine/execution/pipetting.py +1 -1
- opentrons/protocol_engine/state/geometry.py +134 -81
- opentrons/protocol_engine/state/modules.py +33 -16
- opentrons/protocol_engine/types/module.py +32 -0
- {opentrons-8.4.0a7.dist-info → opentrons-8.4.0a8.dist-info}/METADATA +4 -4
- {opentrons-8.4.0a7.dist-info → opentrons-8.4.0a8.dist-info}/RECORD +20 -20
- {opentrons-8.4.0a7.dist-info → opentrons-8.4.0a8.dist-info}/LICENSE +0 -0
- {opentrons-8.4.0a7.dist-info → opentrons-8.4.0a8.dist-info}/WHEEL +0 -0
- {opentrons-8.4.0a7.dist-info → opentrons-8.4.0a8.dist-info}/entry_points.txt +0 -0
- {opentrons-8.4.0a7.dist-info → opentrons-8.4.0a8.dist-info}/top_level.txt +0 -0
|
@@ -834,7 +834,7 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
834
834
|
)
|
|
835
835
|
)
|
|
836
836
|
|
|
837
|
-
def resin_tip_unseal(self, location: Location, well_core: WellCore) -> None:
|
|
837
|
+
def resin_tip_unseal(self, location: Location | None, well_core: WellCore) -> None:
|
|
838
838
|
well_name = well_core.get_name()
|
|
839
839
|
labware_id = well_core.labware_id
|
|
840
840
|
|
|
@@ -1188,9 +1188,9 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1188
1188
|
cmd.GetNextTipParams(
|
|
1189
1189
|
pipetteId=self._pipette_id,
|
|
1190
1190
|
labwareIds=[tip_rack.labware_id for tip_rack in valid_tip_racks],
|
|
1191
|
-
startingTipWell=
|
|
1192
|
-
|
|
1193
|
-
|
|
1191
|
+
startingTipWell=(
|
|
1192
|
+
starting_well.get_name() if starting_well is not None else None
|
|
1193
|
+
),
|
|
1194
1194
|
)
|
|
1195
1195
|
)
|
|
1196
1196
|
next_tip_info = result.nextTipInfo
|
|
@@ -332,7 +332,7 @@ class LegacyInstrumentCore(AbstractInstrument[LegacyWellCore, LegacyLabwareCore]
|
|
|
332
332
|
|
|
333
333
|
def resin_tip_unseal(
|
|
334
334
|
self,
|
|
335
|
-
location: types.Location,
|
|
335
|
+
location: types.Location | None,
|
|
336
336
|
well_core: WellCore,
|
|
337
337
|
) -> None:
|
|
338
338
|
raise APIVersionError(api_element="Unsealing resin tips.")
|
|
@@ -606,7 +606,20 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
606
606
|
"Blow_out being performed on a tiprack. "
|
|
607
607
|
"Please re-check your code"
|
|
608
608
|
)
|
|
609
|
-
|
|
609
|
+
if target.location:
|
|
610
|
+
# because the lower levels of blowout don't handle LiquidHandlingWellLocation and
|
|
611
|
+
# there is no "operation_volume" for blowout we need to convert the relative location
|
|
612
|
+
# given with a .meniscus to an absolute point. To maintain the meniscus behavior
|
|
613
|
+
# we can just add the offset to the current liquid height.
|
|
614
|
+
if target.location.meniscus_tracking:
|
|
615
|
+
move_to_location = target.well.bottom(
|
|
616
|
+
target.well.current_liquid_height() # type: ignore [arg-type]
|
|
617
|
+
+ target.location.point.z
|
|
618
|
+
)
|
|
619
|
+
else:
|
|
620
|
+
move_to_location = target.location
|
|
621
|
+
else:
|
|
622
|
+
move_to_location = target.well.top()
|
|
610
623
|
well = target.well
|
|
611
624
|
elif isinstance(target, validation.PointTarget):
|
|
612
625
|
move_to_location = target.location
|
|
@@ -1611,9 +1624,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1611
1624
|
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1612
1625
|
for rack in transfer_args.tip_racks
|
|
1613
1626
|
],
|
|
1614
|
-
starting_tip=
|
|
1615
|
-
|
|
1616
|
-
|
|
1627
|
+
starting_tip=(
|
|
1628
|
+
self.starting_tip._core if self.starting_tip is not None else None
|
|
1629
|
+
),
|
|
1617
1630
|
trash_location=transfer_args.trash_location,
|
|
1618
1631
|
return_tip=return_tip,
|
|
1619
1632
|
)
|
|
@@ -1727,9 +1740,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1727
1740
|
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1728
1741
|
for rack in transfer_args.tip_racks
|
|
1729
1742
|
],
|
|
1730
|
-
starting_tip=
|
|
1731
|
-
|
|
1732
|
-
|
|
1743
|
+
starting_tip=(
|
|
1744
|
+
self.starting_tip._core if self.starting_tip is not None else None
|
|
1745
|
+
),
|
|
1733
1746
|
trash_location=transfer_args.trash_location,
|
|
1734
1747
|
return_tip=return_tip,
|
|
1735
1748
|
)
|
|
@@ -1843,9 +1856,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1843
1856
|
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1844
1857
|
for rack in transfer_args.tip_racks
|
|
1845
1858
|
],
|
|
1846
|
-
starting_tip=
|
|
1847
|
-
|
|
1848
|
-
|
|
1859
|
+
starting_tip=(
|
|
1860
|
+
self.starting_tip._core if self.starting_tip is not None else None
|
|
1861
|
+
),
|
|
1849
1862
|
trash_location=transfer_args.trash_location,
|
|
1850
1863
|
return_tip=return_tip,
|
|
1851
1864
|
)
|
|
@@ -2019,7 +2032,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2019
2032
|
location=well,
|
|
2020
2033
|
),
|
|
2021
2034
|
):
|
|
2022
|
-
self._core.resin_tip_unseal(location=
|
|
2035
|
+
self._core.resin_tip_unseal(location=None, well_core=well._core)
|
|
2023
2036
|
|
|
2024
2037
|
return self
|
|
2025
2038
|
|
|
@@ -188,6 +188,12 @@ async def _execute_common( # noqa: C901
|
|
|
188
188
|
well_name=well_name,
|
|
189
189
|
well_location=params.wellLocation,
|
|
190
190
|
)
|
|
191
|
+
state_view.geometry.validate_probed_height(
|
|
192
|
+
labware_id=labware_id,
|
|
193
|
+
well_name=well_name,
|
|
194
|
+
pipette_id=pipette_id,
|
|
195
|
+
probed_height=z_pos,
|
|
196
|
+
)
|
|
191
197
|
except PipetteLiquidNotFoundError as exception:
|
|
192
198
|
move_result.state_update.set_pipette_ready_to_aspirate(
|
|
193
199
|
pipette_id=pipette_id, ready_to_aspirate=True
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"""Seal tips to pipette command request, result, and implementation models."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from pydantic import Field, BaseModel
|
|
5
4
|
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
6
|
-
|
|
7
|
-
from opentrons.protocol_engine.types import MotorAxis
|
|
5
|
+
|
|
8
6
|
from typing_extensions import Literal
|
|
7
|
+
from pydantic import Field, BaseModel
|
|
8
|
+
|
|
9
|
+
from opentrons_shared_data.errors.exceptions import PositionUnknownError
|
|
9
10
|
|
|
11
|
+
from opentrons.types import MountType
|
|
12
|
+
from opentrons.protocol_engine.types import MotorAxis
|
|
10
13
|
from ..resources import ModelUtils, ensure_ot3_hardware
|
|
11
14
|
from ..types import PickUpTipWellLocation, FluidKind, AspiratedFluid
|
|
12
15
|
from .pipetting_common import (
|
|
@@ -27,7 +30,6 @@ from .command import (
|
|
|
27
30
|
|
|
28
31
|
from opentrons.hardware_control import HardwareControlAPI
|
|
29
32
|
from opentrons.hardware_control.types import Axis
|
|
30
|
-
from ..state.update_types import StateUpdate
|
|
31
33
|
|
|
32
34
|
if TYPE_CHECKING:
|
|
33
35
|
from ..state.state import StateView
|
|
@@ -138,28 +140,50 @@ class SealPipetteToTipImplementation(
|
|
|
138
140
|
"""A relative press-fit pick up command using gantry moves."""
|
|
139
141
|
prep_distance = tip_pick_up_params.prepDistance
|
|
140
142
|
press_distance = tip_pick_up_params.pressDistance
|
|
141
|
-
retract_distance = -1 * (
|
|
143
|
+
retract_distance = -1 * (press_distance) / 2
|
|
142
144
|
|
|
143
145
|
mount_axis = MotorAxis.LEFT_Z if mount == MountType.LEFT else MotorAxis.RIGHT_Z
|
|
144
|
-
|
|
146
|
+
ot3_hardware_api = ensure_ot3_hardware(self._hardware_api)
|
|
145
147
|
# TODO chb, 2025-01-29): Factor out the movement constants and relocate this logic into the hardware controller
|
|
146
|
-
|
|
147
|
-
|
|
148
|
+
try:
|
|
149
|
+
await self._gantry_mover.move_axes(
|
|
150
|
+
axis_map={mount_axis: prep_distance},
|
|
151
|
+
speed=10,
|
|
152
|
+
relative_move=True,
|
|
153
|
+
expect_stalls=True,
|
|
154
|
+
)
|
|
155
|
+
except PositionUnknownError:
|
|
156
|
+
# if this happens it's from the get position after the move and we can ignore it
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
await ot3_hardware_api.update_axis_position_estimations(
|
|
160
|
+
self._gantry_mover.motor_axes_to_present_hardware_axes([mount_axis])
|
|
148
161
|
)
|
|
149
162
|
|
|
150
163
|
# Drive mount down for press-fit
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
164
|
+
try:
|
|
165
|
+
await self._gantry_mover.move_axes(
|
|
166
|
+
axis_map={mount_axis: press_distance},
|
|
167
|
+
speed=10.0,
|
|
168
|
+
relative_move=True,
|
|
169
|
+
expect_stalls=True,
|
|
170
|
+
)
|
|
171
|
+
except PositionUnknownError:
|
|
172
|
+
# if this happens it's from the get position after the move and we can ignore it
|
|
173
|
+
pass
|
|
174
|
+
|
|
175
|
+
await ot3_hardware_api.update_axis_position_estimations(
|
|
176
|
+
self._gantry_mover.motor_axes_to_present_hardware_axes([mount_axis])
|
|
160
177
|
)
|
|
161
178
|
|
|
162
|
-
|
|
179
|
+
try:
|
|
180
|
+
await self._gantry_mover.move_axes(
|
|
181
|
+
axis_map={mount_axis: retract_distance}, speed=5.5, relative_move=True
|
|
182
|
+
)
|
|
183
|
+
except PositionUnknownError:
|
|
184
|
+
# if this happens it's from the get position after the move and we can ignore it
|
|
185
|
+
pass
|
|
186
|
+
|
|
163
187
|
await ot3_hardware_api.update_axis_position_estimations(
|
|
164
188
|
self._gantry_mover.motor_axes_to_present_hardware_axes([mount_axis])
|
|
165
189
|
)
|
|
@@ -283,13 +307,10 @@ class SealPipetteToTipImplementation(
|
|
|
283
307
|
if hw_instr is not None:
|
|
284
308
|
hw_instr.set_current_volume(_SAFE_TOP_VOLUME)
|
|
285
309
|
|
|
286
|
-
state_update =
|
|
287
|
-
state_update.update_pipette_tip_state(
|
|
310
|
+
state_update = move_result.state_update.update_pipette_tip_state(
|
|
288
311
|
pipette_id=pipette_id,
|
|
289
312
|
tip_geometry=tip_geometry,
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
state_update.set_fluid_aspirated(
|
|
313
|
+
).set_fluid_aspirated(
|
|
293
314
|
pipette_id=pipette_id,
|
|
294
315
|
fluid=AspiratedFluid(kind=FluidKind.LIQUID, volume=_SAFE_TOP_VOLUME),
|
|
295
316
|
)
|
|
@@ -3,12 +3,10 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from pydantic import Field
|
|
6
|
-
from typing import TYPE_CHECKING, Optional, Type
|
|
6
|
+
from typing import TYPE_CHECKING, Optional, Type, Final
|
|
7
7
|
from typing_extensions import Literal
|
|
8
8
|
|
|
9
9
|
from opentrons.protocol_engine.resources.model_utils import ModelUtils
|
|
10
|
-
from opentrons.protocol_engine.types import MotorAxis
|
|
11
|
-
from opentrons.types import MountType
|
|
12
10
|
|
|
13
11
|
from ..types import DropTipWellLocation
|
|
14
12
|
from .pipetting_common import (
|
|
@@ -56,6 +54,8 @@ _ExecuteReturn = (
|
|
|
56
54
|
SuccessData[UnsealPipetteFromTipResult] | DefinedErrorData[StallOrCollisionError]
|
|
57
55
|
)
|
|
58
56
|
|
|
57
|
+
CUSTOM_TIP_LENGTH_MARGIN: Final = 10
|
|
58
|
+
|
|
59
59
|
|
|
60
60
|
class UnsealPipetteFromTipImplementation(
|
|
61
61
|
AbstractCommandImpl[UnsealPipetteFromTipParams, _ExecuteReturn]
|
|
@@ -85,6 +85,10 @@ class UnsealPipetteFromTipImplementation(
|
|
|
85
85
|
|
|
86
86
|
well_location = params.wellLocation
|
|
87
87
|
|
|
88
|
+
tip_geometry = self._state_view.geometry.get_nominal_tip_geometry(
|
|
89
|
+
pipette_id, labware_id, well_name
|
|
90
|
+
)
|
|
91
|
+
|
|
88
92
|
is_partially_configured = self._state_view.pipettes.get_is_partially_configured(
|
|
89
93
|
pipette_id=pipette_id
|
|
90
94
|
)
|
|
@@ -93,6 +97,7 @@ class UnsealPipetteFromTipImplementation(
|
|
|
93
97
|
labware_id=labware_id,
|
|
94
98
|
well_location=well_location,
|
|
95
99
|
partially_configured=is_partially_configured,
|
|
100
|
+
override_default_offset=-(tip_geometry.length - CUSTOM_TIP_LENGTH_MARGIN),
|
|
96
101
|
)
|
|
97
102
|
|
|
98
103
|
move_result = await move_to_well(
|
|
@@ -106,14 +111,6 @@ class UnsealPipetteFromTipImplementation(
|
|
|
106
111
|
if isinstance(move_result, DefinedErrorData):
|
|
107
112
|
return move_result
|
|
108
113
|
|
|
109
|
-
# Move to an appropriate position
|
|
110
|
-
mount = self._state_view.pipettes.get_mount(pipette_id)
|
|
111
|
-
|
|
112
|
-
mount_axis = MotorAxis.LEFT_Z if mount == MountType.LEFT else MotorAxis.RIGHT_Z
|
|
113
|
-
await self._gantry_mover.move_axes(
|
|
114
|
-
axis_map={mount_axis: -14}, speed=10, relative_move=True
|
|
115
|
-
)
|
|
116
|
-
|
|
117
114
|
await self._tip_handler.drop_tip(
|
|
118
115
|
pipette_id=pipette_id,
|
|
119
116
|
home_after=None,
|
|
@@ -88,6 +88,7 @@ from .exceptions import (
|
|
|
88
88
|
OffsetLocationInvalidError,
|
|
89
89
|
FlexStackerLabwarePoolNotYetDefinedError,
|
|
90
90
|
FlexStackerNotLogicallyEmptyError,
|
|
91
|
+
InvalidLabwarePositionError,
|
|
91
92
|
)
|
|
92
93
|
|
|
93
94
|
from .error_occurrence import ErrorOccurrence, ProtocolCommandFailedError
|
|
@@ -171,6 +172,7 @@ __all__ = [
|
|
|
171
172
|
"OffsetLocationInvalidError",
|
|
172
173
|
"FlexStackerLabwarePoolNotYetDefinedError",
|
|
173
174
|
"FlexStackerNotLogicallyEmptyError",
|
|
175
|
+
"InvalidLabwarePositionError",
|
|
174
176
|
# error occurrence models
|
|
175
177
|
"ErrorOccurrence",
|
|
176
178
|
"CommandNotAllowedError",
|
|
@@ -1281,3 +1281,15 @@ class FlexStackerLabwarePoolNotYetDefinedError(ProtocolEngineError):
|
|
|
1281
1281
|
wrapping: Optional[Sequence[EnumeratedError]] = None,
|
|
1282
1282
|
) -> None:
|
|
1283
1283
|
super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
class InvalidLabwarePositionError(ProtocolEngineError):
|
|
1287
|
+
"""Raised when a labware position is internally invalid."""
|
|
1288
|
+
|
|
1289
|
+
def __init__(
|
|
1290
|
+
self,
|
|
1291
|
+
message: Optional[str] = None,
|
|
1292
|
+
details: Optional[dict[str, Any]] = None,
|
|
1293
|
+
wrapping: Optional[Sequence[EnumeratedError]] = None,
|
|
1294
|
+
) -> None:
|
|
1295
|
+
super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
|
|
@@ -326,7 +326,7 @@ class HardwarePipettingHandler(PipettingHandler):
|
|
|
326
326
|
well_name: str,
|
|
327
327
|
well_location: WellLocation,
|
|
328
328
|
) -> LiquidTrackingType:
|
|
329
|
-
"""
|
|
329
|
+
"""Return liquid level relative to the bottom of the well."""
|
|
330
330
|
hw_pipette = self._state_view.pipettes.get_hardware_pipette(
|
|
331
331
|
pipette_id=pipette_id,
|
|
332
332
|
attached_pipettes=self._hardware_api.attached_instruments,
|
|
@@ -17,7 +17,10 @@ from opentrons.types import (
|
|
|
17
17
|
MeniscusTrackingTarget,
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
-
from opentrons_shared_data.errors.exceptions import
|
|
20
|
+
from opentrons_shared_data.errors.exceptions import (
|
|
21
|
+
InvalidStoredData,
|
|
22
|
+
PipetteLiquidNotFoundError,
|
|
23
|
+
)
|
|
21
24
|
from opentrons_shared_data.labware.constants import WELL_NAME_PATTERN
|
|
22
25
|
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
23
26
|
from opentrons_shared_data.deck.types import CutoutFixture
|
|
@@ -31,6 +34,8 @@ from ..errors import (
|
|
|
31
34
|
LabwareNotLoadedOnModuleError,
|
|
32
35
|
LabwareMovementNotAllowedError,
|
|
33
36
|
OperationLocationNotInWellError,
|
|
37
|
+
InvalidLabwarePositionError,
|
|
38
|
+
LabwareNotOnDeckError,
|
|
34
39
|
)
|
|
35
40
|
from ..errors.exceptions import InvalidLiquidHeightFound
|
|
36
41
|
from ..resources import (
|
|
@@ -373,6 +378,59 @@ class GeometryView:
|
|
|
373
378
|
"Either it has been loaded off-deck or its been moved off-deck."
|
|
374
379
|
)
|
|
375
380
|
|
|
381
|
+
def _get_offset_from_parent_addressable_area(
|
|
382
|
+
self, child_definition: LabwareDefinition, parent: LabwareLocation
|
|
383
|
+
) -> LabwareOffsetVector:
|
|
384
|
+
"""Gets the offset vector of a labware from its eventual parent addressable area.
|
|
385
|
+
|
|
386
|
+
This returns the sum of the offsets for any labware-on-labware pairs plus the
|
|
387
|
+
"base offset", which is (0, 0, 0) in all cases except for modules on the
|
|
388
|
+
OT-2. See
|
|
389
|
+
protocol_engine.state.modules.get_nominal_offset_to_child_from_addressable_area
|
|
390
|
+
for more.
|
|
391
|
+
|
|
392
|
+
This does not incorporate LPC offsets or module calibration offsets.
|
|
393
|
+
"""
|
|
394
|
+
if isinstance(parent, (AddressableAreaLocation, DeckSlotLocation)):
|
|
395
|
+
return LabwareOffsetVector(x=0, y=0, z=0)
|
|
396
|
+
elif isinstance(parent, ModuleLocation):
|
|
397
|
+
module_id = parent.moduleId
|
|
398
|
+
module_model = self._modules.get_connected_model(module_id)
|
|
399
|
+
stacking_overlap = self._labware.get_module_overlap_offsets(
|
|
400
|
+
child_definition, module_model
|
|
401
|
+
)
|
|
402
|
+
module_to_child = (
|
|
403
|
+
self._modules.get_nominal_offset_to_child_from_addressable_area(
|
|
404
|
+
module_id=module_id
|
|
405
|
+
)
|
|
406
|
+
)
|
|
407
|
+
return LabwareOffsetVector(
|
|
408
|
+
x=module_to_child.x - stacking_overlap.x,
|
|
409
|
+
y=module_to_child.y - stacking_overlap.y,
|
|
410
|
+
z=module_to_child.z - stacking_overlap.z,
|
|
411
|
+
)
|
|
412
|
+
elif isinstance(parent, OnLabwareLocation):
|
|
413
|
+
on_labware = self._labware.get(parent.labwareId)
|
|
414
|
+
on_labware_dimensions = self._labware.get_dimensions(
|
|
415
|
+
labware_id=on_labware.id
|
|
416
|
+
)
|
|
417
|
+
stacking_overlap = self._labware.get_labware_overlap_offsets(
|
|
418
|
+
definition=child_definition, below_labware_name=on_labware.loadName
|
|
419
|
+
)
|
|
420
|
+
labware_offset = LabwareOffsetVector(
|
|
421
|
+
x=stacking_overlap.x,
|
|
422
|
+
y=stacking_overlap.y,
|
|
423
|
+
z=on_labware_dimensions.z - stacking_overlap.z,
|
|
424
|
+
)
|
|
425
|
+
return labware_offset + self._get_offset_from_parent_addressable_area(
|
|
426
|
+
self._labware.get_definition(on_labware.id), on_labware.location
|
|
427
|
+
)
|
|
428
|
+
else:
|
|
429
|
+
raise errors.LabwareNotOnDeckError(
|
|
430
|
+
"Cannot access labware since it is not on the deck. "
|
|
431
|
+
"Either it has been loaded off-deck or it has been moved off-deck."
|
|
432
|
+
)
|
|
433
|
+
|
|
376
434
|
def _normalize_module_calibration_offset(
|
|
377
435
|
self,
|
|
378
436
|
module_location: DeckSlotLocation,
|
|
@@ -498,6 +556,30 @@ class GeometryView:
|
|
|
498
556
|
f"Specifying {well_location.origin} with an offset of {well_location.offset} results in an operation location below the bottom of the well"
|
|
499
557
|
)
|
|
500
558
|
|
|
559
|
+
def validate_probed_height(
|
|
560
|
+
self,
|
|
561
|
+
labware_id: str,
|
|
562
|
+
well_name: str,
|
|
563
|
+
pipette_id: str,
|
|
564
|
+
probed_height: LiquidTrackingType,
|
|
565
|
+
) -> None:
|
|
566
|
+
"""Raise an error if a probed liquid height is not within well bounds."""
|
|
567
|
+
if isinstance(probed_height, SimulatedProbeResult):
|
|
568
|
+
return
|
|
569
|
+
lld_min_height = self._pipettes.get_current_tip_lld_settings(
|
|
570
|
+
pipette_id=pipette_id
|
|
571
|
+
)
|
|
572
|
+
well_def = self._labware.get_well_definition(labware_id, well_name)
|
|
573
|
+
well_depth = well_def.depth
|
|
574
|
+
if probed_height < lld_min_height:
|
|
575
|
+
raise PipetteLiquidNotFoundError(
|
|
576
|
+
f"Liquid Height of {probed_height} mm is lower minumum allowed lld height {lld_min_height} mm."
|
|
577
|
+
)
|
|
578
|
+
if probed_height > well_depth:
|
|
579
|
+
raise PipetteLiquidNotFoundError(
|
|
580
|
+
f"Liquid Height of {probed_height} mm is greater than maximum well height {well_depth} mm."
|
|
581
|
+
)
|
|
582
|
+
|
|
501
583
|
def get_well_position(
|
|
502
584
|
self,
|
|
503
585
|
labware_id: str,
|
|
@@ -695,6 +777,7 @@ class GeometryView:
|
|
|
695
777
|
labware_id: str,
|
|
696
778
|
well_location: DropTipWellLocation,
|
|
697
779
|
partially_configured: bool = False,
|
|
780
|
+
override_default_offset: float | None = None,
|
|
698
781
|
) -> WellLocation:
|
|
699
782
|
"""Get tip drop location given labware and hardware pipette.
|
|
700
783
|
|
|
@@ -713,8 +796,9 @@ class GeometryView:
|
|
|
713
796
|
origin=WellOrigin(well_location.origin.value),
|
|
714
797
|
offset=well_location.offset,
|
|
715
798
|
)
|
|
716
|
-
|
|
717
|
-
|
|
799
|
+
if override_default_offset is not None:
|
|
800
|
+
z_offset = override_default_offset
|
|
801
|
+
elif self._labware.get_definition(labware_id).parameters.isTiprack:
|
|
718
802
|
z_offset = self._labware.get_tip_drop_z_offset(
|
|
719
803
|
labware_id=labware_id,
|
|
720
804
|
length_scale=self._pipettes.get_return_tip_scale(pipette_id),
|
|
@@ -795,6 +879,32 @@ class GeometryView:
|
|
|
795
879
|
|
|
796
880
|
return slot_name
|
|
797
881
|
|
|
882
|
+
def get_ancestor_addressable_area_name(self, labware_id: str) -> str:
|
|
883
|
+
"""Get the name of the addressable area the labware is eventually on."""
|
|
884
|
+
labware = self._labware.get(labware_id)
|
|
885
|
+
original_display_name = self._labware.get_display_name(labware_id)
|
|
886
|
+
seen: Set[str] = set((labware_id,))
|
|
887
|
+
while isinstance(labware.location, OnLabwareLocation):
|
|
888
|
+
labware = self._labware.get(labware.location.labwareId)
|
|
889
|
+
if labware.id in seen:
|
|
890
|
+
raise InvalidLabwarePositionError(
|
|
891
|
+
f"Cycle detected in labware positioning for {original_display_name}"
|
|
892
|
+
)
|
|
893
|
+
seen.add(labware.id)
|
|
894
|
+
if isinstance(labware.location, DeckSlotLocation):
|
|
895
|
+
return labware.location.slotName.id
|
|
896
|
+
elif isinstance(labware.location, AddressableAreaLocation):
|
|
897
|
+
return labware.location.addressableAreaName
|
|
898
|
+
elif isinstance(labware.location, ModuleLocation):
|
|
899
|
+
return self._modules.get_provided_addressable_area(
|
|
900
|
+
labware.location.moduleId
|
|
901
|
+
)
|
|
902
|
+
else:
|
|
903
|
+
raise LabwareNotOnDeckError(
|
|
904
|
+
f"Labware {original_display_name} is not loaded on deck",
|
|
905
|
+
details={"eventual-location": repr(labware.location)},
|
|
906
|
+
)
|
|
907
|
+
|
|
798
908
|
def ensure_location_not_occupied(
|
|
799
909
|
self,
|
|
800
910
|
location: _LabwareLocation,
|
|
@@ -962,70 +1072,23 @@ class GeometryView:
|
|
|
962
1072
|
self._labware.get_grip_height_from_labware_bottom(labware_definition)
|
|
963
1073
|
)
|
|
964
1074
|
location_name: str
|
|
965
|
-
|
|
966
|
-
|
|
1075
|
+
offset = self._get_offset_from_parent_addressable_area(
|
|
1076
|
+
child_definition=labware_definition, parent=location
|
|
1077
|
+
) + self._get_calibrated_module_offset(location)
|
|
967
1078
|
if isinstance(location, DeckSlotLocation):
|
|
968
1079
|
location_name = location.slotName.id
|
|
969
|
-
offset = LabwareOffsetVector(x=0, y=0, z=0)
|
|
970
1080
|
elif isinstance(location, AddressableAreaLocation):
|
|
971
1081
|
location_name = location.addressableAreaName
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
location_name
|
|
976
|
-
)
|
|
977
|
-
)
|
|
978
|
-
return drop_labware_location + Point(z=grip_height_from_labware_bottom)
|
|
979
|
-
# Location should have been pre-validated so this will be a deck/staging area slot
|
|
980
|
-
else:
|
|
981
|
-
offset = LabwareOffsetVector(x=0, y=0, z=0)
|
|
982
|
-
else:
|
|
983
|
-
if isinstance(location, ModuleLocation):
|
|
984
|
-
location_name = self._modules.get_provided_addressable_area(
|
|
985
|
-
location.moduleId
|
|
986
|
-
)
|
|
987
|
-
module_location = location
|
|
988
|
-
else: # OnLabwareLocation
|
|
989
|
-
labware_loc = self._labware.get(location.labwareId).location
|
|
990
|
-
if isinstance(labware_loc, ModuleLocation):
|
|
991
|
-
location_name = self._modules.get_provided_addressable_area(
|
|
992
|
-
labware_loc.moduleId
|
|
993
|
-
)
|
|
994
|
-
module_location = labware_loc
|
|
995
|
-
else:
|
|
996
|
-
location_name = self.get_ancestor_slot_name(location.labwareId).id
|
|
997
|
-
labware_offset = self._get_offset_from_parent(
|
|
998
|
-
child_definition=labware_definition, parent=location
|
|
999
|
-
)
|
|
1000
|
-
# Get the calibrated offset if the on labware location is on top of a module, otherwise return empty one
|
|
1001
|
-
cal_offset = self._get_calibrated_module_offset(location)
|
|
1002
|
-
offset = LabwareOffsetVector(
|
|
1003
|
-
x=labware_offset.x + cal_offset.x,
|
|
1004
|
-
y=labware_offset.y + cal_offset.y,
|
|
1005
|
-
z=labware_offset.z + cal_offset.z,
|
|
1006
|
-
)
|
|
1007
|
-
|
|
1008
|
-
if module_location is not None:
|
|
1009
|
-
# Location center must be determined from the cutout the Module is loaded in
|
|
1010
|
-
position = deck_configuration_provider.get_cutout_position(
|
|
1011
|
-
cutout_id=self._addressable_areas.get_cutout_id_by_deck_slot_name(
|
|
1012
|
-
self._modules.get_location(module_location.moduleId).slotName
|
|
1013
|
-
),
|
|
1014
|
-
deck_definition=self._addressable_areas.deck_definition,
|
|
1015
|
-
)
|
|
1016
|
-
bounding_box = self._addressable_areas.get_addressable_area(
|
|
1017
|
-
location_name
|
|
1018
|
-
).bounding_box
|
|
1019
|
-
location_center = Point(
|
|
1020
|
-
position.x + bounding_box.x / 2,
|
|
1021
|
-
position.y + bounding_box.y / 2,
|
|
1022
|
-
position.z,
|
|
1082
|
+
elif isinstance(location, ModuleLocation):
|
|
1083
|
+
location_name = self._modules.get_provided_addressable_area(
|
|
1084
|
+
location.moduleId
|
|
1023
1085
|
)
|
|
1086
|
+
else: # OnLabwareLocation
|
|
1087
|
+
location_name = self.get_ancestor_addressable_area_name(location.labwareId)
|
|
1024
1088
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
)
|
|
1089
|
+
location_center = self._addressable_areas.get_addressable_area_center(
|
|
1090
|
+
location_name
|
|
1091
|
+
)
|
|
1029
1092
|
|
|
1030
1093
|
return Point(
|
|
1031
1094
|
location_center.x + offset.x,
|
|
@@ -1464,10 +1527,6 @@ class GeometryView:
|
|
|
1464
1527
|
# * The "additional offset" or "user offset", e.g. the `pickUpOffset` and `dropOffset`
|
|
1465
1528
|
# params in the `moveLabware` command.
|
|
1466
1529
|
#
|
|
1467
|
-
# And this *does* take these extra offsets into account:
|
|
1468
|
-
#
|
|
1469
|
-
# * The labware's Labware Position Check offset
|
|
1470
|
-
#
|
|
1471
1530
|
# For robustness, we should combine this with `get_gripper_labware_movement_waypoints()`.
|
|
1472
1531
|
#
|
|
1473
1532
|
# We should also be more explicit about which offsets act to move the gripper paddles
|
|
@@ -1489,23 +1548,17 @@ class GeometryView:
|
|
|
1489
1548
|
return
|
|
1490
1549
|
|
|
1491
1550
|
tip = self._pipettes.get_attached_tip(pipette.id)
|
|
1492
|
-
if tip:
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1551
|
+
if not tip:
|
|
1552
|
+
continue
|
|
1553
|
+
labware_top_z_when_gripped = gripper_homed_position_z + (
|
|
1554
|
+
self._labware.get_dimensions(labware_definition=labware_definition).z
|
|
1555
|
+
- self._labware.get_grip_height_from_labware_bottom(labware_definition)
|
|
1556
|
+
)
|
|
1557
|
+
# TODO(cb, 2024-01-18): Utilizing the nozzle map and labware X coordinates verify if collisions will occur on the X axis (analysis will use hard coded data to measure from the gripper critical point to the pipette mount)
|
|
1558
|
+
if (_PIPETTE_HOMED_POSITION_Z - tip.length) < labware_top_z_when_gripped:
|
|
1559
|
+
raise LabwareMovementNotAllowedError(
|
|
1560
|
+
f"Cannot move labware '{labware_definition.parameters.loadName}' when {int(tip.volume)} µL tips are attached."
|
|
1501
1561
|
)
|
|
1502
|
-
# TODO(cb, 2024-01-18): Utilizing the nozzle map and labware X coordinates verify if collisions will occur on the X axis (analysis will use hard coded data to measure from the gripper critical point to the pipette mount)
|
|
1503
|
-
if (
|
|
1504
|
-
_PIPETTE_HOMED_POSITION_Z - tip.length
|
|
1505
|
-
) < labware_top_z_when_gripped:
|
|
1506
|
-
raise LabwareMovementNotAllowedError(
|
|
1507
|
-
f"Cannot move labware '{labware_definition.parameters.loadName}' when {int(tip.volume)} µL tips are attached."
|
|
1508
|
-
)
|
|
1509
1562
|
return
|
|
1510
1563
|
|
|
1511
1564
|
def _nominal_gripper_offsets_for_location(
|
|
@@ -930,10 +930,39 @@ class ModuleView:
|
|
|
930
930
|
Includes the slot-specific transform. Does not include the child's
|
|
931
931
|
Labware Position Check offset.
|
|
932
932
|
"""
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
933
|
+
base = self.get_nominal_offset_to_child_from_addressable_area(module_id)
|
|
934
|
+
if self.get_deck_supports_module_fixtures():
|
|
935
|
+
module_addressable_area = self.get_provided_addressable_area(module_id)
|
|
936
|
+
module_addressable_area_position = (
|
|
937
|
+
addressable_areas.get_addressable_area_offsets_from_cutout(
|
|
938
|
+
module_addressable_area
|
|
939
|
+
)
|
|
940
|
+
)
|
|
941
|
+
return base + LabwareOffsetVector(
|
|
942
|
+
x=module_addressable_area_position.x,
|
|
943
|
+
y=module_addressable_area_position.y,
|
|
944
|
+
z=module_addressable_area_position.z,
|
|
945
|
+
)
|
|
946
|
+
else:
|
|
947
|
+
return base
|
|
948
|
+
|
|
949
|
+
def get_nominal_offset_to_child_from_addressable_area(
|
|
950
|
+
self, module_id: str
|
|
951
|
+
) -> LabwareOffsetVector:
|
|
952
|
+
"""Get the position offset for a child of this module from the nearest AA.
|
|
953
|
+
|
|
954
|
+
On the Flex, this is always (0, 0, 0); on the OT-2, since modules load on top
|
|
955
|
+
of addressable areas rather than providing addressable areas, the offset is
|
|
956
|
+
the labwareOffset from the module definition, rotated by the module's
|
|
957
|
+
slotTransform if appropriate.
|
|
958
|
+
"""
|
|
959
|
+
if self.get_deck_supports_module_fixtures():
|
|
960
|
+
return LabwareOffsetVector(
|
|
961
|
+
x=0,
|
|
962
|
+
y=0,
|
|
963
|
+
z=0,
|
|
964
|
+
)
|
|
965
|
+
else:
|
|
937
966
|
definition = self.get_definition(module_id)
|
|
938
967
|
slot = self.get_location(module_id).slotName.id
|
|
939
968
|
|
|
@@ -968,18 +997,6 @@ class ModuleView:
|
|
|
968
997
|
y=xformed[1],
|
|
969
998
|
z=xformed[2],
|
|
970
999
|
)
|
|
971
|
-
else:
|
|
972
|
-
module_addressable_area = self.get_provided_addressable_area(module_id)
|
|
973
|
-
module_addressable_area_position = (
|
|
974
|
-
addressable_areas.get_addressable_area_offsets_from_cutout(
|
|
975
|
-
module_addressable_area
|
|
976
|
-
)
|
|
977
|
-
)
|
|
978
|
-
return LabwareOffsetVector(
|
|
979
|
-
x=module_addressable_area_position.x,
|
|
980
|
-
y=module_addressable_area_position.y,
|
|
981
|
-
z=module_addressable_area_position.z,
|
|
982
|
-
)
|
|
983
1000
|
|
|
984
1001
|
def get_module_calibration_offset(
|
|
985
1002
|
self, module_id: str
|
|
@@ -253,6 +253,38 @@ class ModuleOffsetVector(BaseModel):
|
|
|
253
253
|
y: float
|
|
254
254
|
z: float
|
|
255
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
|
+
|
|
256
288
|
|
|
257
289
|
@dataclass
|
|
258
290
|
class ModuleOffsetData:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: opentrons
|
|
3
|
-
Version: 8.4.
|
|
3
|
+
Version: 8.4.0a8
|
|
4
4
|
Summary: The Opentrons API is a simple framework designed to make writing automated biology lab protocols easy.
|
|
5
5
|
Author: Opentrons
|
|
6
6
|
Author-email: engineering@opentrons.com
|
|
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
21
21
|
Classifier: Topic :: Scientific/Engineering
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
License-File: ../LICENSE
|
|
24
|
-
Requires-Dist: opentrons-shared-data (==8.4.
|
|
24
|
+
Requires-Dist: opentrons-shared-data (==8.4.0a8)
|
|
25
25
|
Requires-Dist: aionotify (==0.3.1)
|
|
26
26
|
Requires-Dist: anyio (<4.0.0,>=3.6.1)
|
|
27
27
|
Requires-Dist: jsonschema (<4.18.0,>=3.0.1)
|
|
@@ -35,9 +35,9 @@ Requires-Dist: pyusb (==1.2.1)
|
|
|
35
35
|
Requires-Dist: packaging (>=21.0)
|
|
36
36
|
Requires-Dist: importlib-metadata (>=1.0) ; python_version < "3.8"
|
|
37
37
|
Provides-Extra: flex-hardware
|
|
38
|
-
Requires-Dist: opentrons-hardware[flex] (==8.4.
|
|
38
|
+
Requires-Dist: opentrons-hardware[flex] (==8.4.0a8) ; extra == 'flex-hardware'
|
|
39
39
|
Provides-Extra: ot2-hardware
|
|
40
|
-
Requires-Dist: opentrons-hardware (==8.4.
|
|
40
|
+
Requires-Dist: opentrons-hardware (==8.4.0a8) ; extra == 'ot2-hardware'
|
|
41
41
|
|
|
42
42
|
.. _Full API Documentation: http://docs.opentrons.com
|
|
43
43
|
|
|
@@ -228,7 +228,7 @@ opentrons/protocol_api/config.py,sha256=r9lyvXjagTX_g3q5FGURPpcz2IA9sSF7Oa_1mKx-
|
|
|
228
228
|
opentrons/protocol_api/create_protocol_context.py,sha256=wwsZje0L__oDnu1Yrihau320_f-ASloR9eL1QCtkOh8,7612
|
|
229
229
|
opentrons/protocol_api/deck.py,sha256=94vFceg1SC1bAGd7TvC1ZpYwnJR-VlzurEZ6jkacYeg,8910
|
|
230
230
|
opentrons/protocol_api/disposal_locations.py,sha256=NRiSGmDR0LnbyEkWSOM-o64uR2fUoB1NWJG7Y7SsJSs,7920
|
|
231
|
-
opentrons/protocol_api/instrument_context.py,sha256
|
|
231
|
+
opentrons/protocol_api/instrument_context.py,sha256=wqQ_un5E_sLjhwwNsp2qF_GTD0lajlrBG68JE7WgbPY,120913
|
|
232
232
|
opentrons/protocol_api/labware.py,sha256=KRt91dOzmCX6l8LQ5Wny7kIk_L0Y69Uzpolp-geE0MY,60458
|
|
233
233
|
opentrons/protocol_api/module_contexts.py,sha256=3tVXj6Q7n-WuTJPU_dvIQLzzGv1P-jsMuDtMVpuhAf8,48291
|
|
234
234
|
opentrons/protocol_api/module_validation_and_errors.py,sha256=XL_m72P8rcvGO2fynY7UzXLcpGuI6X4s0V6Xf735Iyc,1464
|
|
@@ -238,7 +238,7 @@ opentrons/protocol_api/validation.py,sha256=uiVTHyJF3wSh5LLfaIDBTELoMNCAT17E767u
|
|
|
238
238
|
opentrons/protocol_api/core/__init__.py,sha256=-g74o8OtBB0LmmOvwkRvPgrHt7fF7T8FRHDj-x_-Onk,736
|
|
239
239
|
opentrons/protocol_api/core/common.py,sha256=q9ZbfpRdBvB3iDAOCyONtupvkYP5n1hjE-bwqGcwP_U,1172
|
|
240
240
|
opentrons/protocol_api/core/core_map.py,sha256=gq3CIYPxuPvozf8yj8FprqBfs3e4ZJGQ6s0ViPbwV08,1757
|
|
241
|
-
opentrons/protocol_api/core/instrument.py,sha256=
|
|
241
|
+
opentrons/protocol_api/core/instrument.py,sha256=iDYCzLtO5fOpbS4dOneMsYFovYjS-GCirHm3jDZSUq4,13712
|
|
242
242
|
opentrons/protocol_api/core/labware.py,sha256=-ZOjkalikXCV3ptehKCNaWGAdKxIdwne8LRFQW9NAm4,4290
|
|
243
243
|
opentrons/protocol_api/core/module.py,sha256=z2STDyqqxZX3y6UyJVDnajeFXMEn1ie2NRBYHhry_XE,13838
|
|
244
244
|
opentrons/protocol_api/core/protocol.py,sha256=v7v28jfeHSfOf-tqFDW2chGtrEatPiZ1y6YNwHfmtAs,9058
|
|
@@ -248,7 +248,7 @@ opentrons/protocol_api/core/well_grid.py,sha256=BU28DKaBgEU_JdZ6pEzrwNxmuh6TkO4z
|
|
|
248
248
|
opentrons/protocol_api/core/engine/__init__.py,sha256=B_5T7zgkWDb1mXPg4NbT-wBkQaK-WVokMMnJRNu7xiM,582
|
|
249
249
|
opentrons/protocol_api/core/engine/deck_conflict.py,sha256=q3JViIAHDthIqq6ce7h2gxw3CHRfYsm5kkwzuXB-Gnc,12334
|
|
250
250
|
opentrons/protocol_api/core/engine/exceptions.py,sha256=aZgNrmYEeuPZm21nX_KZYtvyjv5h_zPjxxgPkEV7_bw,725
|
|
251
|
-
opentrons/protocol_api/core/engine/instrument.py,sha256=
|
|
251
|
+
opentrons/protocol_api/core/engine/instrument.py,sha256=jh3QIqGYDFMoJIrgZLq-IR2liqEhq5aCQgh5xomW3P8,95884
|
|
252
252
|
opentrons/protocol_api/core/engine/labware.py,sha256=1xvzguNnK7aecFLiJK0gtRrZ5kpwtzLS73HnKvdJ5lc,8413
|
|
253
253
|
opentrons/protocol_api/core/engine/load_labware_params.py,sha256=I4Cb8rqpBhmykQuZE8QRG802APrdCy_TYS88rm_9oGA,7159
|
|
254
254
|
opentrons/protocol_api/core/engine/module_core.py,sha256=MLPgYSRJHUZPZ9rTLvsg3GlpL5b6-Pjk5UBgXCGrL6U,30994
|
|
@@ -263,7 +263,7 @@ opentrons/protocol_api/core/engine/well.py,sha256=o4Qm25AvZwd4ytR3IpK4wH-BwAmzt_
|
|
|
263
263
|
opentrons/protocol_api/core/legacy/__init__.py,sha256=_9jCJNKG3SlS_vljVu8HHkZmtLf4F-f-JHALLF5d5go,401
|
|
264
264
|
opentrons/protocol_api/core/legacy/deck.py,sha256=qHqcGo-Kdkl9L1aOE0pwrm9tsAnwkXbt4rIOr_VEP-s,13955
|
|
265
265
|
opentrons/protocol_api/core/legacy/labware_offset_provider.py,sha256=2DLIby9xmUrwLb2ht8hZbvNTxqPhNzWijd7yCb2cqP8,3783
|
|
266
|
-
opentrons/protocol_api/core/legacy/legacy_instrument_core.py,sha256=
|
|
266
|
+
opentrons/protocol_api/core/legacy/legacy_instrument_core.py,sha256=MMB5t77J8AceBa58Ri2NBA9jUfibEFr8IwkWpacg2BM,26508
|
|
267
267
|
opentrons/protocol_api/core/legacy/legacy_labware_core.py,sha256=WQOgtMlq--zv0Ch7mmraYr9rQBT4ie2zHqwgamBq9J8,8606
|
|
268
268
|
opentrons/protocol_api/core/legacy/legacy_module_core.py,sha256=tUhj88NKBMjCmCg6wjh1e2HX4d5hxjh8ZeJiYXaTaGY,23111
|
|
269
269
|
opentrons/protocol_api/core/legacy/legacy_protocol_core.py,sha256=ZIFC7W6YA61oWWkq5xYGTcI_2S2pmALz16uB1R8HVyQ,23670
|
|
@@ -272,7 +272,7 @@ opentrons/protocol_api/core/legacy/load_info.py,sha256=r-WaH5ZJb3TRCp_zvbMMh0P4B
|
|
|
272
272
|
opentrons/protocol_api/core/legacy/module_geometry.py,sha256=lvWFHZ81-JFw-1VZUW1R3yUIb59xpXT6H3jwlRintRo,21082
|
|
273
273
|
opentrons/protocol_api/core/legacy/well_geometry.py,sha256=n5bEsvYZXXTAqYSAqlXd5t40bUPPrJ2Oj2frBZafQHA,4719
|
|
274
274
|
opentrons/protocol_api/core/legacy_simulator/__init__.py,sha256=m9bLHGDJ6LSYC2WPm8tpOuu0zWSOPIrlybQgjRQBw9k,647
|
|
275
|
-
opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py,sha256=
|
|
275
|
+
opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py,sha256=j_EAItSq1mZ61qcRwacDDsXS9tJzG6rDtX8OQOFynG8,22947
|
|
276
276
|
opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py,sha256=28HrrHzeUfnGKXpZqQ-VM8WbPiadqVhKj2S9y33q6Lo,2910
|
|
277
277
|
opentrons/protocol_engine/__init__.py,sha256=UPSk7MbidkiSH_h4V3yxMvyTePKpRr5DM9-wfkJrlSo,4094
|
|
278
278
|
opentrons/protocol_engine/create_protocol_engine.py,sha256=tfDIsC7_JKlRiCXPB_8tuxRsssU6o0ViRmWbGPtX9QA,7582
|
|
@@ -314,7 +314,7 @@ opentrons/protocol_engine/commands/get_tip_presence.py,sha256=vK80XN5qCzK44SOSxH
|
|
|
314
314
|
opentrons/protocol_engine/commands/hash_command_params.py,sha256=obWy4TbVH97SyhNqrSD6iP1wgZ20JoaH1rilZCjXxIs,1530
|
|
315
315
|
opentrons/protocol_engine/commands/home.py,sha256=g77hewv-puMxEHFy0PPnl8-Nkbb7K-2qk36HbWG_Nik,3326
|
|
316
316
|
opentrons/protocol_engine/commands/labware_handling_common.py,sha256=WtkdGIjQ5GBiBWsenyLyPLkSn6phgoesfWxCFTmG1AU,1074
|
|
317
|
-
opentrons/protocol_engine/commands/liquid_probe.py,sha256=
|
|
317
|
+
opentrons/protocol_engine/commands/liquid_probe.py,sha256=wjD-a_xUasEAQSfigexcIJ0FkjhEejlFUh6hpm-Y-JA,15899
|
|
318
318
|
opentrons/protocol_engine/commands/load_labware.py,sha256=p02iOEbnYtq5gklOKTF2RNmYLVR4Ak7lnEUpSZjaHYc,8625
|
|
319
319
|
opentrons/protocol_engine/commands/load_lid.py,sha256=8zRWBfdAQHSULLtjzYPEflkXC_rSSLZML9vJ4TJjxoQ,5484
|
|
320
320
|
opentrons/protocol_engine/commands/load_lid_stack.py,sha256=WgSBr9bd4rRwv6yYztYuz-mIHMByPom6G0Vzo4znpAY,10572
|
|
@@ -336,11 +336,11 @@ opentrons/protocol_engine/commands/pressure_dispense.py,sha256=mGCJDFKwy6MPHg-AO
|
|
|
336
336
|
opentrons/protocol_engine/commands/reload_labware.py,sha256=eB1X7M9rHso1qc0beBTVHm5SHbjS6IODsIDj9RhR3mI,2910
|
|
337
337
|
opentrons/protocol_engine/commands/retract_axis.py,sha256=3h0eb6O3fjrCBY89q9tnjDFUGQXN9qafURxvXGcmCm4,2889
|
|
338
338
|
opentrons/protocol_engine/commands/save_position.py,sha256=koxPh6t8s7Cl1vjPt9e6raZz5_rQtXsg_IGdWqAPzPI,3395
|
|
339
|
-
opentrons/protocol_engine/commands/seal_pipette_to_tip.py,sha256=
|
|
339
|
+
opentrons/protocol_engine/commands/seal_pipette_to_tip.py,sha256=xGCcoYbkSwRSPsuZm4idK5UQgdaAvVDtB3_JKwZ8Wj0,12290
|
|
340
340
|
opentrons/protocol_engine/commands/set_rail_lights.py,sha256=QfB-NKw2ktBvSge1jOi9wYVLD19Vj6HiKw22Fsn0aSo,2090
|
|
341
341
|
opentrons/protocol_engine/commands/set_status_bar.py,sha256=LJGFBteL8bD8tG8yMPQir93mWnGYlPy3er00THbp6kk,2834
|
|
342
342
|
opentrons/protocol_engine/commands/touch_tip.py,sha256=620D8mXSKQdjXQonNVztz_ENOqjuHQd_oa-nHFiM2Ls,5713
|
|
343
|
-
opentrons/protocol_engine/commands/unseal_pipette_from_tip.py,sha256=
|
|
343
|
+
opentrons/protocol_engine/commands/unseal_pipette_from_tip.py,sha256=5U-wkUR13CFt3KEK-j2ppT7d7_W8H8tOi1WT3xwJf-I,4768
|
|
344
344
|
opentrons/protocol_engine/commands/verify_tip_presence.py,sha256=UUwUWdlryfh-mU8IoHUZkoy67KxrqXTFygeu1bsavhc,3136
|
|
345
345
|
opentrons/protocol_engine/commands/wait_for_duration.py,sha256=G-Lmo97BoqW8KA-cZDGQkqUmEE7lrLdw5j-2_LBF5gg,2396
|
|
346
346
|
opentrons/protocol_engine/commands/wait_for_resume.py,sha256=IE_I7fqoKBrlBumaCp5Tm5ihyA6i5VAzG25xdVdRnVw,2372
|
|
@@ -404,9 +404,9 @@ opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py,sha256=Ze5hLslsX
|
|
|
404
404
|
opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py,sha256=mcIPhcQvVCUL_wfb2-JPrCvIFTXMVD93VeJb4H1LmhM,7873
|
|
405
405
|
opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py,sha256=9Sjx92JZhi-tRY1P77M--jJp4JzIGESXUakIpstESwQ,2461
|
|
406
406
|
opentrons/protocol_engine/commands/unsafe/update_position_estimators.py,sha256=xLe3u3rYu1eOvWxDtA2xsvNy7H6TVtljqo-78nOtFLI,2994
|
|
407
|
-
opentrons/protocol_engine/errors/__init__.py,sha256=
|
|
407
|
+
opentrons/protocol_engine/errors/__init__.py,sha256=mqgb4cg9dAbi9YnKIUpbacX6lZiGNyWwEWKjpAen5YQ,6020
|
|
408
408
|
opentrons/protocol_engine/errors/error_occurrence.py,sha256=ODyXHxVO4iXDxpcLaC3uO7ocTOOGPqWwcC1uaiytv0c,7846
|
|
409
|
-
opentrons/protocol_engine/errors/exceptions.py,sha256=
|
|
409
|
+
opentrons/protocol_engine/errors/exceptions.py,sha256=z45LKW0FzT7uNc6o9Y8-lkdPCuY6ChkSsbtsZsqMgrU,45610
|
|
410
410
|
opentrons/protocol_engine/execution/__init__.py,sha256=X8qTYYOc1v84JIDM1xYpIo3VG_BPnsrfl2jm9UUQGwQ,1384
|
|
411
411
|
opentrons/protocol_engine/execution/command_executor.py,sha256=SxE6W9_8HgiCLiPu6Q8hJr2HKsO1Ta-V1PdmFDxa7rQ,8208
|
|
412
412
|
opentrons/protocol_engine/execution/create_queue_worker.py,sha256=6hMuOqbqwfMn63idsrAgro0NJZoyX4VVH7AV3le2EWM,3372
|
|
@@ -418,7 +418,7 @@ opentrons/protocol_engine/execution/hardware_stopper.py,sha256=wlIl7U3gvnOiCvwri
|
|
|
418
418
|
opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py,sha256=BSFLzSSeELAYZCrCUfJZx5DdlrwU06Ur92TYd0T-hzM,9084
|
|
419
419
|
opentrons/protocol_engine/execution/labware_movement.py,sha256=XYVcxZOQ6_udpxcpwkIJpVD8-lgWLhizJAcRD9BclIo,12247
|
|
420
420
|
opentrons/protocol_engine/execution/movement.py,sha256=AWcj7xlrOh3QrvoaH0sZO63yrPCEc7VE8hKfJNxxtP0,12527
|
|
421
|
-
opentrons/protocol_engine/execution/pipetting.py,sha256=
|
|
421
|
+
opentrons/protocol_engine/execution/pipetting.py,sha256=cnJYbLiJ2QD1xziD8dkRm0mZG3xOk00klW8Ff8rgSG4,22199
|
|
422
422
|
opentrons/protocol_engine/execution/queue_worker.py,sha256=riVVywKIOQ3Lx-woFuuSqqBtfeKFt23nCUnsk7gSVoI,2860
|
|
423
423
|
opentrons/protocol_engine/execution/rail_lights.py,sha256=eiJT6oI_kFk7rFuFkZzISZiLNnpf7Kkh86Kyk9wQ_Jo,590
|
|
424
424
|
opentrons/protocol_engine/execution/run_control.py,sha256=ksvI2zkguC4G3lR3HJgAF8uY1PNcaRfi7UOYu-oIZgo,1144
|
|
@@ -450,11 +450,11 @@ opentrons/protocol_engine/state/config.py,sha256=7jSGxC6Vqj1eA8fqZ2I3zjlxVXg8pxv
|
|
|
450
450
|
opentrons/protocol_engine/state/files.py,sha256=w8xxxg8HY0RqKKEGSfHWfrjV54Gb02O3dwtisJ-9j8E,1753
|
|
451
451
|
opentrons/protocol_engine/state/fluid_stack.py,sha256=uwkf0qYk1UX5iU52xmk-e3yLPK8OG-TtMCcBqrkVFpM,5932
|
|
452
452
|
opentrons/protocol_engine/state/frustum_helpers.py,sha256=uRBLLR75Z_PnfVd-U7gPF3NeOALR3TgLNCojgxB4z0o,17343
|
|
453
|
-
opentrons/protocol_engine/state/geometry.py,sha256=
|
|
453
|
+
opentrons/protocol_engine/state/geometry.py,sha256=REIucYpouMOUXpr3450ExaiNapnb-aZEzSl_a-95rWU,100878
|
|
454
454
|
opentrons/protocol_engine/state/labware.py,sha256=rehy7R1HIhxx3DTtTHIKxqHoBQJ_1tDhhiculMJeIy8,57556
|
|
455
455
|
opentrons/protocol_engine/state/liquid_classes.py,sha256=u_z75UYdiFAKG0yB3mr1il4T3qaS0Sotq8sL7KLODP8,2990
|
|
456
456
|
opentrons/protocol_engine/state/liquids.py,sha256=NoesktcQdJUjIVmet1uqqJPf-rzbo4SGemXwQC295W0,2338
|
|
457
|
-
opentrons/protocol_engine/state/modules.py,sha256=
|
|
457
|
+
opentrons/protocol_engine/state/modules.py,sha256=U3CUhV0KOz_eKBED5QNEanWq4JICqrzHdTbmV3nDouM,58786
|
|
458
458
|
opentrons/protocol_engine/state/motion.py,sha256=pWt28-vBaO6dz_rtvoliUsGDvls_ML6sRfDOwmD0F7g,15086
|
|
459
459
|
opentrons/protocol_engine/state/pipettes.py,sha256=nqeJWn98S8wSDW-CPJnjEl5hEIkmhZOInmDzn0-kxDM,36921
|
|
460
460
|
opentrons/protocol_engine/state/state.py,sha256=gHmXrlq17kx3sTbizq8gPoJQx_0nazxnooLODvrLY5k,15468
|
|
@@ -487,7 +487,7 @@ opentrons/protocol_engine/types/liquid_class.py,sha256=SF5WS3s38S87efUqawRGSIYqj
|
|
|
487
487
|
opentrons/protocol_engine/types/liquid_handling.py,sha256=Xx1GihrNRJJdJJA5zIwWvIYNydbSXAHjSUAliF18Iu0,319
|
|
488
488
|
opentrons/protocol_engine/types/liquid_level_detection.py,sha256=0Pf9B_w6tTZ110pGbjgZVoigmOIEF0DVuXVHvhRKeNQ,4395
|
|
489
489
|
opentrons/protocol_engine/types/location.py,sha256=qIYBs86RO1ws2aXStmdx0CqEVNF9enlj-ACknf75nSs,5707
|
|
490
|
-
opentrons/protocol_engine/types/module.py,sha256=
|
|
490
|
+
opentrons/protocol_engine/types/module.py,sha256=E2tQVGRBPL9DCbbY8dfC4PQafRz-ws6UJRkF9i-3q9Q,10249
|
|
491
491
|
opentrons/protocol_engine/types/partial_tip_configuration.py,sha256=4RMtHOAX-dgpXWA737tthj_izTBnhKphBcA24LAKmhI,2760
|
|
492
492
|
opentrons/protocol_engine/types/run_time_parameters.py,sha256=5gH4GmGK7e3OkSClftZT6VA4wXELIvEMgpmQ__waceU,4468
|
|
493
493
|
opentrons/protocol_engine/types/tip.py,sha256=qfjnCPG7RAlTGS80SAQB8rGwtFW3yRWYj7DpYy0oDow,389
|
|
@@ -583,9 +583,9 @@ opentrons/util/linal.py,sha256=IlKAP9HkNBBgULeSf4YVwSKHdx9jnCjSr7nvDvlRALg,5753
|
|
|
583
583
|
opentrons/util/logging_config.py,sha256=7et4YYuQdWdq_e50U-8vFS_QyNBRgdnqPGAQJm8qrIo,9954
|
|
584
584
|
opentrons/util/logging_queue_handler.py,sha256=ZsSJwy-oV8DXwpYiZisQ1PbYwmK2cOslD46AcyJ1E4I,2484
|
|
585
585
|
opentrons/util/performance_helpers.py,sha256=ew7H8XD20iS6-2TJAzbQeyzStZkkE6PzHt_Adx3wbZQ,5172
|
|
586
|
-
opentrons-8.4.
|
|
587
|
-
opentrons-8.4.
|
|
588
|
-
opentrons-8.4.
|
|
589
|
-
opentrons-8.4.
|
|
590
|
-
opentrons-8.4.
|
|
591
|
-
opentrons-8.4.
|
|
586
|
+
opentrons-8.4.0a8.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
587
|
+
opentrons-8.4.0a8.dist-info/METADATA,sha256=9ntyEPWku4FwnS7WhzXREh1pQgG-LVLXuLFWUMhRk_A,5084
|
|
588
|
+
opentrons-8.4.0a8.dist-info/WHEEL,sha256=qUzzGenXXuJTzyjFah76kDVqDvnk-YDzY00svnrl84w,109
|
|
589
|
+
opentrons-8.4.0a8.dist-info/entry_points.txt,sha256=fTa6eGCYkvOtv0ov-KVE8LLGetgb35LQLF9x85OWPVw,106
|
|
590
|
+
opentrons-8.4.0a8.dist-info/top_level.txt,sha256=wk6whpbMZdBQpcK0Fg0YVfUGrAgVOFON7oQAhOMGMW8,10
|
|
591
|
+
opentrons-8.4.0a8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|