opentrons 8.6.0a10__py3-none-any.whl → 8.6.0a12__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/_version.py +2 -2
- opentrons/cli/analyze.py +58 -2
- opentrons/legacy_commands/module_commands.py +62 -1
- opentrons/legacy_commands/types.py +71 -0
- opentrons/protocol_api/core/engine/transfer_components_executor.py +36 -20
- opentrons/protocol_api/module_contexts.py +5 -0
- opentrons/protocol_runner/legacy_command_mapper.py +4 -0
- {opentrons-8.6.0a10.dist-info → opentrons-8.6.0a12.dist-info}/METADATA +4 -4
- {opentrons-8.6.0a10.dist-info → opentrons-8.6.0a12.dist-info}/RECORD +12 -12
- {opentrons-8.6.0a10.dist-info → opentrons-8.6.0a12.dist-info}/WHEEL +0 -0
- {opentrons-8.6.0a10.dist-info → opentrons-8.6.0a12.dist-info}/entry_points.txt +0 -0
- {opentrons-8.6.0a10.dist-info → opentrons-8.6.0a12.dist-info}/licenses/LICENSE +0 -0
opentrons/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '8.6.
|
|
32
|
-
__version_tuple__ = version_tuple = (8, 6, 0, '
|
|
31
|
+
__version__ = version = '8.6.0a12'
|
|
32
|
+
__version_tuple__ = version_tuple = (8, 6, 0, 'a12')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
opentrons/cli/analyze.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Opentrons analyze CLI."""
|
|
2
|
+
|
|
2
3
|
import click
|
|
3
4
|
|
|
4
5
|
from anyio import run
|
|
@@ -24,7 +25,9 @@ from typing import (
|
|
|
24
25
|
import logging
|
|
25
26
|
import sys
|
|
26
27
|
import json
|
|
28
|
+
import gc
|
|
27
29
|
|
|
30
|
+
from opentrons.protocol_engine import ProtocolEngine
|
|
28
31
|
from opentrons.protocol_engine.types import (
|
|
29
32
|
RunTimeParameter,
|
|
30
33
|
CSVRuntimeParamPaths,
|
|
@@ -94,6 +97,18 @@ class _Output:
|
|
|
94
97
|
help="Return analysis results as JSON, formatted for human eyes. Specify --human-json-output=- to use stdout, but be aware that Python protocols may contain print() which will make the output JSON invalid.",
|
|
95
98
|
type=click.File(mode="wb"),
|
|
96
99
|
)
|
|
100
|
+
@click.option(
|
|
101
|
+
"--leaks",
|
|
102
|
+
help="Fail (via exit code) if the analysis engine has not been garbage collected after analysis is complete.",
|
|
103
|
+
is_flag=True,
|
|
104
|
+
default=False,
|
|
105
|
+
)
|
|
106
|
+
@click.option(
|
|
107
|
+
"--leaks-debug",
|
|
108
|
+
help="Drop into a PDB shell if a leak is detected",
|
|
109
|
+
is_flag=True,
|
|
110
|
+
default=False,
|
|
111
|
+
)
|
|
97
112
|
@click.option(
|
|
98
113
|
"--check",
|
|
99
114
|
help="Fail (via exit code) if the protocol had an error. If not specified, always succeed.",
|
|
@@ -133,6 +148,8 @@ def analyze(
|
|
|
133
148
|
log_output: str,
|
|
134
149
|
log_level: str,
|
|
135
150
|
check: bool,
|
|
151
|
+
leaks: bool,
|
|
152
|
+
leaks_debug: bool,
|
|
136
153
|
) -> int:
|
|
137
154
|
"""Analyze a protocol.
|
|
138
155
|
|
|
@@ -147,7 +164,18 @@ def analyze(
|
|
|
147
164
|
|
|
148
165
|
try:
|
|
149
166
|
with _capture_logs(log_output, log_level):
|
|
150
|
-
sys.exit(
|
|
167
|
+
sys.exit(
|
|
168
|
+
run(
|
|
169
|
+
_analyze,
|
|
170
|
+
files,
|
|
171
|
+
rtp_values,
|
|
172
|
+
rtp_files,
|
|
173
|
+
outputs,
|
|
174
|
+
check,
|
|
175
|
+
leaks or leaks_debug,
|
|
176
|
+
leaks_debug,
|
|
177
|
+
)
|
|
178
|
+
)
|
|
151
179
|
except click.ClickException:
|
|
152
180
|
raise
|
|
153
181
|
except Exception as e:
|
|
@@ -344,12 +372,14 @@ async def _do_analyze(
|
|
|
344
372
|
return await orchestrator.run(deck_configuration=[])
|
|
345
373
|
|
|
346
374
|
|
|
347
|
-
async def _analyze(
|
|
375
|
+
async def _analyze( # noqa: C901
|
|
348
376
|
files_and_dirs: Sequence[Path],
|
|
349
377
|
rtp_values: str,
|
|
350
378
|
rtp_files: str,
|
|
351
379
|
outputs: Sequence[_Output],
|
|
352
380
|
check: bool,
|
|
381
|
+
fail_on_leak: bool,
|
|
382
|
+
debug_on_leak: bool,
|
|
353
383
|
) -> int:
|
|
354
384
|
input_files = _get_input_files(files_and_dirs)
|
|
355
385
|
parsed_rtp_values = _get_runtime_parameter_values(rtp_values)
|
|
@@ -366,6 +396,32 @@ async def _analyze(
|
|
|
366
396
|
analysis = await _do_analyze(protocol_source, parsed_rtp_values, rtp_paths)
|
|
367
397
|
return_code = _get_return_code(analysis)
|
|
368
398
|
|
|
399
|
+
# This ugly code checks to see if an engine remains past garbage collection
|
|
400
|
+
# after analysis is complete.
|
|
401
|
+
# It should be here and open coded to make it a little easier to present
|
|
402
|
+
# the debug option.
|
|
403
|
+
if fail_on_leak or debug_on_leak:
|
|
404
|
+
gc.collect()
|
|
405
|
+
leaked_engine = next(
|
|
406
|
+
(obj for obj in gc.get_objects() if isinstance(obj, ProtocolEngine)), None
|
|
407
|
+
)
|
|
408
|
+
if leaked_engine:
|
|
409
|
+
if fail_on_leak:
|
|
410
|
+
print(
|
|
411
|
+
"A ProtocolEngine instance exists even after garbage collection; "
|
|
412
|
+
"some thing (likely in the protocol) has caused it to be leaked, "
|
|
413
|
+
"likely by reference to the engine or something that refers to the "
|
|
414
|
+
"engine after the run function ends.",
|
|
415
|
+
file=sys.stderr,
|
|
416
|
+
)
|
|
417
|
+
return_code = -2
|
|
418
|
+
if debug_on_leak:
|
|
419
|
+
print(
|
|
420
|
+
"You are now in an interactive PDB (https://docs.python.org/3.10/library/pdb.html) "
|
|
421
|
+
"session; the leaked engine is bound to the variable leaked_engine."
|
|
422
|
+
)
|
|
423
|
+
breakpoint()
|
|
424
|
+
|
|
369
425
|
if not outputs:
|
|
370
426
|
return return_code
|
|
371
427
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import List
|
|
1
|
+
from typing import Any, List
|
|
2
2
|
from math import trunc
|
|
3
3
|
|
|
4
4
|
from opentrons.drivers import utils
|
|
@@ -213,3 +213,64 @@ def heater_shaker_deactivate_heater() -> command_types.HeaterShakerDeactivateHea
|
|
|
213
213
|
"name": command_types.HEATER_SHAKER_DEACTIVATE_HEATER,
|
|
214
214
|
"payload": {"text": text},
|
|
215
215
|
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# FLex Stacker
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def flex_stacker_set_stored_labware(
|
|
222
|
+
self: Any,
|
|
223
|
+
load_name: str,
|
|
224
|
+
namespace: str | None = None,
|
|
225
|
+
version: int | None = None,
|
|
226
|
+
adapter: str | None = None,
|
|
227
|
+
lid: str | None = None,
|
|
228
|
+
count: int | None = None,
|
|
229
|
+
stacking_offset_z: float | None = None,
|
|
230
|
+
) -> command_types.FlexStackerSetStoredLabwareCommand:
|
|
231
|
+
uri = f"{namespace}/{load_name}/{version}"
|
|
232
|
+
text = f"Configuring {self} with {count} labware {uri}, adapter: {adapter}, lid: {lid}, stacking_offset_z: {stacking_offset_z}"
|
|
233
|
+
return {
|
|
234
|
+
"name": command_types.FLEX_STACKER_SET_STORED_LABWARE,
|
|
235
|
+
"payload": {"text": text},
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def flex_stacker_retrieve(
|
|
240
|
+
self: Any,
|
|
241
|
+
) -> command_types.FlexStackerRetrieveCommand:
|
|
242
|
+
text = f"Retrieving labware from {self}"
|
|
243
|
+
return {
|
|
244
|
+
"name": command_types.FLEX_STACKER_RETRIEVE,
|
|
245
|
+
"payload": {"text": text},
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def flex_stacker_store(
|
|
250
|
+
self: Any,
|
|
251
|
+
) -> command_types.FlexStackerStoreCommand:
|
|
252
|
+
text = f"Storing labware to {self}"
|
|
253
|
+
return {
|
|
254
|
+
"name": command_types.FLEX_STACKER_STORE,
|
|
255
|
+
"payload": {"text": text},
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def flex_stacker_empty(
|
|
260
|
+
self: Any,
|
|
261
|
+
) -> command_types.FlexStackerEmptyCommand:
|
|
262
|
+
text = f"Emptying {self}"
|
|
263
|
+
return {
|
|
264
|
+
"name": command_types.FLEX_STACKER_EMPTY,
|
|
265
|
+
"payload": {"text": text},
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def flex_stacker_fill(
|
|
270
|
+
self: Any, count: int | None = None
|
|
271
|
+
) -> command_types.FlexStackerFillCommand:
|
|
272
|
+
text = f"Filling {self} with {count} labware"
|
|
273
|
+
return {
|
|
274
|
+
"name": command_types.FLEX_STACKER_FILL,
|
|
275
|
+
"payload": {"text": text},
|
|
276
|
+
}
|
|
@@ -89,6 +89,12 @@ THERMOCYCLER_SET_LID_TEMP: Final = "command.THERMOCYCLER_SET_LID_TEMP"
|
|
|
89
89
|
THERMOCYCLER_DEACTIVATE_LID: Final = "command.THERMOCYCLER_DEACTIVATE_LID"
|
|
90
90
|
THERMOCYCLER_DEACTIVATE_BLOCK: Final = "command.THERMOCYCLER_DEACTIVATE_BLOCK"
|
|
91
91
|
|
|
92
|
+
FLEX_STACKER_SET_STORED_LABWARE: Final = "command.FLEX_STACKER_SET_STORED_LABWARE"
|
|
93
|
+
FLEX_STACKER_RETRIEVE: Final = "command.FLEX_STACKER_RETRIEVE"
|
|
94
|
+
FLEX_STACKER_STORE: Final = "command.FLEX_STACKER_STORE"
|
|
95
|
+
FLEX_STACKER_EMPTY: Final = "command.FLEX_STACKER_EMPTY"
|
|
96
|
+
FLEX_STACKER_FILL: Final = "command.FLEX_STACKER_FILL"
|
|
97
|
+
|
|
92
98
|
# Robot #
|
|
93
99
|
ROBOT_MOVE_TO: Final = "command.ROBOT_MOVE_TO"
|
|
94
100
|
ROBOT_MOVE_AXES_TO: Final = "command.ROBOT_MOVE_AXES_TO"
|
|
@@ -154,6 +160,9 @@ class ResumeCommand(TypedDict):
|
|
|
154
160
|
payload: ResumeCommandPayload
|
|
155
161
|
|
|
156
162
|
|
|
163
|
+
# Module commands
|
|
164
|
+
|
|
165
|
+
|
|
157
166
|
class HeaterShakerSetTargetTemperaturePayload(TextOnlyPayload):
|
|
158
167
|
pass
|
|
159
168
|
|
|
@@ -371,6 +380,34 @@ class ThermocyclerCloseCommand(TypedDict):
|
|
|
371
380
|
payload: ThermocyclerCloseCommandPayload
|
|
372
381
|
|
|
373
382
|
|
|
383
|
+
class FlexStackerSetStoredLabwareCommand(TypedDict):
|
|
384
|
+
name: Literal["command.FLEX_STACKER_SET_STORED_LABWARE"]
|
|
385
|
+
payload: TextOnlyPayload
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class FlexStackerRetrieveCommand(TypedDict):
|
|
389
|
+
name: Literal["command.FLEX_STACKER_RETRIEVE"]
|
|
390
|
+
payload: TextOnlyPayload
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class FlexStackerStoreCommand(TypedDict):
|
|
394
|
+
name: Literal["command.FLEX_STACKER_STORE"]
|
|
395
|
+
payload: TextOnlyPayload
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
class FlexStackerEmptyCommand(TypedDict):
|
|
399
|
+
name: Literal["command.FLEX_STACKER_EMPTY"]
|
|
400
|
+
payload: TextOnlyPayload
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
class FlexStackerFillCommand(TypedDict):
|
|
404
|
+
name: Literal["command.FLEX_STACKER_FILL"]
|
|
405
|
+
payload: TextOnlyPayload
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
# Module command end
|
|
409
|
+
|
|
410
|
+
|
|
374
411
|
class HomeCommandPayload(TextOnlyPayload):
|
|
375
412
|
axis: str
|
|
376
413
|
|
|
@@ -739,6 +776,12 @@ Command = Union[
|
|
|
739
776
|
RobotMoveAxisRelativeCommand,
|
|
740
777
|
RobotOpenGripperJawCommand,
|
|
741
778
|
RobotCloseGripperJawCommand,
|
|
779
|
+
# Flex Stacker commands
|
|
780
|
+
FlexStackerSetStoredLabwareCommand,
|
|
781
|
+
FlexStackerRetrieveCommand,
|
|
782
|
+
FlexStackerStoreCommand,
|
|
783
|
+
FlexStackerEmptyCommand,
|
|
784
|
+
FlexStackerFillCommand,
|
|
742
785
|
]
|
|
743
786
|
|
|
744
787
|
|
|
@@ -1019,6 +1062,28 @@ class MagdeckEngageMessage(CommandMessageFields, MagdeckEngageCommand):
|
|
|
1019
1062
|
pass
|
|
1020
1063
|
|
|
1021
1064
|
|
|
1065
|
+
class FlexStackerSetStoredLabwareMessage(
|
|
1066
|
+
CommandMessageFields, FlexStackerSetStoredLabwareCommand
|
|
1067
|
+
):
|
|
1068
|
+
pass
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
class FlexStackerRetrieveMessage(CommandMessageFields, FlexStackerRetrieveCommand):
|
|
1072
|
+
pass
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
class FlexStackerStoreMessage(CommandMessageFields, FlexStackerStoreCommand):
|
|
1076
|
+
pass
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
class FlexStackerEmptyMessage(CommandMessageFields, FlexStackerEmptyCommand):
|
|
1080
|
+
pass
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
class FlexStackerFillMessage(CommandMessageFields, FlexStackerFillCommand):
|
|
1084
|
+
pass
|
|
1085
|
+
|
|
1086
|
+
|
|
1022
1087
|
class ResumeMessage(CommandMessageFields, ResumeCommand):
|
|
1023
1088
|
pass
|
|
1024
1089
|
|
|
@@ -1112,4 +1177,10 @@ CommandMessage = Union[
|
|
|
1112
1177
|
RobotMoveAxisRelativeMessage,
|
|
1113
1178
|
RobotOpenGripperJawMessage,
|
|
1114
1179
|
RobotCloseGripperJawMessage,
|
|
1180
|
+
# Flex Stacker Messages
|
|
1181
|
+
FlexStackerSetStoredLabwareMessage,
|
|
1182
|
+
FlexStackerRetrieveMessage,
|
|
1183
|
+
FlexStackerStoreMessage,
|
|
1184
|
+
FlexStackerEmptyMessage,
|
|
1185
|
+
FlexStackerFillMessage,
|
|
1115
1186
|
]
|
|
@@ -5,7 +5,7 @@ import logging
|
|
|
5
5
|
from copy import deepcopy
|
|
6
6
|
from enum import Enum
|
|
7
7
|
from typing import TYPE_CHECKING, Optional, Union, Literal
|
|
8
|
-
from dataclasses import dataclass, field
|
|
8
|
+
from dataclasses import dataclass, field, replace
|
|
9
9
|
|
|
10
10
|
from opentrons_shared_data.liquid_classes.liquid_class_definition import (
|
|
11
11
|
PositionReference,
|
|
@@ -21,7 +21,6 @@ from opentrons.protocol_api._liquid_properties import (
|
|
|
21
21
|
MultiDispenseProperties,
|
|
22
22
|
TouchTipProperties,
|
|
23
23
|
)
|
|
24
|
-
from opentrons.protocol_engine.errors import TouchTipDisabledError
|
|
25
24
|
from opentrons.types import Location, Point, Mount
|
|
26
25
|
from opentrons.protocols.advanced_control.transfers.transfer_liquid_utils import (
|
|
27
26
|
LocationCheckDescriptors,
|
|
@@ -466,7 +465,7 @@ class TransferComponentsExecutor:
|
|
|
466
465
|
2. If blowout is enabled and “destination”
|
|
467
466
|
- Do blow-out (at the retract position)
|
|
468
467
|
- Leave plunger down
|
|
469
|
-
3. Touch-tip
|
|
468
|
+
3. Touch-tip in the destination well.
|
|
470
469
|
4. If not ready-to-aspirate
|
|
471
470
|
- Prepare-to-aspirate (at the retract position)
|
|
472
471
|
5. Air-gap (at the retract position)
|
|
@@ -479,7 +478,7 @@ class TransferComponentsExecutor:
|
|
|
479
478
|
6. If blowout is “source” or “trash”
|
|
480
479
|
- Move to location (top of Well)
|
|
481
480
|
- Do blow-out (top of well)
|
|
482
|
-
- Do touch-tip
|
|
481
|
+
- Do touch-tip AGAIN at the source well (if blowout in a non-trash location)
|
|
483
482
|
- Prepare-to-aspirate (top of well)
|
|
484
483
|
- Do air-gap (top of well)
|
|
485
484
|
7. If drop tip, move to drop tip location, drop tip
|
|
@@ -563,9 +562,9 @@ class TransferComponentsExecutor:
|
|
|
563
562
|
blowout_props.enabled
|
|
564
563
|
and blowout_props.location != BlowoutLocation.DESTINATION
|
|
565
564
|
):
|
|
566
|
-
# TODO: no-op touch tip if touch tip is enabled and blowout is in trash/ reservoir/ any labware with touch-tip disabled
|
|
567
565
|
assert blowout_props.flow_rate is not None
|
|
568
566
|
self._instrument.set_flow_rate(blow_out=blowout_props.flow_rate)
|
|
567
|
+
blowout_touch_tip_props = retract_props.touch_tip
|
|
569
568
|
touch_tip_and_air_gap_location: Union[Location, TrashBin, WasteChute]
|
|
570
569
|
if blowout_props.location == BlowoutLocation.SOURCE:
|
|
571
570
|
if source_location is None or source_well is None:
|
|
@@ -584,6 +583,13 @@ class TransferComponentsExecutor:
|
|
|
584
583
|
source_well.get_top(0), labware=source_location.labware
|
|
585
584
|
)
|
|
586
585
|
touch_tip_and_air_gap_well = source_well
|
|
586
|
+
# Skip touch tip if blowing out at the SOURCE and it's untouchable:
|
|
587
|
+
if (
|
|
588
|
+
"touchTipDisabled"
|
|
589
|
+
in source_location.labware.quirks_from_any_parent()
|
|
590
|
+
):
|
|
591
|
+
blowout_touch_tip_props = replace(blowout_touch_tip_props)
|
|
592
|
+
blowout_touch_tip_props.enabled = False
|
|
587
593
|
else:
|
|
588
594
|
self._instrument.blow_out(
|
|
589
595
|
location=trash_location,
|
|
@@ -612,7 +618,7 @@ class TransferComponentsExecutor:
|
|
|
612
618
|
)
|
|
613
619
|
# Do touch tip and air gap again after blowing out into source well or trash
|
|
614
620
|
self._do_touch_tip_and_air_gap_after_dispense(
|
|
615
|
-
touch_tip_properties=
|
|
621
|
+
touch_tip_properties=blowout_touch_tip_props,
|
|
616
622
|
location=touch_tip_and_air_gap_location,
|
|
617
623
|
well=touch_tip_and_air_gap_well,
|
|
618
624
|
air_gap_volume=air_gap_volume,
|
|
@@ -758,6 +764,7 @@ class TransferComponentsExecutor:
|
|
|
758
764
|
):
|
|
759
765
|
assert blowout_props.flow_rate is not None
|
|
760
766
|
self._instrument.set_flow_rate(blow_out=blowout_props.flow_rate)
|
|
767
|
+
blowout_touch_tip_props = retract_props.touch_tip
|
|
761
768
|
touch_tip_and_air_gap_location: Union[Location, TrashBin, WasteChute]
|
|
762
769
|
if blowout_props.location == BlowoutLocation.SOURCE:
|
|
763
770
|
if source_location is None or source_well is None:
|
|
@@ -776,6 +783,13 @@ class TransferComponentsExecutor:
|
|
|
776
783
|
source_well.get_top(0), labware=source_location.labware
|
|
777
784
|
)
|
|
778
785
|
touch_tip_and_air_gap_well = source_well
|
|
786
|
+
# Skip touch tip if blowing out at the SOURCE and it's untouchable:
|
|
787
|
+
if (
|
|
788
|
+
"touchTipDisabled"
|
|
789
|
+
in source_location.labware.quirks_from_any_parent()
|
|
790
|
+
):
|
|
791
|
+
blowout_touch_tip_props = replace(blowout_touch_tip_props)
|
|
792
|
+
blowout_touch_tip_props.enabled = False
|
|
779
793
|
else:
|
|
780
794
|
self._instrument.blow_out(
|
|
781
795
|
location=trash_location,
|
|
@@ -807,13 +821,13 @@ class TransferComponentsExecutor:
|
|
|
807
821
|
air_gap_volume = 0
|
|
808
822
|
# Do touch tip and air gap again after blowing out into source well or trash
|
|
809
823
|
self._do_touch_tip_and_air_gap_after_dispense(
|
|
810
|
-
touch_tip_properties=
|
|
824
|
+
touch_tip_properties=blowout_touch_tip_props,
|
|
811
825
|
location=touch_tip_and_air_gap_location,
|
|
812
826
|
well=touch_tip_and_air_gap_well,
|
|
813
827
|
air_gap_volume=air_gap_volume,
|
|
814
828
|
)
|
|
815
829
|
|
|
816
|
-
def _do_touch_tip_and_air_gap_after_dispense(
|
|
830
|
+
def _do_touch_tip_and_air_gap_after_dispense(
|
|
817
831
|
self,
|
|
818
832
|
touch_tip_properties: TouchTipProperties,
|
|
819
833
|
location: Union[Location, TrashBin, WasteChute],
|
|
@@ -822,6 +836,12 @@ class TransferComponentsExecutor:
|
|
|
822
836
|
) -> None:
|
|
823
837
|
"""Perform touch tip and air gap as part of post-dispense retract.
|
|
824
838
|
|
|
839
|
+
This function can be invoked up to 2 times for each dispense:
|
|
840
|
+
1) Once for touching tip at the dispense location.
|
|
841
|
+
2) Then again in the blowout location if it is not the dispense location.
|
|
842
|
+
For case (2), the caller should disable touch-tip in touch_tip_properties
|
|
843
|
+
if the blowout location is not touchable (such as reservoirs).
|
|
844
|
+
|
|
825
845
|
If the retract location is at or above the safe location of
|
|
826
846
|
AIR_GAP_LOC_Z_OFFSET_FROM_WELL_TOP, then add the air gap at the retract location
|
|
827
847
|
(where the pipette is already assumed to be at).
|
|
@@ -842,18 +862,14 @@ class TransferComponentsExecutor:
|
|
|
842
862
|
# whether the touch tip params from transfer props should be used for
|
|
843
863
|
# both dest-well touch tip and non-dest-well touch tip.
|
|
844
864
|
if isinstance(location, Location) and well is not None:
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
)
|
|
854
|
-
except TouchTipDisabledError:
|
|
855
|
-
# TODO: log a warning
|
|
856
|
-
pass
|
|
865
|
+
self._instrument.touch_tip(
|
|
866
|
+
location=location,
|
|
867
|
+
well_core=well,
|
|
868
|
+
radius=1,
|
|
869
|
+
z_offset=touch_tip_properties.z_offset,
|
|
870
|
+
speed=touch_tip_properties.speed,
|
|
871
|
+
mm_from_edge=touch_tip_properties.mm_from_edge,
|
|
872
|
+
)
|
|
857
873
|
|
|
858
874
|
# Move back to the 'retract' position
|
|
859
875
|
self._instrument.move_to(
|
|
@@ -1140,6 +1140,7 @@ class FlexStackerContext(ModuleContext):
|
|
|
1140
1140
|
return self._core.get_serial_number()
|
|
1141
1141
|
|
|
1142
1142
|
@requires_version(2, 25)
|
|
1143
|
+
@publish(command=cmds.flex_stacker_retrieve)
|
|
1143
1144
|
def retrieve(self) -> Labware:
|
|
1144
1145
|
"""Retrieve a labware from the Flex Stacker and move it onto the shuttle.
|
|
1145
1146
|
|
|
@@ -1160,6 +1161,7 @@ class FlexStackerContext(ModuleContext):
|
|
|
1160
1161
|
)
|
|
1161
1162
|
|
|
1162
1163
|
@requires_version(2, 25)
|
|
1164
|
+
@publish(command=cmds.flex_stacker_store)
|
|
1163
1165
|
def store(self) -> None:
|
|
1164
1166
|
"""Move a labware currently on the Flex Stacker shuttle into the Flex Stacker.
|
|
1165
1167
|
|
|
@@ -1318,6 +1320,7 @@ class FlexStackerContext(ModuleContext):
|
|
|
1318
1320
|
)
|
|
1319
1321
|
|
|
1320
1322
|
@requires_version(2, 25)
|
|
1323
|
+
@publish(command=cmds.flex_stacker_set_stored_labware)
|
|
1321
1324
|
def set_stored_labware(
|
|
1322
1325
|
self,
|
|
1323
1326
|
load_name: str,
|
|
@@ -1392,6 +1395,7 @@ class FlexStackerContext(ModuleContext):
|
|
|
1392
1395
|
)
|
|
1393
1396
|
|
|
1394
1397
|
@requires_version(2, 25)
|
|
1398
|
+
@publish(command=cmds.flex_stacker_fill)
|
|
1395
1399
|
def fill(self, count: int | None = None, message: str | None = None) -> None:
|
|
1396
1400
|
"""Pause the protocol to add labware to the Flex Stacker.
|
|
1397
1401
|
|
|
@@ -1418,6 +1422,7 @@ class FlexStackerContext(ModuleContext):
|
|
|
1418
1422
|
self._core.fill_items(self._labware_to_cores(labware), message)
|
|
1419
1423
|
|
|
1420
1424
|
@requires_version(2, 25)
|
|
1425
|
+
@publish(command=cmds.flex_stacker_empty)
|
|
1421
1426
|
def empty(self, message: str | None = None) -> None:
|
|
1422
1427
|
"""Pause the protocol to remove all labware stored in the Flex Stacker.
|
|
1423
1428
|
|
|
@@ -10,6 +10,8 @@ from opentrons.hardware_control.modules.types import (
|
|
|
10
10
|
MagneticModuleModel,
|
|
11
11
|
ThermocyclerModuleModel,
|
|
12
12
|
HeaterShakerModuleModel,
|
|
13
|
+
AbsorbanceReaderModel,
|
|
14
|
+
FlexStackerModuleModel,
|
|
13
15
|
)
|
|
14
16
|
from opentrons_shared_data.pipette.types import PipetteNameType
|
|
15
17
|
from opentrons.types import MountType, DeckSlotName, Location
|
|
@@ -78,6 +80,8 @@ _HARDWARE_TO_PE_MODULE: Dict[HardwareModuleModel, pe_types.ModuleModel] = {
|
|
|
78
80
|
ThermocyclerModuleModel.THERMOCYCLER_V1: pe_types.ModuleModel.THERMOCYCLER_MODULE_V1,
|
|
79
81
|
ThermocyclerModuleModel.THERMOCYCLER_V2: pe_types.ModuleModel.THERMOCYCLER_MODULE_V2,
|
|
80
82
|
HeaterShakerModuleModel.HEATER_SHAKER_V1: pe_types.ModuleModel.HEATER_SHAKER_MODULE_V1,
|
|
83
|
+
AbsorbanceReaderModel.ABSORBANCE_READER_V1: pe_types.ModuleModel.ABSORBANCE_READER_V1,
|
|
84
|
+
FlexStackerModuleModel.FLEX_STACKER_V1: pe_types.ModuleModel.FLEX_STACKER_MODULE_V1,
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
_HIGHER_ORDER_COMMAND_TYPES = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opentrons
|
|
3
|
-
Version: 8.6.
|
|
3
|
+
Version: 8.6.0a12
|
|
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.6.
|
|
27
|
+
Requires-Dist: opentrons-shared-data==8.6.0a12
|
|
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.6.
|
|
35
|
+
Requires-Dist: opentrons-hardware[flex]==8.6.0a12; extra == 'flex-hardware'
|
|
36
36
|
Provides-Extra: ot2-hardware
|
|
37
|
-
Requires-Dist: opentrons-hardware==8.6.
|
|
37
|
+
Requires-Dist: opentrons-hardware==8.6.0a12; extra == 'ot2-hardware'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
opentrons/__init__.py,sha256=TQ_Ca_zzAM3iLzAysWKkFkQHG8-imihxDPQbLCYrf-E,4533
|
|
2
|
-
opentrons/_version.py,sha256=
|
|
2
|
+
opentrons/_version.py,sha256=Ej-eiQxj2liXf3S-OFMSv77mR8rEtkyJT0yFtbesf_E,714
|
|
3
3
|
opentrons/execute.py,sha256=Y88qICDiHWQjU0L4Ou7DI5OXXu7zZcdkUvNUYmZqIfc,29282
|
|
4
4
|
opentrons/legacy_broker.py,sha256=XnuEBBlrHCThc31RFW2UR0tGqctqWZ-CZ9vSC4L9whU,1553
|
|
5
5
|
opentrons/ordered_set.py,sha256=g-SB3qA14yxHu9zjGyc2wC7d2TUCBE6fKZlHAtbPzI8,4082
|
|
@@ -28,7 +28,7 @@ opentrons/calibration_storage/ot3/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
|
|
|
28
28
|
opentrons/calibration_storage/ot3/models/v1.py,sha256=SZU9CilK4HjPNtE-6mLcGX4ZsT3o0PGX8-RPjogmwXY,4393
|
|
29
29
|
opentrons/cli/__init__.py,sha256=zP_n-SnZnZc_yzb0JnnwvUvIBiIpupGOQrqPZrSmnRs,430
|
|
30
30
|
opentrons/cli/__main__.py,sha256=Jvtl3eMKDT1eX00BGULAw6WqenKe911TMTg4b97y5dA,73
|
|
31
|
-
opentrons/cli/analyze.py,sha256=
|
|
31
|
+
opentrons/cli/analyze.py,sha256=sZHRQxVyQASunYpjl0iks_Gkc8K6iX79cBuaipHfVys,16747
|
|
32
32
|
opentrons/config/__init__.py,sha256=N_ls4aKFt5jrXiPg-M8g2ecc2PgEzH2qTjbPjlr2fFk,21488
|
|
33
33
|
opentrons/config/advanced_settings.py,sha256=CzR1IzIMGMkvzyzwIjaVR7_ZIZ9_zr-Odgq2Ij4K4vU,27215
|
|
34
34
|
opentrons/config/defaults_ot2.py,sha256=_l63QNW0aWTh0HGZcgF592ETJg8-W4M0XrQbbzkAPjA,6031
|
|
@@ -210,11 +210,11 @@ opentrons/hardware_control/scripts/update_module_fw.py,sha256=FqX4y5_Ghs-uY1_Kjb
|
|
|
210
210
|
opentrons/legacy_commands/__init__.py,sha256=erkaz7hc2iHsTtjpFDWrR1V5n47it3U1qxD2zL9CkuE,63
|
|
211
211
|
opentrons/legacy_commands/commands.py,sha256=lgImZ0Y3gZrMKDVioaOXWqa6mMJCNKDa8p-lQhTghWk,14530
|
|
212
212
|
opentrons/legacy_commands/helpers.py,sha256=Bc7mjK6V7b4h472NCx_qSwD0ojd_DM7mPg18tjo1DIQ,5228
|
|
213
|
-
opentrons/legacy_commands/module_commands.py,sha256=
|
|
213
|
+
opentrons/legacy_commands/module_commands.py,sha256=bAqZmsAqXkjf3qzexo9fOs4QxZ-RvcZmdy0_QEcHd7U,9368
|
|
214
214
|
opentrons/legacy_commands/protocol_commands.py,sha256=nPYBrm7j9co83IGWjzae2GOVkEZdu58pXQv3eOdpLzg,1383
|
|
215
215
|
opentrons/legacy_commands/publisher.py,sha256=JRrpF-kG7qt5dwDFbCqeMjokCSwn8BdllMMYnJeDLn8,5440
|
|
216
216
|
opentrons/legacy_commands/robot_commands.py,sha256=c51gVAh-98PxhxmEL_3P80rejkaY58gAQ7S6wNwctao,1642
|
|
217
|
-
opentrons/legacy_commands/types.py,sha256=
|
|
217
|
+
opentrons/legacy_commands/types.py,sha256=cbW_flEmurZIcAh-EOcJp3bgrUCvx3ASTrw1oRqMv10,30745
|
|
218
218
|
opentrons/motion_planning/__init__.py,sha256=Gma3SLAvKbL7QuhVGtL9zFx5vlk_7YBF0TjYZQSiv9s,755
|
|
219
219
|
opentrons/motion_planning/adjacent_slots_getters.py,sha256=z7HkfC8ymAdGHdFq-sC_1_cERX_v29b9x4HKtJ6gp9I,5390
|
|
220
220
|
opentrons/motion_planning/deck_conflict.py,sha256=gIAQYJbSKEn5XM_AoBVCOdp-acQsc0nF5FHaeuF53vg,16757
|
|
@@ -235,7 +235,7 @@ opentrons/protocol_api/deck.py,sha256=94vFceg1SC1bAGd7TvC1ZpYwnJR-VlzurEZ6jkacYe
|
|
|
235
235
|
opentrons/protocol_api/disposal_locations.py,sha256=NRiSGmDR0LnbyEkWSOM-o64uR2fUoB1NWJG7Y7SsJSs,7920
|
|
236
236
|
opentrons/protocol_api/instrument_context.py,sha256=dOg04iqYnNMJ7XnlHBX3tTGiEahc-7feIuErcevRdwY,141216
|
|
237
237
|
opentrons/protocol_api/labware.py,sha256=ZP4QuGadoDp6xtyToupXVSJFnsx4NfWcskRQAH3iU4Y,61443
|
|
238
|
-
opentrons/protocol_api/module_contexts.py,sha256=
|
|
238
|
+
opentrons/protocol_api/module_contexts.py,sha256=HYQ20RV2c-NNwgObQZNxyvVKmy2Ufkf--ILoRmhkcvA,59988
|
|
239
239
|
opentrons/protocol_api/module_validation_and_errors.py,sha256=ljst-M_KK78GnyG3pyZ_6yoYkMY3HORS1QyQyWrme-U,2250
|
|
240
240
|
opentrons/protocol_api/protocol_context.py,sha256=Hzgw3FbCRyd4kWmw4RZwZHJhoGZkmn7ug-Q7JZGCcqs,70298
|
|
241
241
|
opentrons/protocol_api/robot_context.py,sha256=D6ZdpFX30VTtVUDHitsVjabJQXD5TxOV9_Z6sik1LvE,11891
|
|
@@ -264,7 +264,7 @@ opentrons/protocol_api/core/engine/point_calculations.py,sha256=C2eF0fvJQGMqQv3D
|
|
|
264
264
|
opentrons/protocol_api/core/engine/protocol.py,sha256=uX-qwATcTXiEUXe9gGDmp1cJ1Xd4eQnyy-q_jpiyAYY,46023
|
|
265
265
|
opentrons/protocol_api/core/engine/robot.py,sha256=bzUt23NG-clD-9-QFsV_6nm3fMgSmvYEG9DyyZI1xgw,5366
|
|
266
266
|
opentrons/protocol_api/core/engine/stringify.py,sha256=GwFgEhFMk-uPfFQhQG_2mkaf4cxaItiY8RW7rZwiooQ,2794
|
|
267
|
-
opentrons/protocol_api/core/engine/transfer_components_executor.py,sha256=
|
|
267
|
+
opentrons/protocol_api/core/engine/transfer_components_executor.py,sha256=mR59C-e6IHSZthlbQEwmRnh5ye8lhr6a0Qp5CNNi9n8,45211
|
|
268
268
|
opentrons/protocol_api/core/engine/well.py,sha256=IaaFK-3hoUfabfn_twIT7zcAynhzAmRxDnvABss2szo,8923
|
|
269
269
|
opentrons/protocol_api/core/legacy/__init__.py,sha256=_9jCJNKG3SlS_vljVu8HHkZmtLf4F-f-JHALLF5d5go,401
|
|
270
270
|
opentrons/protocol_api/core/legacy/_labware_geometry.py,sha256=ugtMdfnSkUwBCC3Sdj5nP5aDUxX-Dr7BeiuPVmdjAtg,1091
|
|
@@ -520,7 +520,7 @@ opentrons/protocol_runner/__init__.py,sha256=Sr0gBDzNv3nuHPapeNy_IWadhohtwmlhfnB
|
|
|
520
520
|
opentrons/protocol_runner/create_simulating_orchestrator.py,sha256=S1Fu9TMa3NrujcPYTfULHpfqLTkrZPYz7CbcXtcDes0,4249
|
|
521
521
|
opentrons/protocol_runner/json_file_reader.py,sha256=dE9ujq3sWyKF1yFg0AN8h-roGVfvqf1tEcIq5wxHbxE,2341
|
|
522
522
|
opentrons/protocol_runner/json_translator.py,sha256=lrDzHOOkQ19ac4KEdUbfEOnfx-F_QCO-6oGqQZegy4g,12134
|
|
523
|
-
opentrons/protocol_runner/legacy_command_mapper.py,sha256=
|
|
523
|
+
opentrons/protocol_runner/legacy_command_mapper.py,sha256=yUCfnp4sNawFikrujyPo27Ba_aOy-kr-9F3dOK6Zu9Q,37125
|
|
524
524
|
opentrons/protocol_runner/legacy_context_plugin.py,sha256=G_qpeyaLvsCjb72_n96Luy8CPSfgPZpt0QKVzKc6LKY,4730
|
|
525
525
|
opentrons/protocol_runner/protocol_runner.py,sha256=YUHZvttojkYghq82IWYWvTfN2kUZ1oZdm8Fm4K-zftI,21658
|
|
526
526
|
opentrons/protocol_runner/python_protocol_wrappers.py,sha256=KEuM4M7rYD4zLjTqK89T47CiBIZJ42kG0JXWarLUq4E,6511
|
|
@@ -594,8 +594,8 @@ opentrons/util/linal.py,sha256=IlKAP9HkNBBgULeSf4YVwSKHdx9jnCjSr7nvDvlRALg,5753
|
|
|
594
594
|
opentrons/util/logging_config.py,sha256=7et4YYuQdWdq_e50U-8vFS_QyNBRgdnqPGAQJm8qrIo,9954
|
|
595
595
|
opentrons/util/logging_queue_handler.py,sha256=ZsSJwy-oV8DXwpYiZisQ1PbYwmK2cOslD46AcyJ1E4I,2484
|
|
596
596
|
opentrons/util/performance_helpers.py,sha256=ew7H8XD20iS6-2TJAzbQeyzStZkkE6PzHt_Adx3wbZQ,5172
|
|
597
|
-
opentrons-8.6.
|
|
598
|
-
opentrons-8.6.
|
|
599
|
-
opentrons-8.6.
|
|
600
|
-
opentrons-8.6.
|
|
601
|
-
opentrons-8.6.
|
|
597
|
+
opentrons-8.6.0a12.dist-info/METADATA,sha256=l9QH2vlXU_XB9ZQoxc0ls8JKOmdyxwzStTlW-DmhdUw,1611
|
|
598
|
+
opentrons-8.6.0a12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
599
|
+
opentrons-8.6.0a12.dist-info/entry_points.txt,sha256=fTa6eGCYkvOtv0ov-KVE8LLGetgb35LQLF9x85OWPVw,106
|
|
600
|
+
opentrons-8.6.0a12.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
601
|
+
opentrons-8.6.0a12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|