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.

Files changed (57) hide show
  1. opentrons/config/defaults_ot3.py +1 -1
  2. opentrons/legacy_commands/commands.py +16 -4
  3. opentrons/legacy_commands/robot_commands.py +51 -0
  4. opentrons/legacy_commands/types.py +91 -2
  5. opentrons/protocol_api/_liquid.py +60 -15
  6. opentrons/protocol_api/_liquid_properties.py +137 -90
  7. opentrons/protocol_api/_transfer_liquid_validation.py +10 -6
  8. opentrons/protocol_api/core/engine/instrument.py +172 -75
  9. opentrons/protocol_api/core/engine/protocol.py +13 -14
  10. opentrons/protocol_api/core/engine/robot.py +2 -2
  11. opentrons/protocol_api/core/engine/transfer_components_executor.py +157 -126
  12. opentrons/protocol_api/core/engine/well.py +16 -0
  13. opentrons/protocol_api/core/instrument.py +2 -2
  14. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -2
  15. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +1 -1
  16. opentrons/protocol_api/core/legacy/legacy_well_core.py +8 -0
  17. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -2
  18. opentrons/protocol_api/core/protocol.py +2 -2
  19. opentrons/protocol_api/core/well.py +8 -0
  20. opentrons/protocol_api/instrument_context.py +377 -86
  21. opentrons/protocol_api/labware.py +10 -0
  22. opentrons/protocol_api/protocol_context.py +79 -4
  23. opentrons/protocol_api/robot_context.py +48 -6
  24. opentrons/protocol_api/validation.py +15 -8
  25. opentrons/protocol_engine/commands/command_unions.py +10 -10
  26. opentrons/protocol_engine/commands/generate_command_schema.py +1 -1
  27. opentrons/protocol_engine/commands/get_next_tip.py +2 -2
  28. opentrons/protocol_engine/commands/pick_up_tip.py +9 -3
  29. opentrons/protocol_engine/commands/robot/__init__.py +20 -20
  30. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +34 -24
  31. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +29 -20
  32. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +1 -1
  33. opentrons/protocol_engine/commands/unsafe/__init__.py +17 -1
  34. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +1 -2
  35. opentrons/protocol_engine/execution/labware_movement.py +9 -2
  36. opentrons/protocol_engine/execution/movement.py +12 -9
  37. opentrons/protocol_engine/execution/queue_worker.py +8 -1
  38. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +52 -19
  39. opentrons/protocol_engine/state/_well_math.py +2 -2
  40. opentrons/protocol_engine/state/commands.py +14 -28
  41. opentrons/protocol_engine/state/frustum_helpers.py +11 -7
  42. opentrons/protocol_engine/state/modules.py +1 -1
  43. opentrons/protocol_engine/state/pipettes.py +8 -0
  44. opentrons/protocol_engine/state/tips.py +46 -83
  45. opentrons/protocol_engine/state/update_types.py +8 -23
  46. opentrons/protocol_runner/legacy_command_mapper.py +11 -4
  47. opentrons/protocol_runner/run_orchestrator.py +1 -1
  48. opentrons/protocols/advanced_control/transfers/common.py +54 -11
  49. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +1 -1
  50. opentrons/protocols/api_support/definitions.py +1 -1
  51. opentrons/types.py +6 -6
  52. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/METADATA +4 -4
  53. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/RECORD +57 -56
  54. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/LICENSE +0 -0
  55. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/WHEEL +0 -0
  56. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/entry_points.txt +0 -0
  57. {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
- _mm_to_edge: Optional[float]
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._mm_to_edge is None or self._speed is None
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, mm_to_edge and speed must be set before enabling touch tip."
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 mm_to_edge(self) -> Optional[float]:
158
- return self._mm_to_edge
205
+ def mm_from_edge(self) -> Optional[float]:
206
+ return self._mm_from_edge
159
207
 
160
- @mm_to_edge.setter
161
- def mm_to_edge(self, new_mm: float) -> None:
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._mm_to_edge = validated_mm
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._mm_to_edge is not None
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
- mmToEdge=self._mm_to_edge,
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 SubmergeRetractCommon:
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(SubmergeRetractCommon):
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
- positionReference=self._position_reference,
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(SubmergeRetractCommon):
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
- positionReference=self._position_reference,
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(SubmergeRetractCommon):
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
- positionReference=self._position_reference,
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 BaseLiquidHandlingProperties:
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(BaseLiquidHandlingProperties):
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
- positionReference=self._position_reference,
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(BaseLiquidHandlingProperties):
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
- positionReference=self._position_reference,
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(BaseLiquidHandlingProperties):
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
- positionReference=self._position_reference,
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
- mm_to_edge = touch_tip_properties.params.mmToEdge
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
- mm_to_edge = None
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
- _mm_to_edge=mm_to_edge,
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
- _position_reference=submerge_properties.positionReference,
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
- _position_reference=retract_aspirate.positionReference,
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
- _position_reference=retract_dispense.positionReference,
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
- _position_reference=aspirate_properties.positionReference,
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
- _position_reference=single_dispense_properties.positionReference,
705
- _offset=single_dispense_properties.offset,
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
- _position_reference=multi_dispense_properties.positionReference,
729
- _offset=multi_dispense_properties.offset,
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
- by_tip_type_setting: SharedByTipTypeSetting,
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(by_tip_type_setting.aspirate),
751
- _dispense=build_single_dispense_properties(by_tip_type_setting.singleDispense),
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
- by_tip_type_setting.multiDispense
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
- sources_list: List[Well]
23
- destinations_list: List[Well]
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
- flat_dests_list = validation.ensure_valid_flat_wells_list_for_transfer_v2(dest)
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
- sources_list=flat_sources_list,
87
- destinations_list=flat_dests_list,
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,