opentrons 8.6.0a3__py3-none-any.whl → 8.6.0a5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opentrons/_version.py +16 -3
- opentrons/drivers/asyncio/communication/async_serial.py +6 -2
- opentrons/motion_planning/deck_conflict.py +114 -9
- opentrons/protocol_api/core/engine/deck_conflict.py +56 -4
- opentrons/protocol_api/instrument_context.py +65 -3
- opentrons/protocol_engine/execution/movement.py +2 -1
- opentrons/protocol_engine/resources/fixture_validation.py +10 -0
- opentrons/protocol_engine/state/geometry.py +48 -1
- opentrons/protocol_engine/state/labware.py +0 -27
- {opentrons-8.6.0a3.dist-info → opentrons-8.6.0a5.dist-info}/METADATA +4 -4
- {opentrons-8.6.0a3.dist-info → opentrons-8.6.0a5.dist-info}/RECORD +14 -14
- {opentrons-8.6.0a3.dist-info → opentrons-8.6.0a5.dist-info}/WHEEL +0 -0
- {opentrons-8.6.0a3.dist-info → opentrons-8.6.0a5.dist-info}/entry_points.txt +0 -0
- {opentrons-8.6.0a3.dist-info → opentrons-8.6.0a5.dist-info}/licenses/LICENSE +0 -0
opentrons/_version.py
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '8.6.
|
|
21
|
-
__version_tuple__ = version_tuple = (8, 6, 0, '
|
|
31
|
+
__version__ = version = '8.6.0a5'
|
|
32
|
+
__version_tuple__ = version_tuple = (8, 6, 0, 'a5')
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
@@ -120,8 +120,12 @@ class AsyncSerial:
|
|
|
120
120
|
"""
|
|
121
121
|
if self._reset_buffer_before_write:
|
|
122
122
|
self._serial.reset_input_buffer()
|
|
123
|
-
self._serial.write(data
|
|
124
|
-
|
|
123
|
+
self._serial.write(data)
|
|
124
|
+
# flush can fail after entering dfu mode, ignore any exceptions.
|
|
125
|
+
try:
|
|
126
|
+
self._serial.flush()
|
|
127
|
+
except Exception:
|
|
128
|
+
pass
|
|
125
129
|
|
|
126
130
|
async def open(self) -> None:
|
|
127
131
|
"""
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Check a deck layout for conflicts."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
from dataclasses import dataclass
|
|
@@ -97,7 +98,19 @@ class ThermocyclerModule(_Module):
|
|
|
97
98
|
|
|
98
99
|
@dataclass
|
|
99
100
|
class OtherModule(_Module):
|
|
100
|
-
"""A module that's not a Heater-Shaker or Thermocycler."""
|
|
101
|
+
"""A module that's not a Heater-Shaker or Thermocycler or stacker."""
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass
|
|
105
|
+
class FlexStackerModule(_Module):
|
|
106
|
+
"""A stacker where nothing else is known to be in the "location" in column 3 that it lives."""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@dataclass
|
|
110
|
+
class FlexStackerModuleKindaButSomethingElseReally(_Module):
|
|
111
|
+
"""A stacker where something else is also in the "location" in column 3 that it lives."""
|
|
112
|
+
|
|
113
|
+
original_item: "DeckItem"
|
|
101
114
|
|
|
102
115
|
|
|
103
116
|
DeckItem = Union[
|
|
@@ -107,6 +120,8 @@ DeckItem = Union[
|
|
|
107
120
|
ThermocyclerModule,
|
|
108
121
|
OtherModule,
|
|
109
122
|
TrashBin,
|
|
123
|
+
FlexStackerModule,
|
|
124
|
+
FlexStackerModuleKindaButSomethingElseReally,
|
|
110
125
|
]
|
|
111
126
|
|
|
112
127
|
|
|
@@ -121,6 +136,19 @@ class _NothingAllowed(NamedTuple):
|
|
|
121
136
|
return False
|
|
122
137
|
|
|
123
138
|
|
|
139
|
+
class _NothingButStackerAllowed(NamedTuple):
|
|
140
|
+
"""Nothing (in the Odyssean sense) is allowed in this slot."""
|
|
141
|
+
|
|
142
|
+
location: Union[DeckSlotName, StagingSlotName]
|
|
143
|
+
source_item: DeckItem
|
|
144
|
+
source_location: Union[DeckSlotName, StagingSlotName]
|
|
145
|
+
|
|
146
|
+
def is_allowed(self, item: DeckItem) -> bool:
|
|
147
|
+
if isinstance(item, FlexStackerModule):
|
|
148
|
+
return True
|
|
149
|
+
return False
|
|
150
|
+
|
|
151
|
+
|
|
124
152
|
class _MaxHeight(NamedTuple):
|
|
125
153
|
"""Nothing over a certain height is allowed in this slot."""
|
|
126
154
|
|
|
@@ -169,6 +197,7 @@ _DeckRestriction = Union[
|
|
|
169
197
|
_MaxHeight,
|
|
170
198
|
_NoModule,
|
|
171
199
|
_NoHeaterShakerModule,
|
|
200
|
+
_NothingButStackerAllowed,
|
|
172
201
|
]
|
|
173
202
|
"""A restriction on what is allowed in a given slot."""
|
|
174
203
|
|
|
@@ -293,16 +322,10 @@ def _create_ot2_restrictions( # noqa: C901
|
|
|
293
322
|
return restrictions
|
|
294
323
|
|
|
295
324
|
|
|
296
|
-
def _create_flex_restrictions(
|
|
325
|
+
def _create_flex_restrictions( # noqa: C901
|
|
297
326
|
item: DeckItem, location: Union[DeckSlotName, StagingSlotName]
|
|
298
327
|
) -> List[_DeckRestriction]:
|
|
299
|
-
restrictions: List[_DeckRestriction] = [
|
|
300
|
-
_NothingAllowed(
|
|
301
|
-
location=location,
|
|
302
|
-
source_item=item,
|
|
303
|
-
source_location=location,
|
|
304
|
-
)
|
|
305
|
-
]
|
|
328
|
+
restrictions: List[_DeckRestriction] = []
|
|
306
329
|
|
|
307
330
|
if isinstance(item, (HeaterShakerModule, OtherModule)):
|
|
308
331
|
if isinstance(location, StagingSlotName):
|
|
@@ -321,6 +344,58 @@ def _create_flex_restrictions(
|
|
|
321
344
|
source_location=location,
|
|
322
345
|
)
|
|
323
346
|
)
|
|
347
|
+
restrictions.append(
|
|
348
|
+
_NothingAllowed(
|
|
349
|
+
location=location,
|
|
350
|
+
source_item=item,
|
|
351
|
+
source_location=location,
|
|
352
|
+
)
|
|
353
|
+
)
|
|
354
|
+
elif isinstance(item, FlexStackerModule):
|
|
355
|
+
if location not in _flex_slots_allowing_stacker():
|
|
356
|
+
raise DeckConflictError("Cannot place a Flex Stacker outside of column 3.")
|
|
357
|
+
# this is a typing assertion; the check above guarantees this is true
|
|
358
|
+
assert isinstance(location, DeckSlotName)
|
|
359
|
+
adjacent_staging_slot = get_adjacent_staging_slot(location)
|
|
360
|
+
# this is a typing assertion; the check above guarantees this isn't none
|
|
361
|
+
assert adjacent_staging_slot is not None
|
|
362
|
+
# nothing goes in the staging slot in the row the stacker is in, because the stacker is in the
|
|
363
|
+
# way (different from blocking you because of the design of the caddy).
|
|
364
|
+
restrictions.append(
|
|
365
|
+
_NothingAllowed(
|
|
366
|
+
location=adjacent_staging_slot,
|
|
367
|
+
source_item=item,
|
|
368
|
+
source_location=location,
|
|
369
|
+
)
|
|
370
|
+
)
|
|
371
|
+
# note that the stacker does NOT block use of the "slot" that it is "loaded in" because
|
|
372
|
+
# it is actually loaded in that cutout, and you can put a deck slot on top just fine
|
|
373
|
+
elif isinstance(item, FlexStackerModuleKindaButSomethingElseReally):
|
|
374
|
+
if location not in _flex_slots_allowing_stacker():
|
|
375
|
+
raise DeckConflictError("Cannot place a Flex Stacker outside of column 3.")
|
|
376
|
+
# this is a typing assertion; the check above guarantees this is true
|
|
377
|
+
assert isinstance(location, DeckSlotName)
|
|
378
|
+
adjacent_staging_slot = get_adjacent_staging_slot(location)
|
|
379
|
+
assert adjacent_staging_slot is not None
|
|
380
|
+
# nothing goes in the staging slot in the row the stacker is in, because the stacker is in the
|
|
381
|
+
# way (different from blocking you because of the design of the caddy).
|
|
382
|
+
restrictions.append(
|
|
383
|
+
_NothingAllowed(
|
|
384
|
+
location=adjacent_staging_slot,
|
|
385
|
+
source_item=item,
|
|
386
|
+
source_location=location,
|
|
387
|
+
)
|
|
388
|
+
)
|
|
389
|
+
# while the stacker on its own doesn't block use of the "slot" that it is "loaded in",
|
|
390
|
+
# the kind of "flex stacker" that actually means "you loaded a labware in column 3 where a
|
|
391
|
+
# stacker is sort of also "loaded" in column 3" does
|
|
392
|
+
restrictions.append(
|
|
393
|
+
_NothingAllowed(
|
|
394
|
+
location=location,
|
|
395
|
+
source_item=item.original_item,
|
|
396
|
+
source_location=location,
|
|
397
|
+
)
|
|
398
|
+
)
|
|
324
399
|
|
|
325
400
|
elif isinstance(item, ThermocyclerModule):
|
|
326
401
|
for covered_location in _flex_slots_covered_by_thermocycler():
|
|
@@ -331,6 +406,27 @@ def _create_flex_restrictions(
|
|
|
331
406
|
source_location=location,
|
|
332
407
|
)
|
|
333
408
|
)
|
|
409
|
+
restrictions.append(
|
|
410
|
+
_NothingAllowed(
|
|
411
|
+
location=location,
|
|
412
|
+
source_item=item,
|
|
413
|
+
source_location=location,
|
|
414
|
+
)
|
|
415
|
+
)
|
|
416
|
+
elif location in _flex_slots_allowing_stacker():
|
|
417
|
+
restrictions.append(
|
|
418
|
+
_NothingButStackerAllowed(
|
|
419
|
+
location=location,
|
|
420
|
+
source_item=item,
|
|
421
|
+
source_location=location,
|
|
422
|
+
)
|
|
423
|
+
)
|
|
424
|
+
else:
|
|
425
|
+
restrictions.append(
|
|
426
|
+
_NothingAllowed(
|
|
427
|
+
location=location, source_item=item, source_location=location
|
|
428
|
+
)
|
|
429
|
+
)
|
|
334
430
|
|
|
335
431
|
return restrictions
|
|
336
432
|
|
|
@@ -390,6 +486,15 @@ def _flex_slots_covered_by_thermocycler() -> Set[DeckSlotName]:
|
|
|
390
486
|
return {DeckSlotName.SLOT_B1, DeckSlotName.SLOT_A1}
|
|
391
487
|
|
|
392
488
|
|
|
489
|
+
def _flex_slots_allowing_stacker() -> Set[DeckSlotName]:
|
|
490
|
+
return {
|
|
491
|
+
DeckSlotName.SLOT_A3,
|
|
492
|
+
DeckSlotName.SLOT_B3,
|
|
493
|
+
DeckSlotName.SLOT_C3,
|
|
494
|
+
DeckSlotName.SLOT_D3,
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
|
|
393
498
|
def _is_ot2_fixed_trash(item: DeckItem) -> bool:
|
|
394
499
|
return (isinstance(item, Labware) and item.is_fixed_trash) or isinstance(
|
|
395
500
|
item, TrashBin
|
|
@@ -176,8 +176,12 @@ def check(
|
|
|
176
176
|
for existing_location, existing_item in itertools.chain(
|
|
177
177
|
mapped_existing_labware, mapped_existing_modules, mapped_disposal_locations
|
|
178
178
|
):
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
if existing_location not in existing_items:
|
|
180
|
+
existing_items[existing_location] = existing_item
|
|
181
|
+
else:
|
|
182
|
+
existing_items[existing_location] = _check_pair_compatibility(
|
|
183
|
+
existing_items[existing_location], existing_item, existing_location
|
|
184
|
+
)
|
|
181
185
|
|
|
182
186
|
wrapped_deck_conflict.check(
|
|
183
187
|
existing_items=existing_items,
|
|
@@ -187,6 +191,49 @@ def check(
|
|
|
187
191
|
)
|
|
188
192
|
|
|
189
193
|
|
|
194
|
+
def _check_pair_compatibility(
|
|
195
|
+
item1: wrapped_deck_conflict.DeckItem,
|
|
196
|
+
item2: wrapped_deck_conflict.DeckItem,
|
|
197
|
+
location: Union[DeckSlotName, StagingSlotName],
|
|
198
|
+
) -> wrapped_deck_conflict.DeckItem:
|
|
199
|
+
# if this is a stacker and something that can also "go" where a stacker "goes" (like a labware or magblock)
|
|
200
|
+
# then we build a combo; otherwise, we raise an error. this error in theory should never happen because to
|
|
201
|
+
# have the configuration that causes the error, it has to have passed the wrapped deck conflict checking,
|
|
202
|
+
# so there would be a bug in there, which is of course impossible.
|
|
203
|
+
|
|
204
|
+
def _check_pair_compat_once(
|
|
205
|
+
item1: wrapped_deck_conflict.DeckItem, item2: wrapped_deck_conflict.DeckItem
|
|
206
|
+
) -> bool:
|
|
207
|
+
if isinstance(item1, wrapped_deck_conflict.FlexStackerModule) and isinstance(
|
|
208
|
+
item2,
|
|
209
|
+
(wrapped_deck_conflict.MagneticBlockModule, wrapped_deck_conflict.Labware),
|
|
210
|
+
):
|
|
211
|
+
return True
|
|
212
|
+
return False
|
|
213
|
+
|
|
214
|
+
if _check_pair_compat_once(item1, item2) or _check_pair_compat_once(item2, item1):
|
|
215
|
+
not_stacker = (
|
|
216
|
+
item1
|
|
217
|
+
if not isinstance(item1, wrapped_deck_conflict.FlexStackerModule)
|
|
218
|
+
else item2
|
|
219
|
+
)
|
|
220
|
+
# type-only assertion: trash bins are not alowed in _check_pair_compat_once and
|
|
221
|
+
# so we would never get here
|
|
222
|
+
assert not isinstance(not_stacker, wrapped_deck_conflict.TrashBin)
|
|
223
|
+
return wrapped_deck_conflict.FlexStackerModuleKindaButSomethingElseReally(
|
|
224
|
+
name_for_errors=not_stacker.name_for_errors,
|
|
225
|
+
highest_z_including_labware=(
|
|
226
|
+
not_stacker.highest_z
|
|
227
|
+
if isinstance(not_stacker, wrapped_deck_conflict.Labware)
|
|
228
|
+
else not_stacker.highest_z_including_labware
|
|
229
|
+
),
|
|
230
|
+
original_item=not_stacker,
|
|
231
|
+
)
|
|
232
|
+
raise wrapped_deck_conflict.DeckConflictError(
|
|
233
|
+
f"{item1.name_for_errors} and {item2.name_for_errors} cannot both be loaded in {location}"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
|
|
190
237
|
def _map_labware(
|
|
191
238
|
engine_state: StateView,
|
|
192
239
|
labware_id: str,
|
|
@@ -304,8 +351,13 @@ def _map_module(
|
|
|
304
351
|
),
|
|
305
352
|
)
|
|
306
353
|
elif module_type == ModuleType.FLEX_STACKER:
|
|
307
|
-
|
|
308
|
-
|
|
354
|
+
return (
|
|
355
|
+
mapped_location,
|
|
356
|
+
wrapped_deck_conflict.FlexStackerModule(
|
|
357
|
+
name_for_errors=name_for_errors,
|
|
358
|
+
highest_z_including_labware=highest_z_including_labware,
|
|
359
|
+
),
|
|
360
|
+
)
|
|
309
361
|
else:
|
|
310
362
|
return (
|
|
311
363
|
mapped_location,
|
|
@@ -72,6 +72,8 @@ _PARTIAL_NOZZLE_CONFIGURATION_SINGLE_ROW_PARTIAL_COLUMN_ADDED_IN = APIVersion(2,
|
|
|
72
72
|
"""The version after which partial nozzle configurations of single, row, and partial column layouts became available."""
|
|
73
73
|
_AIR_GAP_TRACKING_ADDED_IN = APIVersion(2, 22)
|
|
74
74
|
"""The version after which air gaps should be implemented with a separate call instead of an aspirate for better liquid volume tracking."""
|
|
75
|
+
_LIQUID_CLASS_TRANSFER_TIP_RACKS_ARG_ADDED_IN = APIVersion(2, 25)
|
|
76
|
+
"""The version after which the user can supply liquid class transfers with non-assigned tip racks."""
|
|
75
77
|
|
|
76
78
|
|
|
77
79
|
AdvancedLiquidHandling = v1_transfer.AdvancedLiquidHandling
|
|
@@ -1796,6 +1798,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1796
1798
|
return_tip: bool = False,
|
|
1797
1799
|
group_wells: bool = True,
|
|
1798
1800
|
keep_last_tip: Optional[bool] = None,
|
|
1801
|
+
tip_racks: Optional[List[labware.Labware]] = None,
|
|
1799
1802
|
) -> InstrumentContext:
|
|
1800
1803
|
"""Move a particular type of liquid from one well or group of wells to another.
|
|
1801
1804
|
|
|
@@ -1832,6 +1835,12 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1832
1835
|
:param keep_last_tip: When ``True``, the pipette keeps the last tip used in the transfer attached. When
|
|
1833
1836
|
``False``, the last tip will be dropped or returned. If not set, behavior depends on the value of
|
|
1834
1837
|
``new_tip``. ``new_tip="never"`` keeps the tip, and all other values of ``new_tip`` drop or return the tip.
|
|
1838
|
+
:param tip_racks: A list of tip racks to pick up from for this command. If not provided, the pipette will pick
|
|
1839
|
+
up from its associated :py:obj:`.InstrumentContext.tip_racks`. Providing this argument does not change the
|
|
1840
|
+
value of ``InstrumentContext.tip_racks``.
|
|
1841
|
+
|
|
1842
|
+
.. versionchanged:: 2.25
|
|
1843
|
+
Added the ``tip_racks`` parameter.
|
|
1835
1844
|
|
|
1836
1845
|
"""
|
|
1837
1846
|
if volume == 0.0:
|
|
@@ -1841,12 +1850,22 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1841
1850
|
)
|
|
1842
1851
|
return self
|
|
1843
1852
|
|
|
1853
|
+
if (
|
|
1854
|
+
tip_racks is not None
|
|
1855
|
+
and self.api_version < _LIQUID_CLASS_TRANSFER_TIP_RACKS_ARG_ADDED_IN
|
|
1856
|
+
):
|
|
1857
|
+
raise APIVersionError(
|
|
1858
|
+
api_element="tip_racks",
|
|
1859
|
+
until_version="2.25",
|
|
1860
|
+
current_version=f"{self.api_version}",
|
|
1861
|
+
)
|
|
1862
|
+
|
|
1844
1863
|
transfer_args = verify_and_normalize_transfer_args(
|
|
1845
1864
|
source=source,
|
|
1846
1865
|
dest=dest,
|
|
1847
1866
|
tip_policy=new_tip,
|
|
1848
1867
|
last_tip_well=self._get_current_tip_source_well(),
|
|
1849
|
-
tip_racks=self._tip_racks,
|
|
1868
|
+
tip_racks=tip_racks or self._tip_racks,
|
|
1850
1869
|
nozzle_map=self._core.get_nozzle_map(),
|
|
1851
1870
|
group_wells_for_multi_channel=group_wells,
|
|
1852
1871
|
current_volume=self.current_volume,
|
|
@@ -1875,6 +1894,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1875
1894
|
for well in transfer_args.dest
|
|
1876
1895
|
]
|
|
1877
1896
|
|
|
1897
|
+
for tip_rack in transfer_args.tip_racks:
|
|
1898
|
+
instrument.validate_tiprack(self.name, tip_rack, _log)
|
|
1899
|
+
|
|
1878
1900
|
with publisher.publish_context(
|
|
1879
1901
|
broker=self.broker,
|
|
1880
1902
|
command=cmds.transfer_with_liquid_class(
|
|
@@ -1924,6 +1946,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1924
1946
|
return_tip: bool = False,
|
|
1925
1947
|
group_wells: bool = True,
|
|
1926
1948
|
keep_last_tip: Optional[bool] = None,
|
|
1949
|
+
tip_racks: Optional[List[labware.Labware]] = None,
|
|
1927
1950
|
) -> InstrumentContext:
|
|
1928
1951
|
"""
|
|
1929
1952
|
Distribute a particular type of liquid from one well to a group of wells.
|
|
@@ -1957,6 +1980,12 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1957
1980
|
:param keep_last_tip: When ``True``, the pipette keeps the last tip used in the distribute attached. When
|
|
1958
1981
|
``False``, the last tip will be dropped or returned. If not set, behavior depends on the value of
|
|
1959
1982
|
``new_tip``. ``new_tip="never"`` keeps the tip, and all other values of ``new_tip`` drop or return the tip.
|
|
1983
|
+
:param tip_racks: A list of tip racks to pick up from for this command. If not provided, the pipette will pick
|
|
1984
|
+
up from its associated :py:obj:`.InstrumentContext.tip_racks`. Providing this argument does not change the
|
|
1985
|
+
value of ``InstrumentContext.tip_racks``.
|
|
1986
|
+
|
|
1987
|
+
.. versionchanged:: 2.25
|
|
1988
|
+
Added the ``tip_racks`` parameter.
|
|
1960
1989
|
|
|
1961
1990
|
"""
|
|
1962
1991
|
if volume == 0.0:
|
|
@@ -1966,12 +1995,22 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1966
1995
|
)
|
|
1967
1996
|
return self
|
|
1968
1997
|
|
|
1998
|
+
if (
|
|
1999
|
+
tip_racks is not None
|
|
2000
|
+
and self.api_version < _LIQUID_CLASS_TRANSFER_TIP_RACKS_ARG_ADDED_IN
|
|
2001
|
+
):
|
|
2002
|
+
raise APIVersionError(
|
|
2003
|
+
api_element="tip_racks",
|
|
2004
|
+
until_version="2.25",
|
|
2005
|
+
current_version=f"{self.api_version}",
|
|
2006
|
+
)
|
|
2007
|
+
|
|
1969
2008
|
transfer_args = verify_and_normalize_transfer_args(
|
|
1970
2009
|
source=source,
|
|
1971
2010
|
dest=dest,
|
|
1972
2011
|
tip_policy=new_tip,
|
|
1973
2012
|
last_tip_well=self._get_current_tip_source_well(),
|
|
1974
|
-
tip_racks=self._tip_racks,
|
|
2013
|
+
tip_racks=tip_racks or self._tip_racks,
|
|
1975
2014
|
nozzle_map=self._core.get_nozzle_map(),
|
|
1976
2015
|
group_wells_for_multi_channel=group_wells,
|
|
1977
2016
|
current_volume=self.current_volume,
|
|
@@ -2004,6 +2043,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2004
2043
|
f" 'once', 'never' and 'always'."
|
|
2005
2044
|
)
|
|
2006
2045
|
|
|
2046
|
+
for tip_rack in transfer_args.tip_racks:
|
|
2047
|
+
instrument.validate_tiprack(self.name, tip_rack, _log)
|
|
2048
|
+
|
|
2007
2049
|
verified_source = transfer_args.source[0]
|
|
2008
2050
|
with publisher.publish_context(
|
|
2009
2051
|
broker=self.broker,
|
|
@@ -2057,6 +2099,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2057
2099
|
return_tip: bool = False,
|
|
2058
2100
|
group_wells: bool = True,
|
|
2059
2101
|
keep_last_tip: Optional[bool] = None,
|
|
2102
|
+
tip_racks: Optional[List[labware.Labware]] = None,
|
|
2060
2103
|
) -> InstrumentContext:
|
|
2061
2104
|
"""
|
|
2062
2105
|
Consolidate a particular type of liquid from a group of wells to one well.
|
|
@@ -2091,6 +2134,12 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2091
2134
|
:param keep_last_tip: When ``True``, the pipette keeps the last tip used in the consolidate attached. When
|
|
2092
2135
|
``False``, the last tip will be dropped or returned. If not set, behavior depends on the value of
|
|
2093
2136
|
``new_tip``. ``new_tip="never"`` keeps the tip, and all other values of ``new_tip`` drop or return the tip.
|
|
2137
|
+
:param tip_racks: A list of tip racks to pick up from for this command. If not provided, the pipette will pick
|
|
2138
|
+
up from its associated :py:obj:`.InstrumentContext.tip_racks`. Providing this argument does not change the
|
|
2139
|
+
value of ``InstrumentContext.tip_racks``.
|
|
2140
|
+
|
|
2141
|
+
.. versionchanged:: 2.25
|
|
2142
|
+
Added the ``tip_racks`` parameter.
|
|
2094
2143
|
|
|
2095
2144
|
"""
|
|
2096
2145
|
if volume == 0.0:
|
|
@@ -2100,12 +2149,22 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2100
2149
|
)
|
|
2101
2150
|
return self
|
|
2102
2151
|
|
|
2152
|
+
if (
|
|
2153
|
+
tip_racks is not None
|
|
2154
|
+
and self.api_version < _LIQUID_CLASS_TRANSFER_TIP_RACKS_ARG_ADDED_IN
|
|
2155
|
+
):
|
|
2156
|
+
raise APIVersionError(
|
|
2157
|
+
api_element="tip_racks",
|
|
2158
|
+
until_version="2.25",
|
|
2159
|
+
current_version=f"{self.api_version}",
|
|
2160
|
+
)
|
|
2161
|
+
|
|
2103
2162
|
transfer_args = verify_and_normalize_transfer_args(
|
|
2104
2163
|
source=source,
|
|
2105
2164
|
dest=dest,
|
|
2106
2165
|
tip_policy=new_tip,
|
|
2107
2166
|
last_tip_well=self._get_current_tip_source_well(),
|
|
2108
|
-
tip_racks=self._tip_racks,
|
|
2167
|
+
tip_racks=tip_racks or self._tip_racks,
|
|
2109
2168
|
nozzle_map=self._core.get_nozzle_map(),
|
|
2110
2169
|
group_wells_for_multi_channel=group_wells,
|
|
2111
2170
|
current_volume=self.current_volume,
|
|
@@ -2141,6 +2200,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2141
2200
|
f" 'once', 'never' and 'always'."
|
|
2142
2201
|
)
|
|
2143
2202
|
|
|
2203
|
+
for tip_rack in transfer_args.tip_racks:
|
|
2204
|
+
instrument.validate_tiprack(self.name, tip_rack, _log)
|
|
2205
|
+
|
|
2144
2206
|
with publisher.publish_context(
|
|
2145
2207
|
broker=self.broker,
|
|
2146
2208
|
command=cmds.consolidate_with_liquid_class(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Movement command handling."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
import logging
|
|
@@ -84,7 +85,7 @@ class MovementHandler:
|
|
|
84
85
|
operation_volume: Optional[float] = None,
|
|
85
86
|
) -> Point:
|
|
86
87
|
"""Move to a specific well."""
|
|
87
|
-
self._state_store.
|
|
88
|
+
self._state_store.geometry.raise_if_labware_inaccessible_by_pipette(
|
|
88
89
|
labware_id=labware_id
|
|
89
90
|
)
|
|
90
91
|
|
|
@@ -56,3 +56,13 @@ def is_deck_slot(addressable_area_name: str) -> bool:
|
|
|
56
56
|
def is_abs_reader(addressable_area_name: str) -> bool:
|
|
57
57
|
"""Check if an addressable area is an absorbance plate reader area."""
|
|
58
58
|
return "absorbanceReaderV1" in addressable_area_name
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def is_stacker_shuttle(addressable_area_name: str) -> bool:
|
|
62
|
+
"""Check if an addressable area is a flex stacker shuttle area."""
|
|
63
|
+
return addressable_area_name in [
|
|
64
|
+
"flexStackerModuleV1A4",
|
|
65
|
+
"flexStackerModuleV1B4",
|
|
66
|
+
"flexStackerModuleV1C4",
|
|
67
|
+
"flexStackerModuleV1D4",
|
|
68
|
+
]
|
|
@@ -1122,7 +1122,9 @@ class GeometryView:
|
|
|
1122
1122
|
"providesAddressableAreas"
|
|
1123
1123
|
][
|
|
1124
1124
|
deck_configuration_provider.get_cutout_id_by_deck_slot_name(
|
|
1125
|
-
DeckSlotName.SLOT_C2
|
|
1125
|
+
DeckSlotName.SLOT_C2.to_equivalent_for_robot_type(
|
|
1126
|
+
self._config.robot_type
|
|
1127
|
+
)
|
|
1126
1128
|
)
|
|
1127
1129
|
][
|
|
1128
1130
|
0
|
|
@@ -2359,3 +2361,48 @@ class GeometryView:
|
|
|
2359
2361
|
return pending_labware[labware_id]
|
|
2360
2362
|
except KeyError as ke:
|
|
2361
2363
|
raise lnle from ke
|
|
2364
|
+
|
|
2365
|
+
def raise_if_labware_inaccessible_by_pipette( # noqa: C901
|
|
2366
|
+
self, labware_id: str
|
|
2367
|
+
) -> None:
|
|
2368
|
+
"""Raise an error if the specified location cannot be reached via a pipette."""
|
|
2369
|
+
labware = self._labware.get(labware_id)
|
|
2370
|
+
labware_location = labware.location
|
|
2371
|
+
if isinstance(labware_location, OnLabwareLocation):
|
|
2372
|
+
return self.raise_if_labware_inaccessible_by_pipette(
|
|
2373
|
+
labware_location.labwareId
|
|
2374
|
+
)
|
|
2375
|
+
elif labware.lid_id is not None:
|
|
2376
|
+
raise errors.LocationNotAccessibleByPipetteError(
|
|
2377
|
+
f"Cannot move pipette to {labware.loadName} "
|
|
2378
|
+
"because labware is currently covered by a lid."
|
|
2379
|
+
)
|
|
2380
|
+
elif isinstance(labware_location, AddressableAreaLocation):
|
|
2381
|
+
if fixture_validation.is_staging_slot(labware_location.addressableAreaName):
|
|
2382
|
+
raise errors.LocationNotAccessibleByPipetteError(
|
|
2383
|
+
f"Cannot move pipette to {labware.loadName},"
|
|
2384
|
+
f" labware is on staging slot {labware_location.addressableAreaName}"
|
|
2385
|
+
)
|
|
2386
|
+
elif fixture_validation.is_stacker_shuttle(
|
|
2387
|
+
labware_location.addressableAreaName
|
|
2388
|
+
):
|
|
2389
|
+
raise errors.LocationNotAccessibleByPipetteError(
|
|
2390
|
+
f"Cannot move pipette to {labware.loadName} because it is on a stacker shuttle"
|
|
2391
|
+
)
|
|
2392
|
+
elif (
|
|
2393
|
+
labware_location == OFF_DECK_LOCATION or labware_location == SYSTEM_LOCATION
|
|
2394
|
+
):
|
|
2395
|
+
raise errors.LocationNotAccessibleByPipetteError(
|
|
2396
|
+
f"Cannot move pipette to {labware.loadName}, labware is off-deck."
|
|
2397
|
+
)
|
|
2398
|
+
elif isinstance(labware_location, ModuleLocation):
|
|
2399
|
+
module = self._modules.get(labware_location.moduleId)
|
|
2400
|
+
if ModuleModel.is_flex_stacker(module.model):
|
|
2401
|
+
raise errors.LocationNotAccessibleByPipetteError(
|
|
2402
|
+
f"Cannot move pipette to {labware.loadName}, labware is on a stacker shuttle"
|
|
2403
|
+
)
|
|
2404
|
+
|
|
2405
|
+
elif isinstance(labware_location, InStackerHopperLocation):
|
|
2406
|
+
raise errors.LocationNotAccessibleByPipetteError(
|
|
2407
|
+
f"Cannot move pipette to {labware.loadName}, labware is in a stacker hopper"
|
|
2408
|
+
)
|
|
@@ -58,7 +58,6 @@ from ..types import (
|
|
|
58
58
|
LabwareMovementOffsetData,
|
|
59
59
|
OnDeckLabwareLocation,
|
|
60
60
|
OFF_DECK_LOCATION,
|
|
61
|
-
SYSTEM_LOCATION,
|
|
62
61
|
)
|
|
63
62
|
from ..actions import (
|
|
64
63
|
Action,
|
|
@@ -1036,32 +1035,6 @@ class LabwareView:
|
|
|
1036
1035
|
"""Check if labware is a lid."""
|
|
1037
1036
|
return LabwareRole.lid in self.get_definition(labware_id).allowedRoles
|
|
1038
1037
|
|
|
1039
|
-
def raise_if_labware_inaccessible_by_pipette(self, labware_id: str) -> None:
|
|
1040
|
-
"""Raise an error if the specified location cannot be reached via a pipette."""
|
|
1041
|
-
labware = self.get(labware_id)
|
|
1042
|
-
labware_location = labware.location
|
|
1043
|
-
if isinstance(labware_location, OnLabwareLocation):
|
|
1044
|
-
return self.raise_if_labware_inaccessible_by_pipette(
|
|
1045
|
-
labware_location.labwareId
|
|
1046
|
-
)
|
|
1047
|
-
elif labware.lid_id is not None:
|
|
1048
|
-
raise errors.LocationNotAccessibleByPipetteError(
|
|
1049
|
-
f"Cannot move pipette to {labware.loadName} "
|
|
1050
|
-
"because labware is currently covered by a lid."
|
|
1051
|
-
)
|
|
1052
|
-
elif isinstance(labware_location, AddressableAreaLocation):
|
|
1053
|
-
if fixture_validation.is_staging_slot(labware_location.addressableAreaName):
|
|
1054
|
-
raise errors.LocationNotAccessibleByPipetteError(
|
|
1055
|
-
f"Cannot move pipette to {labware.loadName},"
|
|
1056
|
-
f" labware is on staging slot {labware_location.addressableAreaName}"
|
|
1057
|
-
)
|
|
1058
|
-
elif (
|
|
1059
|
-
labware_location == OFF_DECK_LOCATION or labware_location == SYSTEM_LOCATION
|
|
1060
|
-
):
|
|
1061
|
-
raise errors.LocationNotAccessibleByPipetteError(
|
|
1062
|
-
f"Cannot move pipette to {labware.loadName}, labware is off-deck."
|
|
1063
|
-
)
|
|
1064
|
-
|
|
1065
1038
|
def raise_if_labware_in_location(
|
|
1066
1039
|
self,
|
|
1067
1040
|
location: OnDeckLabwareLocation,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opentrons
|
|
3
|
-
Version: 8.6.
|
|
3
|
+
Version: 8.6.0a5
|
|
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.0a5
|
|
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.0a5; extra == 'flex-hardware'
|
|
36
36
|
Provides-Extra: ot2-hardware
|
|
37
|
-
Requires-Dist: opentrons-hardware==8.6.
|
|
37
|
+
Requires-Dist: opentrons-hardware==8.6.0a5; 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=DwgORFlCYMpHF3Y70AkjCmEVbBrAoGaMakKYbXsdrE8,712
|
|
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
|
|
@@ -51,7 +51,7 @@ opentrons/drivers/absorbance_reader/hid_protocol.py,sha256=OM6Ogkl1Lw3d501rfHcRI
|
|
|
51
51
|
opentrons/drivers/absorbance_reader/simulator.py,sha256=MiFQgnVNq2R35T3u59idcKlrj6SEFllt8tdupfH5jKQ,2419
|
|
52
52
|
opentrons/drivers/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
53
|
opentrons/drivers/asyncio/communication/__init__.py,sha256=b-rd_I0ecbexGm6b9T91JLfFUrCyui9V1N1j-fzy0SQ,523
|
|
54
|
-
opentrons/drivers/asyncio/communication/async_serial.py,sha256=
|
|
54
|
+
opentrons/drivers/asyncio/communication/async_serial.py,sha256=Tzv_uXvMYhJF2LXsJWDRA3hdg5_qCo3863zvn7Y66WY,5439
|
|
55
55
|
opentrons/drivers/asyncio/communication/errors.py,sha256=-4pNGVKE83VUPNt1UTBLDzKtty3LxAhUNp-9yLENqyw,2678
|
|
56
56
|
opentrons/drivers/asyncio/communication/serial_connection.py,sha256=cWcISWe0FfoZj63oYVQD-KkwBojzMTVrzJ64-Gd1u90,18876
|
|
57
57
|
opentrons/drivers/flex_stacker/__init__.py,sha256=LiM0onRlgC-JfFBd0QseQU0-3WuuIxa7GNFj7Douiq8,351
|
|
@@ -217,7 +217,7 @@ opentrons/legacy_commands/robot_commands.py,sha256=c51gVAh-98PxhxmEL_3P80rejkaY5
|
|
|
217
217
|
opentrons/legacy_commands/types.py,sha256=dtmHB2VOtsQHFzhdoZgjJZZc8pNGcCnleA5zsi5GTo0,28904
|
|
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
|
-
opentrons/motion_planning/deck_conflict.py,sha256=
|
|
220
|
+
opentrons/motion_planning/deck_conflict.py,sha256=gIAQYJbSKEn5XM_AoBVCOdp-acQsc0nF5FHaeuF53vg,16757
|
|
221
221
|
opentrons/motion_planning/errors.py,sha256=-TOop0-NWaWb6KNYRoYLpWMca_kwsxxXEf31WuDSGls,948
|
|
222
222
|
opentrons/motion_planning/types.py,sha256=C4jXv5b02iBQmePMLrujgvHwqvEphBWtY18MPfKQpj4,1188
|
|
223
223
|
opentrons/motion_planning/waypoints.py,sha256=45J1TBfvDKEczEog1-H16GoX3PhFBlYKyNzE2Sl10U8,8341
|
|
@@ -233,7 +233,7 @@ opentrons/protocol_api/config.py,sha256=r9lyvXjagTX_g3q5FGURPpcz2IA9sSF7Oa_1mKx-
|
|
|
233
233
|
opentrons/protocol_api/create_protocol_context.py,sha256=wwsZje0L__oDnu1Yrihau320_f-ASloR9eL1QCtkOh8,7612
|
|
234
234
|
opentrons/protocol_api/deck.py,sha256=94vFceg1SC1bAGd7TvC1ZpYwnJR-VlzurEZ6jkacYeg,8910
|
|
235
235
|
opentrons/protocol_api/disposal_locations.py,sha256=NRiSGmDR0LnbyEkWSOM-o64uR2fUoB1NWJG7Y7SsJSs,7920
|
|
236
|
-
opentrons/protocol_api/instrument_context.py,sha256=
|
|
236
|
+
opentrons/protocol_api/instrument_context.py,sha256=cgszbfSJbEr1p9QywHIoQjDBTdnakwH3R-iTDb4nuNI,141122
|
|
237
237
|
opentrons/protocol_api/labware.py,sha256=ZP4QuGadoDp6xtyToupXVSJFnsx4NfWcskRQAH3iU4Y,61443
|
|
238
238
|
opentrons/protocol_api/module_contexts.py,sha256=zhm2FfciAs2K73cVZ_8OwKcFKAU7VAiTOnCRnQaki_E,57712
|
|
239
239
|
opentrons/protocol_api/module_validation_and_errors.py,sha256=ljst-M_KK78GnyG3pyZ_6yoYkMY3HORS1QyQyWrme-U,2250
|
|
@@ -252,7 +252,7 @@ opentrons/protocol_api/core/well.py,sha256=Lf89YYEyq-ahRSRIFJw42vxIP8Fw6kzIUh9K1
|
|
|
252
252
|
opentrons/protocol_api/core/well_grid.py,sha256=BU28DKaBgEU_JdZ6pEzrwNxmuh6TkO4zlg7Pq1Rf5Xk,1516
|
|
253
253
|
opentrons/protocol_api/core/engine/__init__.py,sha256=B_5T7zgkWDb1mXPg4NbT-wBkQaK-WVokMMnJRNu7xiM,582
|
|
254
254
|
opentrons/protocol_api/core/engine/_default_labware_versions.py,sha256=hLKAp33c_eNLpvT5qUt8AOYy6PHhM_JnkdOXaMl80jA,7541
|
|
255
|
-
opentrons/protocol_api/core/engine/deck_conflict.py,sha256=
|
|
255
|
+
opentrons/protocol_api/core/engine/deck_conflict.py,sha256=j3AJ-sYr5e-06UgeGueUldx9B3fn7AhN738kJxZO_vw,14693
|
|
256
256
|
opentrons/protocol_api/core/engine/exceptions.py,sha256=aZgNrmYEeuPZm21nX_KZYtvyjv5h_zPjxxgPkEV7_bw,725
|
|
257
257
|
opentrons/protocol_api/core/engine/instrument.py,sha256=lDrCqOZm7ceu1E50EYiSh7qTDMci5cgw4bM-AvLyMjE,98890
|
|
258
258
|
opentrons/protocol_api/core/engine/labware.py,sha256=-2oygShyRZo1-R0UOoBtXniFOXfc3cSdGM-qa_l9wh8,8610
|
|
@@ -427,7 +427,7 @@ opentrons/protocol_engine/execution/gantry_mover.py,sha256=LFTPmzuGRuP6IspgXxIEy
|
|
|
427
427
|
opentrons/protocol_engine/execution/hardware_stopper.py,sha256=ZlhVYEdFfuKqp5slZBkustXcRPy5fJsw2rmfYzHuJkQ,6127
|
|
428
428
|
opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py,sha256=BSFLzSSeELAYZCrCUfJZx5DdlrwU06Ur92TYd0T-hzM,9084
|
|
429
429
|
opentrons/protocol_engine/execution/labware_movement.py,sha256=Bl-Nx3y5-zMlsxL3fcXV04OyiU1JFyqPJTS1Fir_XkA,12962
|
|
430
|
-
opentrons/protocol_engine/execution/movement.py,sha256=
|
|
430
|
+
opentrons/protocol_engine/execution/movement.py,sha256=ZU4K4OHnzZYCZbk3RwfSOC6C3T2jtBlvYMppJhJSF08,12749
|
|
431
431
|
opentrons/protocol_engine/execution/pipetting.py,sha256=cnJYbLiJ2QD1xziD8dkRm0mZG3xOk00klW8Ff8rgSG4,22199
|
|
432
432
|
opentrons/protocol_engine/execution/queue_worker.py,sha256=LM753TrQzJoKUSIrtcaHDOWLe58zcpx-fUOLVpyDlHM,3302
|
|
433
433
|
opentrons/protocol_engine/execution/rail_lights.py,sha256=eiJT6oI_kFk7rFuFkZzISZiLNnpf7Kkh86Kyk9wQ_Jo,590
|
|
@@ -442,7 +442,7 @@ opentrons/protocol_engine/resources/__init__.py,sha256=yvGFYpmLoxHYQff_IwiaEH9vi
|
|
|
442
442
|
opentrons/protocol_engine/resources/deck_configuration_provider.py,sha256=K3_FKHNpeM1_kTjHGBbrMPaCZsbEEOUaY8licOd6Xh8,9411
|
|
443
443
|
opentrons/protocol_engine/resources/deck_data_provider.py,sha256=63c-Hmwy5IbVSoAL3hYoZxizxwzCqbB2KgJptpLX3Bc,3001
|
|
444
444
|
opentrons/protocol_engine/resources/file_provider.py,sha256=6btMCDN7NsyFlV7Icy5vDO7xsgbmtkeAM_KCuQ-GvRo,5903
|
|
445
|
-
opentrons/protocol_engine/resources/fixture_validation.py,sha256=
|
|
445
|
+
opentrons/protocol_engine/resources/fixture_validation.py,sha256=WyGjMjc-DGiNTojesXdwFfCyF3KYl7R2jmEk7teLyxQ,2166
|
|
446
446
|
opentrons/protocol_engine/resources/labware_data_provider.py,sha256=i0otj_dACWHK23mBGjXGwTJtE4sooov2_YQOMIulzJo,3836
|
|
447
447
|
opentrons/protocol_engine/resources/labware_validation.py,sha256=6UkWktVvGNpOrRov4vEZ2A8qbjJMuKlisSQvr4Z749A,2747
|
|
448
448
|
opentrons/protocol_engine/resources/model_utils.py,sha256=C3OHUi-OtuFUm3dS5rApSU3EJ0clnaCZEyBku5sTjzA,941
|
|
@@ -461,9 +461,9 @@ opentrons/protocol_engine/state/commands.py,sha256=y5WE2pKmnMalgHFHEiBnBurO2TZ9w
|
|
|
461
461
|
opentrons/protocol_engine/state/config.py,sha256=7jSGxC6Vqj1eA8fqZ2I3zjlxVXg8pxvcBYMztRIx9Mg,1515
|
|
462
462
|
opentrons/protocol_engine/state/files.py,sha256=w8xxxg8HY0RqKKEGSfHWfrjV54Gb02O3dwtisJ-9j8E,1753
|
|
463
463
|
opentrons/protocol_engine/state/fluid_stack.py,sha256=uwkf0qYk1UX5iU52xmk-e3yLPK8OG-TtMCcBqrkVFpM,5932
|
|
464
|
-
opentrons/protocol_engine/state/geometry.py,sha256=
|
|
464
|
+
opentrons/protocol_engine/state/geometry.py,sha256=o8tefXS_Jekdt82dW4HHVJSnsxCsTFJuG6ogtri2wTY,104065
|
|
465
465
|
opentrons/protocol_engine/state/inner_well_math_utils.py,sha256=UhemsPpcuKwVc-iGXI2-v--miOGNunAnAVznJTVADlQ,20598
|
|
466
|
-
opentrons/protocol_engine/state/labware.py,sha256=
|
|
466
|
+
opentrons/protocol_engine/state/labware.py,sha256=bmNOa6vDFXa-Iow4x_1zNa3tIcNkUvu1OCg3ED2E4i4,59936
|
|
467
467
|
opentrons/protocol_engine/state/liquid_classes.py,sha256=u_z75UYdiFAKG0yB3mr1il4T3qaS0Sotq8sL7KLODP8,2990
|
|
468
468
|
opentrons/protocol_engine/state/liquids.py,sha256=NoesktcQdJUjIVmet1uqqJPf-rzbo4SGemXwQC295W0,2338
|
|
469
469
|
opentrons/protocol_engine/state/modules.py,sha256=2P_3Ks_9hWvtVgttnUqS5wcmWLmMzn2Tjp8CosnFXYM,60737
|
|
@@ -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.0a5.dist-info/METADATA,sha256=2vlfyq7YCEWGMNFuGW00_MMEhCX9KPsoQ0CdJub1poM,1607
|
|
598
|
+
opentrons-8.6.0a5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
599
|
+
opentrons-8.6.0a5.dist-info/entry_points.txt,sha256=fTa6eGCYkvOtv0ov-KVE8LLGetgb35LQLF9x85OWPVw,106
|
|
600
|
+
opentrons-8.6.0a5.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
601
|
+
opentrons-8.6.0a5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|