opentrons 8.4.0a13__py2.py3-none-any.whl → 8.5.0a1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/config/defaults_ot3.py +1 -1
- opentrons/legacy_commands/commands.py +16 -4
- opentrons/legacy_commands/robot_commands.py +51 -0
- opentrons/legacy_commands/types.py +91 -2
- opentrons/protocol_api/_liquid.py +60 -15
- opentrons/protocol_api/_liquid_properties.py +137 -90
- opentrons/protocol_api/_transfer_liquid_validation.py +10 -6
- opentrons/protocol_api/core/engine/instrument.py +172 -75
- opentrons/protocol_api/core/engine/protocol.py +13 -14
- opentrons/protocol_api/core/engine/robot.py +2 -2
- opentrons/protocol_api/core/engine/transfer_components_executor.py +157 -126
- opentrons/protocol_api/core/engine/well.py +16 -0
- opentrons/protocol_api/core/instrument.py +2 -2
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -2
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +1 -1
- opentrons/protocol_api/core/legacy/legacy_well_core.py +8 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -2
- opentrons/protocol_api/core/protocol.py +2 -2
- opentrons/protocol_api/core/well.py +8 -0
- opentrons/protocol_api/instrument_context.py +377 -86
- opentrons/protocol_api/labware.py +10 -0
- opentrons/protocol_api/protocol_context.py +79 -4
- opentrons/protocol_api/robot_context.py +48 -6
- opentrons/protocol_api/validation.py +15 -8
- opentrons/protocol_engine/commands/command_unions.py +10 -10
- opentrons/protocol_engine/commands/generate_command_schema.py +1 -1
- opentrons/protocol_engine/commands/get_next_tip.py +2 -2
- opentrons/protocol_engine/commands/pick_up_tip.py +9 -3
- opentrons/protocol_engine/commands/robot/__init__.py +20 -20
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +34 -24
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +29 -20
- opentrons/protocol_engine/commands/seal_pipette_to_tip.py +1 -1
- opentrons/protocol_engine/commands/unsafe/__init__.py +17 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +1 -2
- opentrons/protocol_engine/execution/labware_movement.py +9 -2
- opentrons/protocol_engine/execution/movement.py +12 -9
- opentrons/protocol_engine/execution/queue_worker.py +8 -1
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +52 -19
- opentrons/protocol_engine/state/_well_math.py +2 -2
- opentrons/protocol_engine/state/commands.py +14 -28
- opentrons/protocol_engine/state/frustum_helpers.py +11 -7
- opentrons/protocol_engine/state/modules.py +1 -1
- opentrons/protocol_engine/state/pipettes.py +8 -0
- opentrons/protocol_engine/state/tips.py +46 -83
- opentrons/protocol_engine/state/update_types.py +8 -23
- opentrons/protocol_runner/legacy_command_mapper.py +11 -4
- opentrons/protocol_runner/run_orchestrator.py +1 -1
- opentrons/protocols/advanced_control/transfers/common.py +54 -11
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +1 -1
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/types.py +6 -6
- {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/METADATA +4 -4
- {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/RECORD +57 -56
- {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/LICENSE +0 -0
- {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/WHEEL +0 -0
- {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/entry_points.txt +0 -0
- {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from numpy import interp
|
|
3
|
-
from typing import Optional, Dict, Sequence, Tuple, List
|
|
3
|
+
from typing import Optional, Dict, Sequence, Tuple, List, Union
|
|
4
4
|
|
|
5
5
|
from opentrons_shared_data.liquid_classes.liquid_class_definition import (
|
|
6
|
+
TransferProperties as SharedDataTransferProperties,
|
|
6
7
|
AspirateProperties as SharedDataAspirateProperties,
|
|
7
8
|
SingleDispenseProperties as SharedDataSingleDispenseProperties,
|
|
8
9
|
MultiDispenseProperties as SharedDataMultiDispenseProperties,
|
|
10
|
+
TipPosition as SharedDataTipPosition,
|
|
9
11
|
DelayProperties as SharedDataDelayProperties,
|
|
10
12
|
DelayParams as SharedDataDelayParams,
|
|
11
13
|
TouchTipProperties as SharedDataTouchTipProperties,
|
|
@@ -22,12 +24,12 @@ from opentrons_shared_data.liquid_classes.liquid_class_definition import (
|
|
|
22
24
|
PositionReference,
|
|
23
25
|
Coordinate,
|
|
24
26
|
)
|
|
25
|
-
|
|
26
27
|
from . import validation
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class LiquidHandlingPropertyByVolume:
|
|
30
31
|
def __init__(self, by_volume_property: Sequence[Tuple[float, float]]) -> None:
|
|
32
|
+
self._initial_properties_by_volume = by_volume_property
|
|
31
33
|
self._properties_by_volume: Dict[float, float] = {
|
|
32
34
|
float(volume): value for volume, value in by_volume_property
|
|
33
35
|
}
|
|
@@ -60,6 +62,11 @@ class LiquidHandlingPropertyByVolume:
|
|
|
60
62
|
interp(validated_volume, self._sorted_volumes, self._sorted_values)
|
|
61
63
|
)
|
|
62
64
|
|
|
65
|
+
def set_for_all_volumes(self, value: float) -> None:
|
|
66
|
+
"""Override all existing volume-dependent values with the given value."""
|
|
67
|
+
self.clear_values()
|
|
68
|
+
self.set_for_volume(0, value)
|
|
69
|
+
|
|
63
70
|
def set_for_volume(self, volume: float, value: float) -> None:
|
|
64
71
|
"""Add a new volume and value for the property for the interpolation curve."""
|
|
65
72
|
validated_volume = validation.ensure_positive_float(volume)
|
|
@@ -74,6 +81,17 @@ class LiquidHandlingPropertyByVolume:
|
|
|
74
81
|
raise KeyError(f"No value set for volume {volume} uL")
|
|
75
82
|
self._sort_volume_and_values()
|
|
76
83
|
|
|
84
|
+
def clear_values(self) -> None:
|
|
85
|
+
"""Removes all existing volume and value pairs from the curve."""
|
|
86
|
+
self._properties_by_volume = {}
|
|
87
|
+
|
|
88
|
+
def reset_values(self) -> None:
|
|
89
|
+
"""Resets volumes and values to the default."""
|
|
90
|
+
self._properties_by_volume = {
|
|
91
|
+
float(volume): value for volume, value in self._initial_properties_by_volume
|
|
92
|
+
}
|
|
93
|
+
self._sort_volume_and_values()
|
|
94
|
+
|
|
77
95
|
def _sort_volume_and_values(self) -> None:
|
|
78
96
|
"""Sort volume in increasing order along with corresponding values in matching order."""
|
|
79
97
|
self._sorted_volumes, self._sorted_values = (
|
|
@@ -86,6 +104,36 @@ class LiquidHandlingPropertyByVolume:
|
|
|
86
104
|
# We use slots for this dataclass (and the rest of liquid properties) to prevent dynamic creation of attributes
|
|
87
105
|
# not defined in the class, not for any performance reasons. This is so that mistyping properties when overriding
|
|
88
106
|
# values will cause the protocol to fail analysis, rather than silently passing.
|
|
107
|
+
@dataclass(slots=True)
|
|
108
|
+
class TipPosition:
|
|
109
|
+
|
|
110
|
+
_position_reference: PositionReference
|
|
111
|
+
_offset: Coordinate
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def position_reference(self) -> PositionReference:
|
|
115
|
+
return self._position_reference
|
|
116
|
+
|
|
117
|
+
@position_reference.setter
|
|
118
|
+
def position_reference(self, new_position: str) -> None:
|
|
119
|
+
self._position_reference = PositionReference(new_position)
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def offset(self) -> Coordinate:
|
|
123
|
+
return self._offset
|
|
124
|
+
|
|
125
|
+
@offset.setter
|
|
126
|
+
def offset(self, new_offset: Sequence[float]) -> None:
|
|
127
|
+
x, y, z = validation.validate_coordinates(new_offset)
|
|
128
|
+
self._offset = Coordinate(x=x, y=y, z=z)
|
|
129
|
+
|
|
130
|
+
def as_shared_data_model(self) -> SharedDataTipPosition:
|
|
131
|
+
return SharedDataTipPosition(
|
|
132
|
+
positionReference=self._position_reference,
|
|
133
|
+
offset=self.offset,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
89
137
|
@dataclass(slots=True)
|
|
90
138
|
class DelayProperties:
|
|
91
139
|
|
|
@@ -126,7 +174,7 @@ class TouchTipProperties:
|
|
|
126
174
|
|
|
127
175
|
_enabled: bool
|
|
128
176
|
_z_offset: Optional[float]
|
|
129
|
-
|
|
177
|
+
_mm_from_edge: Optional[float]
|
|
130
178
|
_speed: Optional[float]
|
|
131
179
|
|
|
132
180
|
@property
|
|
@@ -137,10 +185,10 @@ class TouchTipProperties:
|
|
|
137
185
|
def enabled(self, enable: bool) -> None:
|
|
138
186
|
validated_enable = validation.ensure_boolean(enable)
|
|
139
187
|
if validated_enable and (
|
|
140
|
-
self._z_offset is None or self.
|
|
188
|
+
self._z_offset is None or self._mm_from_edge is None or self._speed is None
|
|
141
189
|
):
|
|
142
190
|
raise ValueError(
|
|
143
|
-
"z_offset,
|
|
191
|
+
"z_offset, mm_from_edge and speed must be set before enabling touch tip."
|
|
144
192
|
)
|
|
145
193
|
self._enabled = validated_enable
|
|
146
194
|
|
|
@@ -154,13 +202,13 @@ class TouchTipProperties:
|
|
|
154
202
|
self._z_offset = validated_offset
|
|
155
203
|
|
|
156
204
|
@property
|
|
157
|
-
def
|
|
158
|
-
return self.
|
|
205
|
+
def mm_from_edge(self) -> Optional[float]:
|
|
206
|
+
return self._mm_from_edge
|
|
159
207
|
|
|
160
|
-
@
|
|
161
|
-
def
|
|
208
|
+
@mm_from_edge.setter
|
|
209
|
+
def mm_from_edge(self, new_mm: float) -> None:
|
|
162
210
|
validated_mm = validation.ensure_float(new_mm)
|
|
163
|
-
self.
|
|
211
|
+
self._mm_from_edge = validated_mm
|
|
164
212
|
|
|
165
213
|
@property
|
|
166
214
|
def speed(self) -> Optional[float]:
|
|
@@ -175,12 +223,12 @@ class TouchTipProperties:
|
|
|
175
223
|
"""Get the touch tip params in schema v1 shape."""
|
|
176
224
|
if (
|
|
177
225
|
self._z_offset is not None
|
|
178
|
-
and self.
|
|
226
|
+
and self._mm_from_edge is not None
|
|
179
227
|
and self._speed is not None
|
|
180
228
|
):
|
|
181
229
|
return SharedDataTouchTipParams(
|
|
182
230
|
zOffset=self._z_offset,
|
|
183
|
-
|
|
231
|
+
mmFromEdge=self._mm_from_edge,
|
|
184
232
|
speed=self._speed,
|
|
185
233
|
)
|
|
186
234
|
else:
|
|
@@ -301,30 +349,11 @@ class BlowoutProperties:
|
|
|
301
349
|
|
|
302
350
|
|
|
303
351
|
@dataclass(slots=True)
|
|
304
|
-
class
|
|
352
|
+
class _SubmergeRetractCommon:
|
|
305
353
|
|
|
306
|
-
_position_reference: PositionReference
|
|
307
|
-
_offset: Coordinate
|
|
308
354
|
_speed: float
|
|
309
355
|
_delay: DelayProperties
|
|
310
356
|
|
|
311
|
-
@property
|
|
312
|
-
def position_reference(self) -> PositionReference:
|
|
313
|
-
return self._position_reference
|
|
314
|
-
|
|
315
|
-
@position_reference.setter
|
|
316
|
-
def position_reference(self, new_position: str) -> None:
|
|
317
|
-
self._position_reference = PositionReference(new_position)
|
|
318
|
-
|
|
319
|
-
@property
|
|
320
|
-
def offset(self) -> Coordinate:
|
|
321
|
-
return self._offset
|
|
322
|
-
|
|
323
|
-
@offset.setter
|
|
324
|
-
def offset(self, new_offset: Sequence[float]) -> None:
|
|
325
|
-
x, y, z = validation.validate_coordinates(new_offset)
|
|
326
|
-
self._offset = Coordinate(x=x, y=y, z=z)
|
|
327
|
-
|
|
328
357
|
@property
|
|
329
358
|
def speed(self) -> float:
|
|
330
359
|
return self._speed
|
|
@@ -340,22 +369,33 @@ class SubmergeRetractCommon:
|
|
|
340
369
|
|
|
341
370
|
|
|
342
371
|
@dataclass(slots=True)
|
|
343
|
-
class Submerge(
|
|
372
|
+
class Submerge(_SubmergeRetractCommon):
|
|
373
|
+
|
|
374
|
+
_start_position: TipPosition
|
|
375
|
+
|
|
376
|
+
@property
|
|
377
|
+
def start_position(self) -> TipPosition:
|
|
378
|
+
return self._start_position
|
|
379
|
+
|
|
344
380
|
def as_shared_data_model(self) -> SharedDataSubmerge:
|
|
345
381
|
return SharedDataSubmerge(
|
|
346
|
-
|
|
347
|
-
offset=self._offset,
|
|
382
|
+
startPosition=self._start_position.as_shared_data_model(),
|
|
348
383
|
speed=self._speed,
|
|
349
384
|
delay=self._delay.as_shared_data_model(),
|
|
350
385
|
)
|
|
351
386
|
|
|
352
387
|
|
|
353
388
|
@dataclass(slots=True)
|
|
354
|
-
class RetractAspirate(
|
|
389
|
+
class RetractAspirate(_SubmergeRetractCommon):
|
|
355
390
|
|
|
391
|
+
_end_position: TipPosition
|
|
356
392
|
_air_gap_by_volume: LiquidHandlingPropertyByVolume
|
|
357
393
|
_touch_tip: TouchTipProperties
|
|
358
394
|
|
|
395
|
+
@property
|
|
396
|
+
def end_position(self) -> TipPosition:
|
|
397
|
+
return self._end_position
|
|
398
|
+
|
|
359
399
|
@property
|
|
360
400
|
def air_gap_by_volume(self) -> LiquidHandlingPropertyByVolume:
|
|
361
401
|
return self._air_gap_by_volume
|
|
@@ -366,8 +406,7 @@ class RetractAspirate(SubmergeRetractCommon):
|
|
|
366
406
|
|
|
367
407
|
def as_shared_data_model(self) -> SharedDataRetractAspirate:
|
|
368
408
|
return SharedDataRetractAspirate(
|
|
369
|
-
|
|
370
|
-
offset=self._offset,
|
|
409
|
+
endPosition=self._end_position.as_shared_data_model(),
|
|
371
410
|
speed=self._speed,
|
|
372
411
|
airGapByVolume=self._air_gap_by_volume.as_list_of_tuples(),
|
|
373
412
|
touchTip=self._touch_tip.as_shared_data_model(),
|
|
@@ -376,12 +415,16 @@ class RetractAspirate(SubmergeRetractCommon):
|
|
|
376
415
|
|
|
377
416
|
|
|
378
417
|
@dataclass(slots=True)
|
|
379
|
-
class RetractDispense(
|
|
380
|
-
|
|
418
|
+
class RetractDispense(_SubmergeRetractCommon):
|
|
419
|
+
_end_position: TipPosition
|
|
381
420
|
_air_gap_by_volume: LiquidHandlingPropertyByVolume
|
|
382
421
|
_touch_tip: TouchTipProperties
|
|
383
422
|
_blowout: BlowoutProperties
|
|
384
423
|
|
|
424
|
+
@property
|
|
425
|
+
def end_position(self) -> TipPosition:
|
|
426
|
+
return self._end_position
|
|
427
|
+
|
|
385
428
|
@property
|
|
386
429
|
def air_gap_by_volume(self) -> LiquidHandlingPropertyByVolume:
|
|
387
430
|
return self._air_gap_by_volume
|
|
@@ -396,8 +439,7 @@ class RetractDispense(SubmergeRetractCommon):
|
|
|
396
439
|
|
|
397
440
|
def as_shared_data_model(self) -> SharedDataRetractDispense:
|
|
398
441
|
return SharedDataRetractDispense(
|
|
399
|
-
|
|
400
|
-
offset=self._offset,
|
|
442
|
+
endPosition=self._end_position.as_shared_data_model(),
|
|
401
443
|
speed=self._speed,
|
|
402
444
|
airGapByVolume=self._air_gap_by_volume.as_list_of_tuples(),
|
|
403
445
|
blowout=self._blowout.as_shared_data_model(),
|
|
@@ -407,11 +449,9 @@ class RetractDispense(SubmergeRetractCommon):
|
|
|
407
449
|
|
|
408
450
|
|
|
409
451
|
@dataclass(slots=True)
|
|
410
|
-
class
|
|
452
|
+
class _BaseLiquidHandlingProperties:
|
|
411
453
|
|
|
412
454
|
_submerge: Submerge
|
|
413
|
-
_position_reference: PositionReference
|
|
414
|
-
_offset: Coordinate
|
|
415
455
|
_flow_rate_by_volume: LiquidHandlingPropertyByVolume
|
|
416
456
|
_correction_by_volume: LiquidHandlingPropertyByVolume
|
|
417
457
|
_delay: DelayProperties
|
|
@@ -420,23 +460,6 @@ class BaseLiquidHandlingProperties:
|
|
|
420
460
|
def submerge(self) -> Submerge:
|
|
421
461
|
return self._submerge
|
|
422
462
|
|
|
423
|
-
@property
|
|
424
|
-
def position_reference(self) -> PositionReference:
|
|
425
|
-
return self._position_reference
|
|
426
|
-
|
|
427
|
-
@position_reference.setter
|
|
428
|
-
def position_reference(self, new_position: str) -> None:
|
|
429
|
-
self._position_reference = PositionReference(new_position)
|
|
430
|
-
|
|
431
|
-
@property
|
|
432
|
-
def offset(self) -> Coordinate:
|
|
433
|
-
return self._offset
|
|
434
|
-
|
|
435
|
-
@offset.setter
|
|
436
|
-
def offset(self, new_offset: Sequence[float]) -> None:
|
|
437
|
-
x, y, z = validation.validate_coordinates(new_offset)
|
|
438
|
-
self._offset = Coordinate(x=x, y=y, z=z)
|
|
439
|
-
|
|
440
463
|
@property
|
|
441
464
|
def flow_rate_by_volume(self) -> LiquidHandlingPropertyByVolume:
|
|
442
465
|
return self._flow_rate_by_volume
|
|
@@ -451,12 +474,17 @@ class BaseLiquidHandlingProperties:
|
|
|
451
474
|
|
|
452
475
|
|
|
453
476
|
@dataclass(slots=True)
|
|
454
|
-
class AspirateProperties(
|
|
477
|
+
class AspirateProperties(_BaseLiquidHandlingProperties):
|
|
455
478
|
|
|
479
|
+
_aspirate_position: TipPosition
|
|
456
480
|
_retract: RetractAspirate
|
|
457
481
|
_pre_wet: bool
|
|
458
482
|
_mix: MixProperties
|
|
459
483
|
|
|
484
|
+
@property
|
|
485
|
+
def aspirate_position(self) -> TipPosition:
|
|
486
|
+
return self._aspirate_position
|
|
487
|
+
|
|
460
488
|
@property
|
|
461
489
|
def pre_wet(self) -> bool:
|
|
462
490
|
return self._pre_wet
|
|
@@ -478,8 +506,7 @@ class AspirateProperties(BaseLiquidHandlingProperties):
|
|
|
478
506
|
return SharedDataAspirateProperties(
|
|
479
507
|
submerge=self._submerge.as_shared_data_model(),
|
|
480
508
|
retract=self._retract.as_shared_data_model(),
|
|
481
|
-
|
|
482
|
-
offset=self._offset,
|
|
509
|
+
aspiratePosition=self._aspirate_position.as_shared_data_model(),
|
|
483
510
|
flowRateByVolume=self._flow_rate_by_volume.as_list_of_tuples(),
|
|
484
511
|
preWet=self._pre_wet,
|
|
485
512
|
mix=self._mix.as_shared_data_model(),
|
|
@@ -489,12 +516,17 @@ class AspirateProperties(BaseLiquidHandlingProperties):
|
|
|
489
516
|
|
|
490
517
|
|
|
491
518
|
@dataclass(slots=True)
|
|
492
|
-
class SingleDispenseProperties(
|
|
519
|
+
class SingleDispenseProperties(_BaseLiquidHandlingProperties):
|
|
493
520
|
|
|
521
|
+
_dispense_position: TipPosition
|
|
494
522
|
_retract: RetractDispense
|
|
495
523
|
_push_out_by_volume: LiquidHandlingPropertyByVolume
|
|
496
524
|
_mix: MixProperties
|
|
497
525
|
|
|
526
|
+
@property
|
|
527
|
+
def dispense_position(self) -> TipPosition:
|
|
528
|
+
return self._dispense_position
|
|
529
|
+
|
|
498
530
|
@property
|
|
499
531
|
def push_out_by_volume(self) -> LiquidHandlingPropertyByVolume:
|
|
500
532
|
return self._push_out_by_volume
|
|
@@ -511,8 +543,7 @@ class SingleDispenseProperties(BaseLiquidHandlingProperties):
|
|
|
511
543
|
return SharedDataSingleDispenseProperties(
|
|
512
544
|
submerge=self._submerge.as_shared_data_model(),
|
|
513
545
|
retract=self._retract.as_shared_data_model(),
|
|
514
|
-
|
|
515
|
-
offset=self._offset,
|
|
546
|
+
dispensePosition=self._dispense_position.as_shared_data_model(),
|
|
516
547
|
flowRateByVolume=self._flow_rate_by_volume.as_list_of_tuples(),
|
|
517
548
|
mix=self._mix.as_shared_data_model(),
|
|
518
549
|
pushOutByVolume=self._push_out_by_volume.as_list_of_tuples(),
|
|
@@ -522,12 +553,17 @@ class SingleDispenseProperties(BaseLiquidHandlingProperties):
|
|
|
522
553
|
|
|
523
554
|
|
|
524
555
|
@dataclass(slots=True)
|
|
525
|
-
class MultiDispenseProperties(
|
|
556
|
+
class MultiDispenseProperties(_BaseLiquidHandlingProperties):
|
|
526
557
|
|
|
558
|
+
_dispense_position: TipPosition
|
|
527
559
|
_retract: RetractDispense
|
|
528
560
|
_conditioning_by_volume: LiquidHandlingPropertyByVolume
|
|
529
561
|
_disposal_by_volume: LiquidHandlingPropertyByVolume
|
|
530
562
|
|
|
563
|
+
@property
|
|
564
|
+
def dispense_position(self) -> TipPosition:
|
|
565
|
+
return self._dispense_position
|
|
566
|
+
|
|
531
567
|
@property
|
|
532
568
|
def retract(self) -> RetractDispense:
|
|
533
569
|
return self._retract
|
|
@@ -544,8 +580,7 @@ class MultiDispenseProperties(BaseLiquidHandlingProperties):
|
|
|
544
580
|
return SharedDataMultiDispenseProperties(
|
|
545
581
|
submerge=self._submerge.as_shared_data_model(),
|
|
546
582
|
retract=self._retract.as_shared_data_model(),
|
|
547
|
-
|
|
548
|
-
offset=self._offset,
|
|
583
|
+
dispensePosition=self._dispense_position.as_shared_data_model(),
|
|
549
584
|
flowRateByVolume=self._flow_rate_by_volume.as_list_of_tuples(),
|
|
550
585
|
conditioningByVolume=self._conditioning_by_volume.as_list_of_tuples(),
|
|
551
586
|
disposalByVolume=self._disposal_by_volume.as_list_of_tuples(),
|
|
@@ -576,6 +611,12 @@ class TransferProperties:
|
|
|
576
611
|
return self._multi_dispense
|
|
577
612
|
|
|
578
613
|
|
|
614
|
+
def _build_tip_position(tip_position: SharedDataTipPosition) -> TipPosition:
|
|
615
|
+
return TipPosition(
|
|
616
|
+
_position_reference=tip_position.positionReference, _offset=tip_position.offset
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
|
|
579
620
|
def _build_delay_properties(
|
|
580
621
|
delay_properties: SharedDataDelayProperties,
|
|
581
622
|
) -> DelayProperties:
|
|
@@ -591,16 +632,16 @@ def _build_touch_tip_properties(
|
|
|
591
632
|
) -> TouchTipProperties:
|
|
592
633
|
if touch_tip_properties.params is not None:
|
|
593
634
|
z_offset = touch_tip_properties.params.zOffset
|
|
594
|
-
|
|
635
|
+
mm_from_edge = touch_tip_properties.params.mmFromEdge
|
|
595
636
|
speed = touch_tip_properties.params.speed
|
|
596
637
|
else:
|
|
597
638
|
z_offset = None
|
|
598
|
-
|
|
639
|
+
mm_from_edge = None
|
|
599
640
|
speed = None
|
|
600
641
|
return TouchTipProperties(
|
|
601
642
|
_enabled=touch_tip_properties.enable,
|
|
602
643
|
_z_offset=z_offset,
|
|
603
|
-
|
|
644
|
+
_mm_from_edge=mm_from_edge,
|
|
604
645
|
_speed=speed,
|
|
605
646
|
)
|
|
606
647
|
|
|
@@ -637,8 +678,7 @@ def _build_submerge(
|
|
|
637
678
|
submerge_properties: SharedDataSubmerge,
|
|
638
679
|
) -> Submerge:
|
|
639
680
|
return Submerge(
|
|
640
|
-
|
|
641
|
-
_offset=submerge_properties.offset,
|
|
681
|
+
_start_position=_build_tip_position(submerge_properties.startPosition),
|
|
642
682
|
_speed=submerge_properties.speed,
|
|
643
683
|
_delay=_build_delay_properties(submerge_properties.delay),
|
|
644
684
|
)
|
|
@@ -648,8 +688,7 @@ def _build_retract_aspirate(
|
|
|
648
688
|
retract_aspirate: SharedDataRetractAspirate,
|
|
649
689
|
) -> RetractAspirate:
|
|
650
690
|
return RetractAspirate(
|
|
651
|
-
|
|
652
|
-
_offset=retract_aspirate.offset,
|
|
691
|
+
_end_position=_build_tip_position(retract_aspirate.endPosition),
|
|
653
692
|
_speed=retract_aspirate.speed,
|
|
654
693
|
_air_gap_by_volume=LiquidHandlingPropertyByVolume(
|
|
655
694
|
retract_aspirate.airGapByVolume
|
|
@@ -663,8 +702,7 @@ def _build_retract_dispense(
|
|
|
663
702
|
retract_dispense: SharedDataRetractDispense,
|
|
664
703
|
) -> RetractDispense:
|
|
665
704
|
return RetractDispense(
|
|
666
|
-
|
|
667
|
-
_offset=retract_dispense.offset,
|
|
705
|
+
_end_position=_build_tip_position(retract_dispense.endPosition),
|
|
668
706
|
_speed=retract_dispense.speed,
|
|
669
707
|
_air_gap_by_volume=LiquidHandlingPropertyByVolume(
|
|
670
708
|
retract_dispense.airGapByVolume
|
|
@@ -681,8 +719,7 @@ def build_aspirate_properties(
|
|
|
681
719
|
return AspirateProperties(
|
|
682
720
|
_submerge=_build_submerge(aspirate_properties.submerge),
|
|
683
721
|
_retract=_build_retract_aspirate(aspirate_properties.retract),
|
|
684
|
-
|
|
685
|
-
_offset=aspirate_properties.offset,
|
|
722
|
+
_aspirate_position=_build_tip_position(aspirate_properties.aspiratePosition),
|
|
686
723
|
_flow_rate_by_volume=LiquidHandlingPropertyByVolume(
|
|
687
724
|
aspirate_properties.flowRateByVolume
|
|
688
725
|
),
|
|
@@ -701,8 +738,9 @@ def build_single_dispense_properties(
|
|
|
701
738
|
return SingleDispenseProperties(
|
|
702
739
|
_submerge=_build_submerge(single_dispense_properties.submerge),
|
|
703
740
|
_retract=_build_retract_dispense(single_dispense_properties.retract),
|
|
704
|
-
|
|
705
|
-
|
|
741
|
+
_dispense_position=_build_tip_position(
|
|
742
|
+
single_dispense_properties.dispensePosition
|
|
743
|
+
),
|
|
706
744
|
_flow_rate_by_volume=LiquidHandlingPropertyByVolume(
|
|
707
745
|
single_dispense_properties.flowRateByVolume
|
|
708
746
|
),
|
|
@@ -725,8 +763,9 @@ def build_multi_dispense_properties(
|
|
|
725
763
|
return MultiDispenseProperties(
|
|
726
764
|
_submerge=_build_submerge(multi_dispense_properties.submerge),
|
|
727
765
|
_retract=_build_retract_dispense(multi_dispense_properties.retract),
|
|
728
|
-
|
|
729
|
-
|
|
766
|
+
_dispense_position=_build_tip_position(
|
|
767
|
+
multi_dispense_properties.dispensePosition
|
|
768
|
+
),
|
|
730
769
|
_flow_rate_by_volume=LiquidHandlingPropertyByVolume(
|
|
731
770
|
multi_dispense_properties.flowRateByVolume
|
|
732
771
|
),
|
|
@@ -744,12 +783,20 @@ def build_multi_dispense_properties(
|
|
|
744
783
|
|
|
745
784
|
|
|
746
785
|
def build_transfer_properties(
|
|
747
|
-
|
|
786
|
+
transfer_properties: Union[SharedDataTransferProperties, SharedByTipTypeSetting],
|
|
748
787
|
) -> TransferProperties:
|
|
788
|
+
if isinstance(transfer_properties, SharedByTipTypeSetting):
|
|
789
|
+
_transfer_properties = SharedDataTransferProperties(
|
|
790
|
+
aspirate=transfer_properties.aspirate,
|
|
791
|
+
singleDispense=transfer_properties.singleDispense,
|
|
792
|
+
multiDispense=transfer_properties.multiDispense,
|
|
793
|
+
)
|
|
794
|
+
else:
|
|
795
|
+
_transfer_properties = transfer_properties
|
|
749
796
|
return TransferProperties(
|
|
750
|
-
_aspirate=build_aspirate_properties(
|
|
751
|
-
_dispense=build_single_dispense_properties(
|
|
797
|
+
_aspirate=build_aspirate_properties(_transfer_properties.aspirate),
|
|
798
|
+
_dispense=build_single_dispense_properties(_transfer_properties.singleDispense),
|
|
752
799
|
_multi_dispense=build_multi_dispense_properties(
|
|
753
|
-
|
|
800
|
+
_transfer_properties.multiDispense
|
|
754
801
|
),
|
|
755
802
|
)
|
|
@@ -19,8 +19,8 @@ from . import validation
|
|
|
19
19
|
@dataclass
|
|
20
20
|
class TransferInfo:
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
source: List[Well]
|
|
23
|
+
dest: Union[List[Well], TrashBin, WasteChute]
|
|
24
24
|
tip_policy: TransferTipPolicyV2
|
|
25
25
|
tip_racks: List[Labware]
|
|
26
26
|
trash_location: Union[Location, TrashBin, WasteChute]
|
|
@@ -28,7 +28,7 @@ class TransferInfo:
|
|
|
28
28
|
|
|
29
29
|
def verify_and_normalize_transfer_args(
|
|
30
30
|
source: Union[Well, Sequence[Well], Sequence[Sequence[Well]]],
|
|
31
|
-
dest: Union[Well, Sequence[Well], Sequence[Sequence[Well]]],
|
|
31
|
+
dest: Union[Well, Sequence[Well], Sequence[Sequence[Well]], TrashBin, WasteChute],
|
|
32
32
|
tip_policy: TransferTipPolicyV2Type,
|
|
33
33
|
last_tip_picked_up_from: Optional[Well],
|
|
34
34
|
tip_racks: List[Labware],
|
|
@@ -38,7 +38,11 @@ def verify_and_normalize_transfer_args(
|
|
|
38
38
|
trash_location: Union[Location, Well, Labware, TrashBin, WasteChute],
|
|
39
39
|
) -> TransferInfo:
|
|
40
40
|
flat_sources_list = validation.ensure_valid_flat_wells_list_for_transfer_v2(source)
|
|
41
|
-
|
|
41
|
+
if not isinstance(dest, (TrashBin, WasteChute)):
|
|
42
|
+
flat_dests_list = validation.ensure_valid_flat_wells_list_for_transfer_v2(dest)
|
|
43
|
+
else:
|
|
44
|
+
# If trash bin or waste chute, set this to empty to have less isinstance checks after this
|
|
45
|
+
flat_dests_list = []
|
|
42
46
|
if not target_all_wells and nozzle_map.tip_count > 1:
|
|
43
47
|
flat_sources_list = tx_liquid_utils.group_wells_for_multi_channel_transfer(
|
|
44
48
|
flat_sources_list, nozzle_map
|
|
@@ -83,8 +87,8 @@ def verify_and_normalize_transfer_args(
|
|
|
83
87
|
)
|
|
84
88
|
|
|
85
89
|
return TransferInfo(
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
source=flat_sources_list,
|
|
91
|
+
dest=flat_dests_list if not isinstance(dest, (TrashBin, WasteChute)) else dest,
|
|
88
92
|
tip_policy=valid_new_tip,
|
|
89
93
|
tip_racks=valid_tip_racks,
|
|
90
94
|
trash_location=valid_trash_location,
|