opentrons 8.6.0a11__py3-none-any.whl → 8.7.0__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/_version.py +2 -2
- opentrons/cli/analyze.py +58 -2
- opentrons/drivers/asyncio/communication/serial_connection.py +8 -5
- opentrons/drivers/flex_stacker/driver.py +6 -1
- opentrons/hardware_control/backends/flex_protocol.py +1 -0
- opentrons/hardware_control/backends/ot3controller.py +25 -13
- opentrons/hardware_control/backends/ot3simulator.py +2 -1
- opentrons/hardware_control/dev_types.py +3 -1
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +1 -0
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +1 -0
- opentrons/hardware_control/ot3api.py +3 -1
- opentrons/hardware_control/protocols/gripper_controller.py +1 -0
- opentrons/protocol_api/core/engine/_default_liquid_class_versions.py +56 -0
- opentrons/protocol_api/core/engine/instrument.py +143 -18
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +77 -17
- opentrons/protocol_api/core/engine/protocol.py +53 -7
- opentrons/protocol_api/core/engine/transfer_components_executor.py +36 -20
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +1 -1
- opentrons/protocol_api/core/protocol.py +1 -1
- opentrons/protocol_api/labware.py +36 -2
- opentrons/protocol_api/module_contexts.py +146 -14
- opentrons/protocol_api/protocol_context.py +162 -12
- opentrons/protocol_api/validation.py +4 -0
- opentrons/protocol_engine/commands/command_unions.py +2 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +13 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +20 -2
- opentrons/protocol_engine/execution/labware_movement.py +14 -12
- opentrons/protocol_engine/resources/pipette_data_provider.py +3 -0
- opentrons/protocol_engine/state/geometry.py +33 -5
- opentrons/protocol_engine/state/labware.py +66 -0
- opentrons/protocol_engine/state/modules.py +6 -0
- opentrons/protocol_engine/state/pipettes.py +12 -3
- opentrons/protocol_engine/types/__init__.py +2 -0
- opentrons/protocol_engine/types/labware.py +9 -0
- opentrons/protocols/api_support/definitions.py +1 -1
- {opentrons-8.6.0a11.dist-info → opentrons-8.7.0.dist-info}/METADATA +4 -4
- {opentrons-8.6.0a11.dist-info → opentrons-8.7.0.dist-info}/RECORD +40 -39
- {opentrons-8.6.0a11.dist-info → opentrons-8.7.0.dist-info}/WHEEL +0 -0
- {opentrons-8.6.0a11.dist-info → opentrons-8.7.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.6.0a11.dist-info → opentrons-8.7.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -10,6 +10,7 @@ from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
|
10
10
|
from opentrons_shared_data.errors.exceptions import (
|
|
11
11
|
FlexStackerStallError,
|
|
12
12
|
FlexStackerShuttleMissingError,
|
|
13
|
+
FlexStackerShuttleLabwareError,
|
|
13
14
|
)
|
|
14
15
|
|
|
15
16
|
from ..command import (
|
|
@@ -22,6 +23,7 @@ from ..command import (
|
|
|
22
23
|
from ..flex_stacker.common import (
|
|
23
24
|
FlexStackerStallOrCollisionError,
|
|
24
25
|
FlexStackerShuttleError,
|
|
26
|
+
FlexStackerLabwareStoreError,
|
|
25
27
|
labware_locations_for_group,
|
|
26
28
|
labware_location_base_sequence,
|
|
27
29
|
primary_location_sequence,
|
|
@@ -115,7 +117,8 @@ class StoreResult(BaseModel):
|
|
|
115
117
|
_ExecuteReturn = Union[
|
|
116
118
|
SuccessData[StoreResult],
|
|
117
119
|
DefinedErrorData[FlexStackerStallOrCollisionError]
|
|
118
|
-
| DefinedErrorData[FlexStackerShuttleError]
|
|
120
|
+
| DefinedErrorData[FlexStackerShuttleError]
|
|
121
|
+
| DefinedErrorData[FlexStackerLabwareStoreError],
|
|
119
122
|
]
|
|
120
123
|
|
|
121
124
|
|
|
@@ -180,7 +183,7 @@ class StoreImpl(AbstractCommandImpl[StoreParams, _ExecuteReturn]):
|
|
|
180
183
|
)
|
|
181
184
|
return labware_ids[0], None, lid_id
|
|
182
185
|
|
|
183
|
-
async def execute(self, params: StoreParams) -> _ExecuteReturn:
|
|
186
|
+
async def execute(self, params: StoreParams) -> _ExecuteReturn: # noqa: C901
|
|
184
187
|
"""Execute the labware storage command."""
|
|
185
188
|
stacker_state = self._state_view.modules.get_flex_stacker_substate(
|
|
186
189
|
params.moduleId
|
|
@@ -250,6 +253,21 @@ class StoreImpl(AbstractCommandImpl[StoreParams, _ExecuteReturn]):
|
|
|
250
253
|
errorInfo={"labwareId": primary_id},
|
|
251
254
|
),
|
|
252
255
|
)
|
|
256
|
+
except FlexStackerShuttleLabwareError as e:
|
|
257
|
+
return DefinedErrorData(
|
|
258
|
+
public=FlexStackerLabwareStoreError(
|
|
259
|
+
id=self._model_utils.generate_id(),
|
|
260
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
261
|
+
wrappedErrors=[
|
|
262
|
+
ErrorOccurrence.from_failed(
|
|
263
|
+
id=self._model_utils.generate_id(),
|
|
264
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
265
|
+
error=e,
|
|
266
|
+
)
|
|
267
|
+
],
|
|
268
|
+
errorInfo={"labwareId": primary_id},
|
|
269
|
+
),
|
|
270
|
+
)
|
|
253
271
|
|
|
254
272
|
id_list = [
|
|
255
273
|
id for id in (primary_id, maybe_adapter_id, maybe_lid_id) if id is not None
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Optional, TYPE_CHECKING, overload
|
|
6
6
|
|
|
7
|
-
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
7
|
+
from opentrons_shared_data.labware.labware_definition import LabwareDefinition, Quirks
|
|
8
8
|
|
|
9
9
|
from opentrons.types import Point
|
|
10
10
|
|
|
@@ -234,23 +234,25 @@ class LabwareMovementHandler:
|
|
|
234
234
|
# we only want to check position after the gripper has opened and
|
|
235
235
|
# should be holding labware
|
|
236
236
|
if holding_labware:
|
|
237
|
-
|
|
238
|
-
labware_definition=labware_definition
|
|
239
|
-
)
|
|
240
|
-
well_bbox = self._state_store.labware.get_well_bbox(
|
|
237
|
+
grip_specs = self._state_store.labware.get_gripper_width_specs(
|
|
241
238
|
labware_definition=labware_definition
|
|
242
239
|
)
|
|
240
|
+
|
|
241
|
+
disable_geometry_grip_check = False
|
|
242
|
+
if labware_definition.parameters.quirks is not None:
|
|
243
|
+
disable_geometry_grip_check = (
|
|
244
|
+
Quirks.disableGeometryBasedGripCheck.value
|
|
245
|
+
in labware_definition.parameters.quirks
|
|
246
|
+
)
|
|
247
|
+
|
|
243
248
|
# todo(mm, 2024-09-26): This currently raises a lower-level 2015 FailedGripperPickupError.
|
|
244
249
|
# Convert this to a higher-level 3001 LabwareDroppedError or 3002 LabwareNotPickedUpError,
|
|
245
250
|
# depending on what waypoint we're at, to propagate a more specific error code to users.
|
|
246
251
|
ot3api.raise_error_if_gripper_pickup_failed(
|
|
247
|
-
expected_grip_width=
|
|
248
|
-
grip_width_uncertainty_wider=
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
grip_width_uncertainty_narrower=abs(
|
|
252
|
-
min(well_bbox.y - labware_bbox.y, 0)
|
|
253
|
-
),
|
|
252
|
+
expected_grip_width=grip_specs.targetY,
|
|
253
|
+
grip_width_uncertainty_wider=grip_specs.uncertaintyWider,
|
|
254
|
+
grip_width_uncertainty_narrower=grip_specs.uncertaintyNarrower,
|
|
255
|
+
disable_geometry_grip_check=disable_geometry_grip_check,
|
|
254
256
|
)
|
|
255
257
|
await ot3api.move_to(
|
|
256
258
|
mount=gripper_mount, abs_position=waypoint_data.position
|
|
@@ -70,6 +70,7 @@ class LoadedStaticPipetteData:
|
|
|
70
70
|
plunger_positions: Dict[str, float]
|
|
71
71
|
shaft_ul_per_mm: float
|
|
72
72
|
available_sensors: pipette_definition.AvailableSensorDefinition
|
|
73
|
+
volume_mode: pip_types.LiquidClasses # pip_types Liquid Classes refers to volume modes
|
|
73
74
|
|
|
74
75
|
|
|
75
76
|
class VirtualPipetteDataProvider:
|
|
@@ -298,6 +299,7 @@ class VirtualPipetteDataProvider:
|
|
|
298
299
|
shaft_ul_per_mm=config.shaft_ul_per_mm,
|
|
299
300
|
available_sensors=config.available_sensors
|
|
300
301
|
or pipette_definition.AvailableSensorDefinition(sensors=[]),
|
|
302
|
+
volume_mode=liquid_class,
|
|
301
303
|
)
|
|
302
304
|
|
|
303
305
|
def get_virtual_pipette_static_config(
|
|
@@ -353,6 +355,7 @@ def get_pipette_static_config(
|
|
|
353
355
|
plunger_positions=pipette_dict["plunger_positions"],
|
|
354
356
|
shaft_ul_per_mm=pipette_dict["shaft_ul_per_mm"],
|
|
355
357
|
available_sensors=available_sensors,
|
|
358
|
+
volume_mode=pipette_dict["volume_mode"],
|
|
356
359
|
)
|
|
357
360
|
|
|
358
361
|
|
|
@@ -274,12 +274,20 @@ class GeometryView:
|
|
|
274
274
|
try:
|
|
275
275
|
labware_id = self._labware.get_id_by_module(module_id=module_id)
|
|
276
276
|
except LabwareNotLoadedOnModuleError:
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
277
|
+
# For the time being we will ignore column 4 modules in this check to avoid conflating results
|
|
278
|
+
if self._modules.is_column_4_module(slot_item.model) is False:
|
|
279
|
+
return self._modules.get_module_highest_z(
|
|
280
|
+
module_id=module_id,
|
|
281
|
+
addressable_areas=self._addressable_areas,
|
|
282
|
+
)
|
|
281
283
|
else:
|
|
282
|
-
|
|
284
|
+
# For the time being we will ignore column 4 modules in this check to avoid conflating results
|
|
285
|
+
if self._modules.is_column_4_module(slot_item.model) is False:
|
|
286
|
+
return self.get_highest_z_of_labware_stack(labware_id)
|
|
287
|
+
# todo (cb, 2025-09-15): For now we skip column 4 modules and handle them seperately in
|
|
288
|
+
# get_highest_z_of_column_4_module, so this will return 0. In the future we may want to consolidate
|
|
289
|
+
# this to make it more apparently at this point in the query process.
|
|
290
|
+
return 0
|
|
283
291
|
elif isinstance(slot_item, LoadedLabware):
|
|
284
292
|
# get stacked heights of all labware in the slot
|
|
285
293
|
return self.get_highest_z_of_labware_stack(slot_item.id)
|
|
@@ -301,6 +309,26 @@ class GeometryView:
|
|
|
301
309
|
return self.get_labware_highest_z(labware_id)
|
|
302
310
|
return self.get_highest_z_of_labware_stack(stacked_labware_id)
|
|
303
311
|
|
|
312
|
+
def get_highest_z_of_column_4_module(self, module: LoadedModule) -> float:
|
|
313
|
+
"""Get the highest Z-point of the topmost labware in the stack of labware on the given column 4 module.
|
|
314
|
+
|
|
315
|
+
If there is no labware on the given module, returns highest z of the module.
|
|
316
|
+
"""
|
|
317
|
+
if self._modules.is_column_4_module(module.model):
|
|
318
|
+
try:
|
|
319
|
+
labware_id = self._labware.get_id_by_module(module_id=module.id)
|
|
320
|
+
except LabwareNotLoadedOnModuleError:
|
|
321
|
+
return self._modules.get_module_highest_z(
|
|
322
|
+
module_id=module.id,
|
|
323
|
+
addressable_areas=self._addressable_areas,
|
|
324
|
+
)
|
|
325
|
+
else:
|
|
326
|
+
return self.get_highest_z_of_labware_stack(labware_id)
|
|
327
|
+
else:
|
|
328
|
+
raise ValueError(
|
|
329
|
+
"Module must be a Column 4 Module to determine maximum z height."
|
|
330
|
+
)
|
|
331
|
+
|
|
304
332
|
def get_min_travel_z(
|
|
305
333
|
self,
|
|
306
334
|
pipette_id: str,
|
|
@@ -46,6 +46,7 @@ from ..types import (
|
|
|
46
46
|
AddressableAreaLocation,
|
|
47
47
|
NonStackedLocation,
|
|
48
48
|
Dimensions,
|
|
49
|
+
GripSpecs,
|
|
49
50
|
LabwareOffset,
|
|
50
51
|
LabwareOffsetVector,
|
|
51
52
|
LabwareOffsetLocationSequence,
|
|
@@ -1430,3 +1431,68 @@ class LabwareView:
|
|
|
1430
1431
|
):
|
|
1431
1432
|
return Dimensions(0, 0, 0)
|
|
1432
1433
|
return Dimensions(max_x - min_x, max_y - min_y, max_z)
|
|
1434
|
+
|
|
1435
|
+
def _gripper_uncertainty_narrower(
|
|
1436
|
+
self, labware_bbox: Dimensions, well_bbox: Dimensions, target_grip_width: float
|
|
1437
|
+
) -> float:
|
|
1438
|
+
"""Most narrower the gripper can be than the target while still likely gripping successfully.
|
|
1439
|
+
|
|
1440
|
+
This number can't just be the 0, because that is not going to be accurate if the labware is
|
|
1441
|
+
skirted - the dimensions are a full bounding box including the skirt, and the labware is
|
|
1442
|
+
narrower than that at the point where it is gripped. The general heuristic is that we can't
|
|
1443
|
+
get to the wells; but some labware don't have wells, so we need alternate values.
|
|
1444
|
+
|
|
1445
|
+
The number will be interpreted relative to the target width, which is (for now) the labware
|
|
1446
|
+
outer bounding box.
|
|
1447
|
+
|
|
1448
|
+
TODO: This should be a number looked up from the definition.
|
|
1449
|
+
"""
|
|
1450
|
+
if well_bbox.y == 0:
|
|
1451
|
+
# This labware has no wells; use a fixed minimum
|
|
1452
|
+
return 5
|
|
1453
|
+
if well_bbox.y > labware_bbox.y:
|
|
1454
|
+
# This labware has a very odd definition with wells outside its dimensions.
|
|
1455
|
+
# Return the smaller value.
|
|
1456
|
+
return 0
|
|
1457
|
+
# An ok heuristic for successful grip is if we don't get all the way to the wells.
|
|
1458
|
+
return target_grip_width - well_bbox.y
|
|
1459
|
+
|
|
1460
|
+
def _gripper_uncertainty_wider(
|
|
1461
|
+
self, labware_bbox: Dimensions, well_bbox: Dimensions, target_grip_width: float
|
|
1462
|
+
) -> float:
|
|
1463
|
+
"""Most wider the gripper can be than the target while still likely gripping successfully.
|
|
1464
|
+
|
|
1465
|
+
This can be a lot closer to 0, since the bounding box of the labware will certainly be the
|
|
1466
|
+
widest point (if it's defined without error), but since there might be error in the
|
|
1467
|
+
definition we allow some slop.
|
|
1468
|
+
|
|
1469
|
+
The number will be interpreted relative to the target width, which is (for now) the labware
|
|
1470
|
+
outer bounding box.
|
|
1471
|
+
|
|
1472
|
+
TODO: This should be a number looked up from the definition.
|
|
1473
|
+
"""
|
|
1474
|
+
# This will be 0 unless the wells are wider than the labware
|
|
1475
|
+
return max(well_bbox.y - target_grip_width, 0)
|
|
1476
|
+
|
|
1477
|
+
def get_gripper_width_specs(
|
|
1478
|
+
self, labware_definition: LabwareDefinition
|
|
1479
|
+
) -> GripSpecs:
|
|
1480
|
+
"""Get the target and bounds for a successful grip of this labware."""
|
|
1481
|
+
outer_bounds = self.get_dimensions(labware_definition=labware_definition)
|
|
1482
|
+
well_bounds = self.get_well_bbox(labware_definition=labware_definition)
|
|
1483
|
+
narrower = self._gripper_uncertainty_narrower(
|
|
1484
|
+
labware_bbox=outer_bounds,
|
|
1485
|
+
well_bbox=well_bounds,
|
|
1486
|
+
target_grip_width=outer_bounds.y,
|
|
1487
|
+
)
|
|
1488
|
+
wider = self._gripper_uncertainty_wider(
|
|
1489
|
+
labware_bbox=outer_bounds,
|
|
1490
|
+
well_bbox=well_bounds,
|
|
1491
|
+
target_grip_width=outer_bounds.y,
|
|
1492
|
+
)
|
|
1493
|
+
return GripSpecs(
|
|
1494
|
+
# TODO: This should be a number looked up from the definition.
|
|
1495
|
+
targetY=outer_bounds.y,
|
|
1496
|
+
uncertaintyNarrower=narrower,
|
|
1497
|
+
uncertaintyWider=wider,
|
|
1498
|
+
)
|
|
@@ -1330,6 +1330,12 @@ class ModuleView:
|
|
|
1330
1330
|
f"Module {module.model} is already present at {location}."
|
|
1331
1331
|
)
|
|
1332
1332
|
|
|
1333
|
+
def is_column_4_module(self, model: ModuleModel) -> bool:
|
|
1334
|
+
"""Determine whether or not a module is a Column 4 Module."""
|
|
1335
|
+
if model in _COLUMN_4_MODULES:
|
|
1336
|
+
return True
|
|
1337
|
+
return False
|
|
1338
|
+
|
|
1333
1339
|
def get_default_gripper_offsets(
|
|
1334
1340
|
self, module_id: str
|
|
1335
1341
|
) -> Optional[LabwareMovementOffsetData]:
|
|
@@ -17,7 +17,10 @@ from typing_extensions import assert_never
|
|
|
17
17
|
|
|
18
18
|
from opentrons_shared_data.pipette import pipette_definition
|
|
19
19
|
from opentrons_shared_data.pipette.ul_per_mm import calculate_ul_per_mm
|
|
20
|
-
from opentrons_shared_data.pipette.types import
|
|
20
|
+
from opentrons_shared_data.pipette.types import (
|
|
21
|
+
UlPerMmAction,
|
|
22
|
+
LiquidClasses as VolumeModes,
|
|
23
|
+
)
|
|
21
24
|
|
|
22
25
|
from opentrons.config.defaults_ot2 import Z_RETRACT_DISTANCE
|
|
23
26
|
from opentrons.hardware_control.dev_types import PipetteDict
|
|
@@ -107,6 +110,7 @@ class StaticPipetteConfig:
|
|
|
107
110
|
plunger_positions: Dict[str, float]
|
|
108
111
|
shaft_ul_per_mm: float
|
|
109
112
|
available_sensors: pipette_definition.AvailableSensorDefinition
|
|
113
|
+
volume_mode: VolumeModes
|
|
110
114
|
|
|
111
115
|
|
|
112
116
|
@dataclasses.dataclass
|
|
@@ -212,7 +216,7 @@ class PipetteStore(HasState[PipetteState], HandlesActions):
|
|
|
212
216
|
# we identify tip classes - looking things up by volume is not enough.
|
|
213
217
|
tip_configuration = list(
|
|
214
218
|
static_config.tip_configuration_lookup_table.values()
|
|
215
|
-
)[
|
|
219
|
+
)[-1]
|
|
216
220
|
self._state.flow_rates_by_id[pipette_id] = FlowRates(
|
|
217
221
|
default_blow_out=tip_configuration.default_blowout_flowrate.values_by_api_level,
|
|
218
222
|
default_aspirate=tip_configuration.default_aspirate_flowrate.values_by_api_level,
|
|
@@ -230,7 +234,7 @@ class PipetteStore(HasState[PipetteState], HandlesActions):
|
|
|
230
234
|
# TODO(seth,9/11/2023): bad way to do defaulting, see above.
|
|
231
235
|
tip_configuration = list(
|
|
232
236
|
static_config.tip_configuration_lookup_table.values()
|
|
233
|
-
)[
|
|
237
|
+
)[-1]
|
|
234
238
|
self._state.flow_rates_by_id[pipette_id] = FlowRates(
|
|
235
239
|
default_blow_out=tip_configuration.default_blowout_flowrate.values_by_api_level,
|
|
236
240
|
default_aspirate=tip_configuration.default_aspirate_flowrate.values_by_api_level,
|
|
@@ -313,6 +317,7 @@ class PipetteStore(HasState[PipetteState], HandlesActions):
|
|
|
313
317
|
plunger_positions=config.plunger_positions,
|
|
314
318
|
shaft_ul_per_mm=config.shaft_ul_per_mm,
|
|
315
319
|
available_sensors=config.available_sensors,
|
|
320
|
+
volume_mode=config.volume_mode,
|
|
316
321
|
)
|
|
317
322
|
self._state.flow_rates_by_id[
|
|
318
323
|
state_update.pipette_config.pipette_id
|
|
@@ -867,6 +872,10 @@ class PipetteView:
|
|
|
867
872
|
return False
|
|
868
873
|
return True
|
|
869
874
|
|
|
875
|
+
def get_is_low_volume_mode(self, pipette_id: str) -> bool:
|
|
876
|
+
"""Determine if the pipette is currently in low volume mode."""
|
|
877
|
+
return self.get_config(pipette_id).volume_mode == VolumeModes.lowVolumeDefault
|
|
878
|
+
|
|
870
879
|
def lookup_volume_to_mm_conversion(
|
|
871
880
|
self, pipette_id: str, volume: float, action: str
|
|
872
881
|
) -> float:
|
|
@@ -102,6 +102,7 @@ from .labware import (
|
|
|
102
102
|
LoadedLabware,
|
|
103
103
|
LabwareParentDefinition,
|
|
104
104
|
LabwareWellId,
|
|
105
|
+
GripSpecs,
|
|
105
106
|
)
|
|
106
107
|
from .liquid import HexColor, EmptyLiquidId, LiquidId, Liquid, FluidKind, AspiratedFluid
|
|
107
108
|
from .labware_offset_location import (
|
|
@@ -257,6 +258,7 @@ __all__ = [
|
|
|
257
258
|
"LabwareOffsetVector",
|
|
258
259
|
"LabwareParentDefinition",
|
|
259
260
|
"LabwareWellId",
|
|
261
|
+
"GripSpecs",
|
|
260
262
|
# Liquids
|
|
261
263
|
"HexColor",
|
|
262
264
|
"EmptyLiquidId",
|
|
@@ -23,6 +23,15 @@ from .module import ModuleDefinition
|
|
|
23
23
|
from .deck_configuration import DeckLocationDefinition
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class GripSpecs:
|
|
28
|
+
"""Data for how a labware should be gripped."""
|
|
29
|
+
|
|
30
|
+
uncertaintyWider: float
|
|
31
|
+
uncertaintyNarrower: float
|
|
32
|
+
targetY: float
|
|
33
|
+
|
|
34
|
+
|
|
26
35
|
class OverlapOffset(Vec3f):
|
|
27
36
|
"""Offset representing overlap space of one labware on top of another labware or module."""
|
|
28
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opentrons
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.7.0
|
|
4
4
|
Summary: The Opentrons API is a simple framework designed to make writing automated biology lab protocols easy.
|
|
5
5
|
Project-URL: opentrons.com, https://www.opentrons.com
|
|
6
6
|
Project-URL: Source Code On Github, https://github.com/Opentrons/opentrons/tree/edge/api
|
|
@@ -24,7 +24,7 @@ Requires-Dist: click<9,>=8.0.0
|
|
|
24
24
|
Requires-Dist: importlib-metadata>=1.0; python_version < '3.8'
|
|
25
25
|
Requires-Dist: jsonschema<4.18.0,>=3.0.1
|
|
26
26
|
Requires-Dist: numpy<2,>=1.20.0
|
|
27
|
-
Requires-Dist: opentrons-shared-data==8.
|
|
27
|
+
Requires-Dist: opentrons-shared-data==8.7.0
|
|
28
28
|
Requires-Dist: packaging>=21.0
|
|
29
29
|
Requires-Dist: pydantic-settings<3,>=2
|
|
30
30
|
Requires-Dist: pydantic<3,>=2.0.0
|
|
@@ -32,6 +32,6 @@ Requires-Dist: pyserial>=3.5
|
|
|
32
32
|
Requires-Dist: pyusb==1.2.1
|
|
33
33
|
Requires-Dist: typing-extensions<5,>=4.0.0
|
|
34
34
|
Provides-Extra: flex-hardware
|
|
35
|
-
Requires-Dist: opentrons-hardware[flex]==8.
|
|
35
|
+
Requires-Dist: opentrons-hardware[flex]==8.7.0; extra == 'flex-hardware'
|
|
36
36
|
Provides-Extra: ot2-hardware
|
|
37
|
-
Requires-Dist: opentrons-hardware==8.
|
|
37
|
+
Requires-Dist: opentrons-hardware==8.7.0; extra == 'ot2-hardware'
|