opentrons 8.5.0a4__py2.py3-none-any.whl → 8.5.0a7__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/protocol_api/_transfer_liquid_validation.py +31 -6
- opentrons/protocol_api/core/engine/instrument.py +191 -148
- opentrons/protocol_api/core/engine/transfer_components_executor.py +114 -40
- opentrons/protocol_api/core/instrument.py +9 -3
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +9 -3
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +9 -3
- opentrons/protocol_api/instrument_context.py +84 -16
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +37 -27
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/METADATA +4 -4
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/RECORD +14 -14
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/LICENSE +0 -0
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/WHEEL +0 -0
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/entry_points.txt +0 -0
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/top_level.txt +0 -0
|
@@ -39,7 +39,10 @@ from .config import Clearances
|
|
|
39
39
|
from .disposal_locations import TrashBin, WasteChute
|
|
40
40
|
from ._nozzle_layout import NozzleLayout
|
|
41
41
|
from ._liquid import LiquidClass
|
|
42
|
-
from ._transfer_liquid_validation import
|
|
42
|
+
from ._transfer_liquid_validation import (
|
|
43
|
+
verify_and_normalize_transfer_args,
|
|
44
|
+
resolve_keep_last_tip,
|
|
45
|
+
)
|
|
43
46
|
from . import labware, validation
|
|
44
47
|
from ..protocols.advanced_control.transfers.common import (
|
|
45
48
|
TransferTipPolicyV2,
|
|
@@ -1774,7 +1777,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1774
1777
|
for cmd in plan:
|
|
1775
1778
|
getattr(self, cmd["method"])(*cmd["args"], **cmd["kwargs"])
|
|
1776
1779
|
|
|
1777
|
-
@requires_version(2,
|
|
1780
|
+
@requires_version(2, 24)
|
|
1778
1781
|
def transfer_with_liquid_class(
|
|
1779
1782
|
self,
|
|
1780
1783
|
liquid_class: LiquidClass,
|
|
@@ -1795,6 +1798,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1795
1798
|
] = None,
|
|
1796
1799
|
return_tip: bool = False,
|
|
1797
1800
|
group_wells: bool = True,
|
|
1801
|
+
keep_last_tip: Optional[bool] = None,
|
|
1798
1802
|
) -> InstrumentContext:
|
|
1799
1803
|
"""Move a particular type of liquid from one well or group of wells to another.
|
|
1800
1804
|
|
|
@@ -1830,6 +1834,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1830
1834
|
:param group_wells: For multi-channel transfers only. If set to ``True``, group together contiguous wells
|
|
1831
1835
|
given into a single transfer step, taking into account the tip configuration. If ``False``, target
|
|
1832
1836
|
each well given with the primary nozzle. Defaults to ``True``.
|
|
1837
|
+
:param keep_last_tip: When ``True``, the pipette keeps the last tip used in the transfer attached. When
|
|
1838
|
+
``False``, the last tip will be dropped or returned. If not set, behavior depends on the value of
|
|
1839
|
+
``new_tip``. ``new_tip="never"`` keeps the tip, and all other values of ``new_tip`` drop or return the tip.
|
|
1833
1840
|
|
|
1834
1841
|
:meta private:
|
|
1835
1842
|
"""
|
|
@@ -1844,7 +1851,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1844
1851
|
source=source,
|
|
1845
1852
|
dest=dest,
|
|
1846
1853
|
tip_policy=new_tip,
|
|
1847
|
-
|
|
1854
|
+
last_tip_well=self._last_tip_picked_up_from,
|
|
1848
1855
|
tip_racks=self._tip_racks,
|
|
1849
1856
|
nozzle_map=self._core.get_nozzle_map(),
|
|
1850
1857
|
group_wells_for_multi_channel=group_wells,
|
|
@@ -1853,6 +1860,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1853
1860
|
trash_location if trash_location is not None else self.trash_container
|
|
1854
1861
|
),
|
|
1855
1862
|
)
|
|
1863
|
+
verified_keep_last_tip = resolve_keep_last_tip(
|
|
1864
|
+
keep_last_tip, transfer_args.tip_policy
|
|
1865
|
+
)
|
|
1856
1866
|
|
|
1857
1867
|
verified_dest: Union[
|
|
1858
1868
|
List[Tuple[types.Location, WellCore]], TrashBin, WasteChute
|
|
@@ -1881,7 +1891,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1881
1891
|
destination=dest,
|
|
1882
1892
|
),
|
|
1883
1893
|
):
|
|
1884
|
-
self._core.transfer_with_liquid_class(
|
|
1894
|
+
last_tip_location = self._core.transfer_with_liquid_class(
|
|
1885
1895
|
liquid_class=liquid_class,
|
|
1886
1896
|
volume=volume,
|
|
1887
1897
|
source=[
|
|
@@ -1899,10 +1909,23 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1899
1909
|
),
|
|
1900
1910
|
trash_location=transfer_args.trash_location,
|
|
1901
1911
|
return_tip=return_tip,
|
|
1912
|
+
keep_last_tip=verified_keep_last_tip,
|
|
1913
|
+
last_tip_location=transfer_args.last_tip_location,
|
|
1902
1914
|
)
|
|
1915
|
+
|
|
1916
|
+
# TODO(jbl 2025-06-23) last_tip_picked_up_from should be removed from the public context and
|
|
1917
|
+
# moved to the engine core or engine as a simpler and more holistic solution
|
|
1918
|
+
if last_tip_location is not None:
|
|
1919
|
+
tip_rack_loc, tip_well_core = last_tip_location
|
|
1920
|
+
self._last_tip_picked_up_from = tip_rack_loc.labware.as_labware()[
|
|
1921
|
+
tip_well_core.get_name()
|
|
1922
|
+
]
|
|
1923
|
+
else:
|
|
1924
|
+
self._last_tip_picked_up_from = None
|
|
1925
|
+
|
|
1903
1926
|
return self
|
|
1904
1927
|
|
|
1905
|
-
@requires_version(2,
|
|
1928
|
+
@requires_version(2, 24)
|
|
1906
1929
|
def distribute_with_liquid_class(
|
|
1907
1930
|
self,
|
|
1908
1931
|
liquid_class: LiquidClass,
|
|
@@ -1917,6 +1940,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1917
1940
|
] = None,
|
|
1918
1941
|
return_tip: bool = False,
|
|
1919
1942
|
group_wells: bool = True,
|
|
1943
|
+
keep_last_tip: Optional[bool] = None,
|
|
1920
1944
|
) -> InstrumentContext:
|
|
1921
1945
|
"""
|
|
1922
1946
|
Distribute a particular type of liquid from one well to a group of wells.
|
|
@@ -1939,6 +1963,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1939
1963
|
|
|
1940
1964
|
- ``"once"``: Use one tip for the entire command.
|
|
1941
1965
|
- ``"never"``: Do not pick up or drop tips at all.
|
|
1966
|
+
- ``"always"``: Pick up a new tip before every aspirate.
|
|
1942
1967
|
|
|
1943
1968
|
See :ref:`param-tip-handling` for details.
|
|
1944
1969
|
|
|
@@ -1949,6 +1974,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1949
1974
|
:param group_wells: For multi-channel transfers only. If set to ``True``, group together contiguous wells
|
|
1950
1975
|
given into a single transfer step, taking into account the tip configuration. If ``False``, target
|
|
1951
1976
|
each well given with the primary nozzle. Defaults to ``True``.
|
|
1977
|
+
:param keep_last_tip: When ``True``, the pipette keeps the last tip used in the distribute attached. When
|
|
1978
|
+
``False``, the last tip will be dropped or returned. If not set, behavior depends on the value of
|
|
1979
|
+
``new_tip``. ``new_tip="never"`` keeps the tip, and all other values of ``new_tip`` drop or return the tip.
|
|
1952
1980
|
|
|
1953
1981
|
:meta private:
|
|
1954
1982
|
"""
|
|
@@ -1963,7 +1991,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1963
1991
|
source=source,
|
|
1964
1992
|
dest=dest,
|
|
1965
1993
|
tip_policy=new_tip,
|
|
1966
|
-
|
|
1994
|
+
last_tip_well=self._last_tip_picked_up_from,
|
|
1967
1995
|
tip_racks=self._tip_racks,
|
|
1968
1996
|
nozzle_map=self._core.get_nozzle_map(),
|
|
1969
1997
|
group_wells_for_multi_channel=group_wells,
|
|
@@ -1972,6 +2000,10 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1972
2000
|
trash_location if trash_location is not None else self.trash_container
|
|
1973
2001
|
),
|
|
1974
2002
|
)
|
|
2003
|
+
verified_keep_last_tip = resolve_keep_last_tip(
|
|
2004
|
+
keep_last_tip, transfer_args.tip_policy
|
|
2005
|
+
)
|
|
2006
|
+
|
|
1975
2007
|
if isinstance(transfer_args.dest, (TrashBin, WasteChute)):
|
|
1976
2008
|
raise ValueError(
|
|
1977
2009
|
"distribute_with_liquid_class() does not support trash bin or waste chute"
|
|
@@ -1985,11 +2017,12 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1985
2017
|
if transfer_args.tip_policy not in [
|
|
1986
2018
|
TransferTipPolicyV2.ONCE,
|
|
1987
2019
|
TransferTipPolicyV2.NEVER,
|
|
2020
|
+
TransferTipPolicyV2.ALWAYS,
|
|
1988
2021
|
]:
|
|
1989
2022
|
raise ValueError(
|
|
1990
2023
|
f"Incompatible `new_tip` value of {new_tip}."
|
|
1991
2024
|
f" `distribute_with_liquid_class()` only supports `new_tip` values of"
|
|
1992
|
-
f" 'once' and '
|
|
2025
|
+
f" 'once', 'never' and 'always'."
|
|
1993
2026
|
)
|
|
1994
2027
|
|
|
1995
2028
|
verified_source = transfer_args.source[0]
|
|
@@ -2003,7 +2036,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2003
2036
|
destination=dest,
|
|
2004
2037
|
),
|
|
2005
2038
|
):
|
|
2006
|
-
self._core.distribute_with_liquid_class(
|
|
2039
|
+
last_tip_location = self._core.distribute_with_liquid_class(
|
|
2007
2040
|
liquid_class=liquid_class,
|
|
2008
2041
|
volume=volume,
|
|
2009
2042
|
source=(
|
|
@@ -2024,10 +2057,23 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2024
2057
|
),
|
|
2025
2058
|
trash_location=transfer_args.trash_location,
|
|
2026
2059
|
return_tip=return_tip,
|
|
2060
|
+
keep_last_tip=verified_keep_last_tip,
|
|
2061
|
+
last_tip_location=transfer_args.last_tip_location,
|
|
2027
2062
|
)
|
|
2063
|
+
|
|
2064
|
+
# TODO(jbl 2025-06-23) last_tip_picked_up_from should be removed from the public context and
|
|
2065
|
+
# moved to the engine core or engine as a simpler and more holistic solution
|
|
2066
|
+
if last_tip_location is not None:
|
|
2067
|
+
tip_rack_loc, tip_well_core = last_tip_location
|
|
2068
|
+
self._last_tip_picked_up_from = tip_rack_loc.labware.as_labware()[
|
|
2069
|
+
tip_well_core.get_name()
|
|
2070
|
+
]
|
|
2071
|
+
else:
|
|
2072
|
+
self._last_tip_picked_up_from = None
|
|
2073
|
+
|
|
2028
2074
|
return self
|
|
2029
2075
|
|
|
2030
|
-
@requires_version(2,
|
|
2076
|
+
@requires_version(2, 24)
|
|
2031
2077
|
def consolidate_with_liquid_class(
|
|
2032
2078
|
self,
|
|
2033
2079
|
liquid_class: LiquidClass,
|
|
@@ -2042,6 +2088,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2042
2088
|
] = None,
|
|
2043
2089
|
return_tip: bool = False,
|
|
2044
2090
|
group_wells: bool = True,
|
|
2091
|
+
keep_last_tip: Optional[bool] = None,
|
|
2045
2092
|
) -> InstrumentContext:
|
|
2046
2093
|
"""
|
|
2047
2094
|
Consolidate a particular type of liquid from a group of wells to one well.
|
|
@@ -2065,6 +2112,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2065
2112
|
|
|
2066
2113
|
- ``"once"``: Use one tip for the entire command.
|
|
2067
2114
|
- ``"never"``: Do not pick up or drop tips at all.
|
|
2115
|
+
- ``"always"``: Pick up a new tip before going back to source for refilling after a dispense.
|
|
2068
2116
|
|
|
2069
2117
|
See :ref:`param-tip-handling` for details.
|
|
2070
2118
|
|
|
@@ -2075,6 +2123,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2075
2123
|
:param group_wells: For multi-channel transfers only. If set to ``True``, group together contiguous wells
|
|
2076
2124
|
given into a single transfer step, taking into account the tip configuration. If ``False``, target
|
|
2077
2125
|
each well given with the primary nozzle. Defaults to ``True``.
|
|
2126
|
+
:param keep_last_tip: When ``True``, the pipette keeps the last tip used in the consolidate attached. When
|
|
2127
|
+
``False``, the last tip will be dropped or returned. If not set, behavior depends on the value of
|
|
2128
|
+
``new_tip``. ``new_tip="never"`` keeps the tip, and all other values of ``new_tip`` drop or return the tip.
|
|
2078
2129
|
|
|
2079
2130
|
:meta private:
|
|
2080
2131
|
"""
|
|
@@ -2089,7 +2140,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2089
2140
|
source=source,
|
|
2090
2141
|
dest=dest,
|
|
2091
2142
|
tip_policy=new_tip,
|
|
2092
|
-
|
|
2143
|
+
last_tip_well=self._last_tip_picked_up_from,
|
|
2093
2144
|
tip_racks=self._tip_racks,
|
|
2094
2145
|
nozzle_map=self._core.get_nozzle_map(),
|
|
2095
2146
|
group_wells_for_multi_channel=group_wells,
|
|
@@ -2098,6 +2149,10 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2098
2149
|
trash_location if trash_location is not None else self.trash_container
|
|
2099
2150
|
),
|
|
2100
2151
|
)
|
|
2152
|
+
verified_keep_last_tip = resolve_keep_last_tip(
|
|
2153
|
+
keep_last_tip, transfer_args.tip_policy
|
|
2154
|
+
)
|
|
2155
|
+
|
|
2101
2156
|
verified_dest: Union[Tuple[types.Location, WellCore], TrashBin, WasteChute]
|
|
2102
2157
|
if isinstance(transfer_args.dest, (TrashBin, WasteChute)):
|
|
2103
2158
|
verified_dest = transfer_args.dest
|
|
@@ -2114,11 +2169,12 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2114
2169
|
if transfer_args.tip_policy not in [
|
|
2115
2170
|
TransferTipPolicyV2.ONCE,
|
|
2116
2171
|
TransferTipPolicyV2.NEVER,
|
|
2172
|
+
TransferTipPolicyV2.ALWAYS,
|
|
2117
2173
|
]:
|
|
2118
2174
|
raise ValueError(
|
|
2119
2175
|
f"Incompatible `new_tip` value of {new_tip}."
|
|
2120
2176
|
f" `consolidate_with_liquid_class()` only supports `new_tip` values of"
|
|
2121
|
-
f" 'once' and '
|
|
2177
|
+
f" 'once', 'never' and 'always'."
|
|
2122
2178
|
)
|
|
2123
2179
|
|
|
2124
2180
|
with publisher.publish_context(
|
|
@@ -2131,7 +2187,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2131
2187
|
destination=dest,
|
|
2132
2188
|
),
|
|
2133
2189
|
):
|
|
2134
|
-
self._core.consolidate_with_liquid_class(
|
|
2190
|
+
last_tip_location = self._core.consolidate_with_liquid_class(
|
|
2135
2191
|
liquid_class=liquid_class,
|
|
2136
2192
|
volume=volume,
|
|
2137
2193
|
source=[
|
|
@@ -2149,7 +2205,20 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2149
2205
|
),
|
|
2150
2206
|
trash_location=transfer_args.trash_location,
|
|
2151
2207
|
return_tip=return_tip,
|
|
2208
|
+
keep_last_tip=verified_keep_last_tip,
|
|
2209
|
+
last_tip_location=transfer_args.last_tip_location,
|
|
2152
2210
|
)
|
|
2211
|
+
|
|
2212
|
+
# TODO(jbl 2025-06-23) last_tip_picked_up_from should be removed from the public context and
|
|
2213
|
+
# moved to the engine core or engine as a simpler and more holistic solution
|
|
2214
|
+
if last_tip_location is not None:
|
|
2215
|
+
tip_rack_loc, tip_well_core = last_tip_location
|
|
2216
|
+
self._last_tip_picked_up_from = tip_rack_loc.labware.as_labware()[
|
|
2217
|
+
tip_well_core.get_name()
|
|
2218
|
+
]
|
|
2219
|
+
else:
|
|
2220
|
+
self._last_tip_picked_up_from = None
|
|
2221
|
+
|
|
2153
2222
|
return self
|
|
2154
2223
|
|
|
2155
2224
|
@requires_version(2, 0)
|
|
@@ -2574,10 +2643,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2574
2643
|
From API version 2.15 to 2.22, this property returned an internal name for Flex
|
|
2575
2644
|
pipettes. (e.g., ``"p1000_single_flex"``).
|
|
2576
2645
|
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
``"flex_1channel_1000"``).
|
|
2646
|
+
In API version 2.23 and later, this property returns the Python Protocol API
|
|
2647
|
+
:ref:`load name <new-pipette-models>` of Flex pipettes (e.g.,
|
|
2648
|
+
``"flex_1channel_1000"``).
|
|
2581
2649
|
"""
|
|
2582
2650
|
return self._core.get_pipette_name()
|
|
2583
2651
|
|
|
@@ -4,7 +4,10 @@ from __future__ import annotations
|
|
|
4
4
|
from typing import Literal, Sequence, List, Optional, TYPE_CHECKING
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
|
|
7
|
-
from opentrons.protocol_engine.errors import
|
|
7
|
+
from opentrons.protocol_engine.errors import (
|
|
8
|
+
LiquidHeightUnknownError,
|
|
9
|
+
IncompleteLabwareDefinitionError,
|
|
10
|
+
)
|
|
8
11
|
from opentrons.protocol_engine.state._well_math import (
|
|
9
12
|
wells_covered_by_pipette_configuration,
|
|
10
13
|
)
|
|
@@ -25,28 +28,24 @@ class LocationCheckDescriptors:
|
|
|
25
28
|
|
|
26
29
|
def raise_if_location_inside_liquid(
|
|
27
30
|
location: Location,
|
|
28
|
-
well_location: Location,
|
|
29
31
|
well_core: WellCore,
|
|
30
32
|
location_check_descriptors: LocationCheckDescriptors,
|
|
31
33
|
logger: Logger,
|
|
32
34
|
) -> None:
|
|
33
35
|
"""Raise an error if the location in question would be inside the liquid.
|
|
34
36
|
|
|
35
|
-
This checker will raise an error if
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
This checker will raise an error if we can find the liquid height
|
|
38
|
+
AND the location in question is below this height.
|
|
39
|
+
|
|
40
|
+
If we can't find the liquid height, then we simply log the details and no error is raised.
|
|
39
41
|
"""
|
|
40
|
-
if location.point.z < well_location.point.z:
|
|
41
|
-
raise RuntimeError(
|
|
42
|
-
f"Received {location_check_descriptors.location_type} location of {location}"
|
|
43
|
-
f" and {location_check_descriptors.pipetting_action} location of {well_location}."
|
|
44
|
-
f" {location_check_descriptors.location_type.capitalize()} location z should not be lower"
|
|
45
|
-
f" than the {location_check_descriptors.pipetting_action} location z."
|
|
46
|
-
)
|
|
47
42
|
try:
|
|
48
43
|
liquid_height_from_bottom = well_core.current_liquid_height()
|
|
49
|
-
except LiquidHeightUnknownError:
|
|
44
|
+
except (IncompleteLabwareDefinitionError, LiquidHeightUnknownError):
|
|
45
|
+
# IncompleteLabwareDefinitionError is raised when there's no inner geometry
|
|
46
|
+
# defined for the well. So, we can't find the liquid height even if liquid volume is known.
|
|
47
|
+
# LiquidHeightUnknownError is raised when we don't have liquid volume info
|
|
48
|
+
# and no probing has been done either.
|
|
50
49
|
liquid_height_from_bottom = None
|
|
51
50
|
if isinstance(liquid_height_from_bottom, (int, float)):
|
|
52
51
|
if liquid_height_from_bottom + well_core.get_bottom(0).z > location.point.z:
|
|
@@ -59,11 +58,12 @@ def raise_if_location_inside_liquid(
|
|
|
59
58
|
# We could raise an error here but that would restrict the use of
|
|
60
59
|
# liquid classes-based transfer to only when LPD is enabled or when liquids are
|
|
61
60
|
# loaded in protocols using `load_liquid`. This can be quite restrictive
|
|
62
|
-
# so we will not raise but just log
|
|
63
|
-
logger.
|
|
61
|
+
# so we will not raise but just log the details.
|
|
62
|
+
logger.info(
|
|
64
63
|
f"Could not verify height of liquid in well {well_core.get_display_name()}, either"
|
|
65
|
-
f" because the liquid in this well has not been probed or
|
|
66
|
-
f" liquid was not loaded in this well using `load_liquid
|
|
64
|
+
f" because the liquid in this well has not been probed or"
|
|
65
|
+
f" liquid was not loaded in this well using `load_liquid` or"
|
|
66
|
+
f" inner geometry is not available for the target well."
|
|
67
67
|
f" Proceeding without verifying if {location_check_descriptors.location_type}"
|
|
68
68
|
f" location is outside the liquid."
|
|
69
69
|
)
|
|
@@ -72,6 +72,7 @@ def raise_if_location_inside_liquid(
|
|
|
72
72
|
def group_wells_for_multi_channel_transfer(
|
|
73
73
|
targets: Sequence[Well],
|
|
74
74
|
nozzle_map: NozzleMapInterface,
|
|
75
|
+
target_name: Literal["source", "destination"],
|
|
75
76
|
) -> List[Well]:
|
|
76
77
|
"""Takes a list of wells and a nozzle map and returns a list of target wells to address every well given
|
|
77
78
|
|
|
@@ -94,13 +95,20 @@ def group_wells_for_multi_channel_transfer(
|
|
|
94
95
|
or (configuration == NozzleConfigurationType.ROW and active_nozzles == 12)
|
|
95
96
|
or active_nozzles == 96
|
|
96
97
|
):
|
|
97
|
-
return _group_wells_for_nozzle_configuration(
|
|
98
|
+
return _group_wells_for_nozzle_configuration(
|
|
99
|
+
list(targets), nozzle_map, target_name
|
|
100
|
+
)
|
|
98
101
|
else:
|
|
99
|
-
raise ValueError(
|
|
102
|
+
raise ValueError(
|
|
103
|
+
"Unsupported nozzle configuration for well grouping. Set group_wells to False"
|
|
104
|
+
" to only target wells with the primary nozzle for this configuration."
|
|
105
|
+
)
|
|
100
106
|
|
|
101
107
|
|
|
102
108
|
def _group_wells_for_nozzle_configuration( # noqa: C901
|
|
103
|
-
targets: List[Well],
|
|
109
|
+
targets: List[Well],
|
|
110
|
+
nozzle_map: NozzleMapInterface,
|
|
111
|
+
target_name: Literal["source", "destination"],
|
|
104
112
|
) -> List[Well]:
|
|
105
113
|
"""Groups wells together for a column, row, or full 96 configuration and returns a reduced list of target wells."""
|
|
106
114
|
grouped_wells = []
|
|
@@ -132,8 +140,9 @@ def _group_wells_for_nozzle_configuration( # noqa: C901
|
|
|
132
140
|
if active_wells_covered:
|
|
133
141
|
if well.parent != active_labware:
|
|
134
142
|
raise ValueError(
|
|
135
|
-
"Could not
|
|
136
|
-
"
|
|
143
|
+
f"Could not group {target_name} wells to match pipette's nozzle configuration. Ensure that the"
|
|
144
|
+
" wells are ordered correctly (e.g. rows() for a row layout or columns() for a column layout), or"
|
|
145
|
+
" set group_wells to False to only target wells with the primary nozzle."
|
|
137
146
|
)
|
|
138
147
|
|
|
139
148
|
if well.well_name in active_wells_covered:
|
|
@@ -165,8 +174,9 @@ def _group_wells_for_nozzle_configuration( # noqa: C901
|
|
|
165
174
|
alternate_384_well_coverage_count += 1
|
|
166
175
|
else:
|
|
167
176
|
raise ValueError(
|
|
168
|
-
"Could not
|
|
169
|
-
"
|
|
177
|
+
f"Could not group {target_name} wells to match pipette's nozzle configuration. Ensure that the"
|
|
178
|
+
" wells are ordered correctly (e.g. rows() for a row layout or columns() for a column layout), or"
|
|
179
|
+
" set group_wells to False to only target wells with the primary nozzle."
|
|
170
180
|
)
|
|
171
181
|
# If we have no active wells covered to account for, add a new target well and list of covered wells to check
|
|
172
182
|
else:
|
|
@@ -193,8 +203,8 @@ def _group_wells_for_nozzle_configuration( # noqa: C901
|
|
|
193
203
|
|
|
194
204
|
if active_wells_covered:
|
|
195
205
|
raise ValueError(
|
|
196
|
-
"
|
|
197
|
-
f"
|
|
206
|
+
f"Pipette will access {target_name} wells not provided in the liquid handling command."
|
|
207
|
+
f" Set group_wells to False or include these wells: {active_wells_covered}"
|
|
198
208
|
)
|
|
199
209
|
|
|
200
210
|
# If we reversed the lookup of wells, reverse the grouped wells we will return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: opentrons
|
|
3
|
-
Version: 8.5.
|
|
3
|
+
Version: 8.5.0a7
|
|
4
4
|
Summary: The Opentrons API is a simple framework designed to make writing automated biology lab protocols easy.
|
|
5
5
|
Author: Opentrons
|
|
6
6
|
Author-email: engineering@opentrons.com
|
|
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
21
21
|
Classifier: Topic :: Scientific/Engineering
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
License-File: ../LICENSE
|
|
24
|
-
Requires-Dist: opentrons-shared-data (==8.5.
|
|
24
|
+
Requires-Dist: opentrons-shared-data (==8.5.0a7)
|
|
25
25
|
Requires-Dist: aionotify (==0.3.1)
|
|
26
26
|
Requires-Dist: anyio (<4.0.0,>=3.6.1)
|
|
27
27
|
Requires-Dist: jsonschema (<4.18.0,>=3.0.1)
|
|
@@ -35,9 +35,9 @@ Requires-Dist: pyusb (==1.2.1)
|
|
|
35
35
|
Requires-Dist: packaging (>=21.0)
|
|
36
36
|
Requires-Dist: importlib-metadata (>=1.0) ; python_version < "3.8"
|
|
37
37
|
Provides-Extra: flex-hardware
|
|
38
|
-
Requires-Dist: opentrons-hardware[flex] (==8.5.
|
|
38
|
+
Requires-Dist: opentrons-hardware[flex] (==8.5.0a7) ; extra == 'flex-hardware'
|
|
39
39
|
Provides-Extra: ot2-hardware
|
|
40
|
-
Requires-Dist: opentrons-hardware (==8.5.
|
|
40
|
+
Requires-Dist: opentrons-hardware (==8.5.0a7) ; extra == 'ot2-hardware'
|
|
41
41
|
|
|
42
42
|
.. _Full API Documentation: http://docs.opentrons.com
|
|
43
43
|
|
|
@@ -223,13 +223,13 @@ opentrons/protocol_api/_liquid_properties.py,sha256=DHdDHoset72mKq2sLaf355Zz1Xds
|
|
|
223
223
|
opentrons/protocol_api/_nozzle_layout.py,sha256=-WA71bRDISs9bLwHdWqAyM7HBc53sOA8_BOVqYsuN3g,1095
|
|
224
224
|
opentrons/protocol_api/_parameter_context.py,sha256=dvGMVObWDSERrXfTKSIwc4YeIdF_RD-q8ASNaSBTcxw,12967
|
|
225
225
|
opentrons/protocol_api/_parameters.py,sha256=BGH50BFawoNnh7NRDh0tRrNncdwz_Ta25tbQfwtlYoM,1298
|
|
226
|
-
opentrons/protocol_api/_transfer_liquid_validation.py,sha256=
|
|
226
|
+
opentrons/protocol_api/_transfer_liquid_validation.py,sha256=wYuvW3UwF0JcK_Hmxim-Fmy1VkSR1TLBW-7u59XADL0,4443
|
|
227
227
|
opentrons/protocol_api/_types.py,sha256=6tPCuOmZ5GNtu-24zyY6O-KkXEqzhTAlHlKHQH3Dvzs,1413
|
|
228
228
|
opentrons/protocol_api/config.py,sha256=r9lyvXjagTX_g3q5FGURPpcz2IA9sSF7Oa_1mKx-7cw,625
|
|
229
229
|
opentrons/protocol_api/create_protocol_context.py,sha256=wwsZje0L__oDnu1Yrihau320_f-ASloR9eL1QCtkOh8,7612
|
|
230
230
|
opentrons/protocol_api/deck.py,sha256=94vFceg1SC1bAGd7TvC1ZpYwnJR-VlzurEZ6jkacYeg,8910
|
|
231
231
|
opentrons/protocol_api/disposal_locations.py,sha256=NRiSGmDR0LnbyEkWSOM-o64uR2fUoB1NWJG7Y7SsJSs,7920
|
|
232
|
-
opentrons/protocol_api/instrument_context.py,sha256=
|
|
232
|
+
opentrons/protocol_api/instrument_context.py,sha256=oV6cdU-L0vHqzjICe3mKE3bRXs8TmGXacpjTHj--oU0,138939
|
|
233
233
|
opentrons/protocol_api/labware.py,sha256=AhL1JX10Xt-mpB85CAnEOBvz9r5v3xncJuLMkiY1FPM,60934
|
|
234
234
|
opentrons/protocol_api/module_contexts.py,sha256=Mzut2a92Gcv23wFPdNVU9fj2P--7WDqBx27xAJ7z8eo,48361
|
|
235
235
|
opentrons/protocol_api/module_validation_and_errors.py,sha256=XL_m72P8rcvGO2fynY7UzXLcpGuI6X4s0V6Xf735Iyc,1464
|
|
@@ -239,7 +239,7 @@ opentrons/protocol_api/validation.py,sha256=73QwpdK5337yu9g8jvpHHizOD0Mf3m6Wr9S8
|
|
|
239
239
|
opentrons/protocol_api/core/__init__.py,sha256=-g74o8OtBB0LmmOvwkRvPgrHt7fF7T8FRHDj-x_-Onk,736
|
|
240
240
|
opentrons/protocol_api/core/common.py,sha256=q9ZbfpRdBvB3iDAOCyONtupvkYP5n1hjE-bwqGcwP_U,1172
|
|
241
241
|
opentrons/protocol_api/core/core_map.py,sha256=gq3CIYPxuPvozf8yj8FprqBfs3e4ZJGQ6s0ViPbwV08,1757
|
|
242
|
-
opentrons/protocol_api/core/instrument.py,sha256=
|
|
242
|
+
opentrons/protocol_api/core/instrument.py,sha256=RCLvsoh3ybHIRxVFQaKEdcxbUA72q8n5Srq2pPhT39s,14202
|
|
243
243
|
opentrons/protocol_api/core/labware.py,sha256=-ZOjkalikXCV3ptehKCNaWGAdKxIdwne8LRFQW9NAm4,4290
|
|
244
244
|
opentrons/protocol_api/core/module.py,sha256=z2STDyqqxZX3y6UyJVDnajeFXMEn1ie2NRBYHhry_XE,13838
|
|
245
245
|
opentrons/protocol_api/core/protocol.py,sha256=4ixn9qY0ca0GYyhTkSdKKm0slFdtzY5mXG_lgjGflns,9089
|
|
@@ -249,7 +249,7 @@ opentrons/protocol_api/core/well_grid.py,sha256=BU28DKaBgEU_JdZ6pEzrwNxmuh6TkO4z
|
|
|
249
249
|
opentrons/protocol_api/core/engine/__init__.py,sha256=B_5T7zgkWDb1mXPg4NbT-wBkQaK-WVokMMnJRNu7xiM,582
|
|
250
250
|
opentrons/protocol_api/core/engine/deck_conflict.py,sha256=q3JViIAHDthIqq6ce7h2gxw3CHRfYsm5kkwzuXB-Gnc,12334
|
|
251
251
|
opentrons/protocol_api/core/engine/exceptions.py,sha256=aZgNrmYEeuPZm21nX_KZYtvyjv5h_zPjxxgPkEV7_bw,725
|
|
252
|
-
opentrons/protocol_api/core/engine/instrument.py,sha256=
|
|
252
|
+
opentrons/protocol_api/core/engine/instrument.py,sha256=KgRDIq50Nah2lcMuOtcpDTjckt9ycqWtQ37u6GfpEnQ,103560
|
|
253
253
|
opentrons/protocol_api/core/engine/labware.py,sha256=1xvzguNnK7aecFLiJK0gtRrZ5kpwtzLS73HnKvdJ5lc,8413
|
|
254
254
|
opentrons/protocol_api/core/engine/load_labware_params.py,sha256=I4Cb8rqpBhmykQuZE8QRG802APrdCy_TYS88rm_9oGA,7159
|
|
255
255
|
opentrons/protocol_api/core/engine/module_core.py,sha256=MLPgYSRJHUZPZ9rTLvsg3GlpL5b6-Pjk5UBgXCGrL6U,30994
|
|
@@ -259,12 +259,12 @@ opentrons/protocol_api/core/engine/point_calculations.py,sha256=C2eF0fvJQGMqQv3D
|
|
|
259
259
|
opentrons/protocol_api/core/engine/protocol.py,sha256=OvE8kDONIR0z5S-FV10KUw5v5_HskPk7aqFNyTSUasc,46919
|
|
260
260
|
opentrons/protocol_api/core/engine/robot.py,sha256=bzUt23NG-clD-9-QFsV_6nm3fMgSmvYEG9DyyZI1xgw,5366
|
|
261
261
|
opentrons/protocol_api/core/engine/stringify.py,sha256=GwFgEhFMk-uPfFQhQG_2mkaf4cxaItiY8RW7rZwiooQ,2794
|
|
262
|
-
opentrons/protocol_api/core/engine/transfer_components_executor.py,sha256=
|
|
262
|
+
opentrons/protocol_api/core/engine/transfer_components_executor.py,sha256=j5V43ns3pmpH5mtbaxKLzyey9je1-FDd9JFc26nMVNQ,43320
|
|
263
263
|
opentrons/protocol_api/core/engine/well.py,sha256=IaaFK-3hoUfabfn_twIT7zcAynhzAmRxDnvABss2szo,8923
|
|
264
264
|
opentrons/protocol_api/core/legacy/__init__.py,sha256=_9jCJNKG3SlS_vljVu8HHkZmtLf4F-f-JHALLF5d5go,401
|
|
265
265
|
opentrons/protocol_api/core/legacy/deck.py,sha256=qHqcGo-Kdkl9L1aOE0pwrm9tsAnwkXbt4rIOr_VEP-s,13955
|
|
266
266
|
opentrons/protocol_api/core/legacy/labware_offset_provider.py,sha256=2DLIby9xmUrwLb2ht8hZbvNTxqPhNzWijd7yCb2cqP8,3783
|
|
267
|
-
opentrons/protocol_api/core/legacy/legacy_instrument_core.py,sha256=
|
|
267
|
+
opentrons/protocol_api/core/legacy/legacy_instrument_core.py,sha256=Q4zYHMElPRSRG4dcm4eXQ0sj5I8ZpuJwwtfJeTlYv4E,27010
|
|
268
268
|
opentrons/protocol_api/core/legacy/legacy_labware_core.py,sha256=WQOgtMlq--zv0Ch7mmraYr9rQBT4ie2zHqwgamBq9J8,8606
|
|
269
269
|
opentrons/protocol_api/core/legacy/legacy_module_core.py,sha256=tUhj88NKBMjCmCg6wjh1e2HX4d5hxjh8ZeJiYXaTaGY,23111
|
|
270
270
|
opentrons/protocol_api/core/legacy/legacy_protocol_core.py,sha256=fodiDwsBi1_Yd6Hgf8Kx-iTvky_J6WHmGhwmeRBHqmE,23702
|
|
@@ -273,7 +273,7 @@ opentrons/protocol_api/core/legacy/load_info.py,sha256=r-WaH5ZJb3TRCp_zvbMMh0P4B
|
|
|
273
273
|
opentrons/protocol_api/core/legacy/module_geometry.py,sha256=lvWFHZ81-JFw-1VZUW1R3yUIb59xpXT6H3jwlRintRo,21082
|
|
274
274
|
opentrons/protocol_api/core/legacy/well_geometry.py,sha256=n5bEsvYZXXTAqYSAqlXd5t40bUPPrJ2Oj2frBZafQHA,4719
|
|
275
275
|
opentrons/protocol_api/core/legacy_simulator/__init__.py,sha256=m9bLHGDJ6LSYC2WPm8tpOuu0zWSOPIrlybQgjRQBw9k,647
|
|
276
|
-
opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py,sha256=
|
|
276
|
+
opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py,sha256=_C-9nxssbYXh5tuQdM-wqL3lptcuHPlXZM3tiO-Qm9A,23449
|
|
277
277
|
opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py,sha256=28HrrHzeUfnGKXpZqQ-VM8WbPiadqVhKj2S9y33q6Lo,2910
|
|
278
278
|
opentrons/protocol_engine/__init__.py,sha256=UPSk7MbidkiSH_h4V3yxMvyTePKpRr5DM9-wfkJrlSo,4094
|
|
279
279
|
opentrons/protocol_engine/create_protocol_engine.py,sha256=tfDIsC7_JKlRiCXPB_8tuxRsssU6o0ViRmWbGPtX9QA,7582
|
|
@@ -526,7 +526,7 @@ opentrons/protocols/advanced_control/mix.py,sha256=GobQ9E6F2gARjfhNp2xdyWQXFBSwO
|
|
|
526
526
|
opentrons/protocols/advanced_control/transfers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
527
527
|
opentrons/protocols/advanced_control/transfers/common.py,sha256=Mal5AKO35nCXqjwxR6tDityEoLYg09Yty3Jv1fgOHnQ,5498
|
|
528
528
|
opentrons/protocols/advanced_control/transfers/transfer.py,sha256=-vE1uZq2BqAagSGeiuTxTyL1wT6fza_fwkO_V_OMMFc,37318
|
|
529
|
-
opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py,sha256=
|
|
529
|
+
opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py,sha256=uHUQJLYzDqA4pzZyIbR00PKRN5FMc6A6JgPBA9wSKTg,9713
|
|
530
530
|
opentrons/protocols/api_support/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
531
531
|
opentrons/protocols/api_support/constants.py,sha256=pI_zJ8oORr6FUOaF508ttll3KOIYqRRgcwVFwnqZuqc,262
|
|
532
532
|
opentrons/protocols/api_support/deck_type.py,sha256=cBxm-IQqFyL1QtYTMGtLXOlyuh-67xWgnJSP6rkg8oc,3942
|
|
@@ -584,9 +584,9 @@ opentrons/util/linal.py,sha256=IlKAP9HkNBBgULeSf4YVwSKHdx9jnCjSr7nvDvlRALg,5753
|
|
|
584
584
|
opentrons/util/logging_config.py,sha256=7et4YYuQdWdq_e50U-8vFS_QyNBRgdnqPGAQJm8qrIo,9954
|
|
585
585
|
opentrons/util/logging_queue_handler.py,sha256=ZsSJwy-oV8DXwpYiZisQ1PbYwmK2cOslD46AcyJ1E4I,2484
|
|
586
586
|
opentrons/util/performance_helpers.py,sha256=ew7H8XD20iS6-2TJAzbQeyzStZkkE6PzHt_Adx3wbZQ,5172
|
|
587
|
-
opentrons-8.5.
|
|
588
|
-
opentrons-8.5.
|
|
589
|
-
opentrons-8.5.
|
|
590
|
-
opentrons-8.5.
|
|
591
|
-
opentrons-8.5.
|
|
592
|
-
opentrons-8.5.
|
|
587
|
+
opentrons-8.5.0a7.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
588
|
+
opentrons-8.5.0a7.dist-info/METADATA,sha256=hwuM6YYv_P5I0ajOPnA881RX44DKkJhCbARJrffgKcY,5084
|
|
589
|
+
opentrons-8.5.0a7.dist-info/WHEEL,sha256=qUzzGenXXuJTzyjFah76kDVqDvnk-YDzY00svnrl84w,109
|
|
590
|
+
opentrons-8.5.0a7.dist-info/entry_points.txt,sha256=fTa6eGCYkvOtv0ov-KVE8LLGetgb35LQLF9x85OWPVw,106
|
|
591
|
+
opentrons-8.5.0a7.dist-info/top_level.txt,sha256=wk6whpbMZdBQpcK0Fg0YVfUGrAgVOFON7oQAhOMGMW8,10
|
|
592
|
+
opentrons-8.5.0a7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|