opentrons 8.8.0a7__py3-none-any.whl → 8.8.1__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 +2 -2
- opentrons/drivers/asyncio/communication/serial_connection.py +21 -0
- opentrons/hardware_control/ot3api.py +10 -3
- opentrons/hardware_control/protocols/liquid_handler.py +6 -2
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +4 -18
- opentrons/protocol_api/instrument_context.py +45 -37
- opentrons/protocol_api/module_contexts.py +22 -32
- opentrons/protocol_api/protocol_context.py +11 -13
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +13 -19
- opentrons/protocol_engine/commands/dispense_while_tracking.py +13 -20
- opentrons/protocol_engine/execution/command_executor.py +1 -1
- opentrons/protocol_engine/execution/pipetting.py +7 -0
- opentrons/protocol_engine/resources/camera_provider.py +2 -2
- opentrons/protocol_engine/state/motion.py +16 -18
- opentrons/protocol_runner/legacy_command_mapper.py +9 -1
- opentrons/system/camera.py +1 -1
- {opentrons-8.8.0a7.dist-info → opentrons-8.8.1.dist-info}/METADATA +4 -4
- {opentrons-8.8.0a7.dist-info → opentrons-8.8.1.dist-info}/RECORD +21 -21
- {opentrons-8.8.0a7.dist-info → opentrons-8.8.1.dist-info}/WHEEL +0 -0
- {opentrons-8.8.0a7.dist-info → opentrons-8.8.1.dist-info}/entry_points.txt +0 -0
- {opentrons-8.8.0a7.dist-info → opentrons-8.8.1.dist-info}/licenses/LICENSE +0 -0
opentrons/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '8.8.
|
|
32
|
-
__version_tuple__ = version_tuple = (8, 8,
|
|
31
|
+
__version__ = version = '8.8.1'
|
|
32
|
+
__version_tuple__ = version_tuple = (8, 8, 1)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -12,6 +12,8 @@ from .errors import (
|
|
|
12
12
|
ErrorResponse,
|
|
13
13
|
BaseErrorCode,
|
|
14
14
|
DefaultErrorCodes,
|
|
15
|
+
UnhandledGcode,
|
|
16
|
+
GCodeCacheFull,
|
|
15
17
|
)
|
|
16
18
|
from .async_serial import AsyncSerial
|
|
17
19
|
|
|
@@ -555,6 +557,23 @@ class AsyncResponseSerialConnection(SerialConnection):
|
|
|
555
557
|
# A read timeout, end
|
|
556
558
|
yield "empty-unknown", data
|
|
557
559
|
|
|
560
|
+
def _raise_on_parser_error(self, data: str, response: bytes) -> None:
|
|
561
|
+
"""Raise an exception if this response contains an error from the gcode parser on the module.
|
|
562
|
+
|
|
563
|
+
This has to be treated specially because multiack commands won't get multiple acks if the command
|
|
564
|
+
fails at the parse stage. The errors handled here should be kept in sync with the module gcode
|
|
565
|
+
parse code.
|
|
566
|
+
"""
|
|
567
|
+
try:
|
|
568
|
+
str_response = self.process_raw_response(
|
|
569
|
+
command=data, response=response.replace(self._ack, b"").decode()
|
|
570
|
+
)
|
|
571
|
+
self.raise_on_error(response=str_response, request=data)
|
|
572
|
+
except (UnhandledGcode, GCodeCacheFull):
|
|
573
|
+
raise
|
|
574
|
+
except Exception:
|
|
575
|
+
pass
|
|
576
|
+
|
|
558
577
|
async def _send_one_retry(self, data: str, acks: int) -> list[str]:
|
|
559
578
|
data_encode = data.encode("utf-8")
|
|
560
579
|
log.debug(f"{self._name}: Write -> {data_encode!r}")
|
|
@@ -567,8 +586,10 @@ class AsyncResponseSerialConnection(SerialConnection):
|
|
|
567
586
|
async for response_type, response in self._consume_responses(acks):
|
|
568
587
|
if response_type == "error":
|
|
569
588
|
async_errors.append(response)
|
|
589
|
+
self._raise_on_parser_error(data, response)
|
|
570
590
|
elif response_type == "response":
|
|
571
591
|
command_acks.append(response)
|
|
592
|
+
self._raise_on_parser_error(data, response)
|
|
572
593
|
else:
|
|
573
594
|
break
|
|
574
595
|
|
|
@@ -3089,6 +3089,7 @@ class OT3API(
|
|
|
3089
3089
|
volume: float,
|
|
3090
3090
|
rate: float = 1.0,
|
|
3091
3091
|
movement_delay: Optional[float] = None,
|
|
3092
|
+
end_critical_point: Optional[CriticalPoint] = None,
|
|
3092
3093
|
) -> None:
|
|
3093
3094
|
"""
|
|
3094
3095
|
Aspirate a volume of liquid (in microliters/uL) while moving the z axis synchronously.
|
|
@@ -3108,7 +3109,7 @@ class OT3API(
|
|
|
3108
3109
|
end_position = target_position_from_absolute(
|
|
3109
3110
|
realmount,
|
|
3110
3111
|
end_point,
|
|
3111
|
-
self.critical_point_for,
|
|
3112
|
+
partial(self.critical_point_for, cp_override=end_critical_point),
|
|
3112
3113
|
top_types.Point(*self._config.left_mount_offset),
|
|
3113
3114
|
top_types.Point(*self._config.right_mount_offset),
|
|
3114
3115
|
top_types.Point(*self._config.gripper_mount_offset),
|
|
@@ -3123,6 +3124,9 @@ class OT3API(
|
|
|
3123
3124
|
delay: Optional[Tuple[List[Axis], float]] = None
|
|
3124
3125
|
if movement_delay is not None:
|
|
3125
3126
|
delay = ([Axis.X, Axis.Y, Axis.Z_L, Axis.Z_R], movement_delay)
|
|
3127
|
+
self._log.info(
|
|
3128
|
+
f"aspirate_while_tracking: end at {end_point} {end_critical_point}, machine pos {end_position}, with plunger {target_pos}, delay {delay}"
|
|
3129
|
+
)
|
|
3126
3130
|
try:
|
|
3127
3131
|
await self._backend.set_active_current(
|
|
3128
3132
|
{aspirate_spec.axis: aspirate_spec.current}
|
|
@@ -3158,6 +3162,7 @@ class OT3API(
|
|
|
3158
3162
|
rate: float = 1.0,
|
|
3159
3163
|
is_full_dispense: bool = False,
|
|
3160
3164
|
movement_delay: Optional[float] = None,
|
|
3165
|
+
end_critical_point: Optional[CriticalPoint] = None,
|
|
3161
3166
|
) -> None:
|
|
3162
3167
|
"""
|
|
3163
3168
|
Dispense a volume of liquid (in microliters/uL) while moving the z axis synchronously.
|
|
@@ -3177,7 +3182,7 @@ class OT3API(
|
|
|
3177
3182
|
end_position = target_position_from_absolute(
|
|
3178
3183
|
realmount,
|
|
3179
3184
|
end_point,
|
|
3180
|
-
self.critical_point_for,
|
|
3185
|
+
partial(self.critical_point_for, cp_override=end_critical_point),
|
|
3181
3186
|
top_types.Point(*self._config.left_mount_offset),
|
|
3182
3187
|
top_types.Point(*self._config.right_mount_offset),
|
|
3183
3188
|
top_types.Point(*self._config.gripper_mount_offset),
|
|
@@ -3192,7 +3197,9 @@ class OT3API(
|
|
|
3192
3197
|
delay: Optional[Tuple[List[Axis], float]] = None
|
|
3193
3198
|
if movement_delay is not None:
|
|
3194
3199
|
delay = ([Axis.X, Axis.Y, Axis.Z_L, Axis.Z_R], movement_delay)
|
|
3195
|
-
|
|
3200
|
+
self._log.info(
|
|
3201
|
+
f"dispense_while_tracking: end at {end_point} {end_critical_point}, machine pos {end_position}, with plunger {target_pos}, delay {delay}"
|
|
3202
|
+
)
|
|
3196
3203
|
try:
|
|
3197
3204
|
await self._backend.set_active_current(
|
|
3198
3205
|
{dispense_spec.axis: dispense_spec.current}
|
|
@@ -129,15 +129,17 @@ class LiquidHandler(
|
|
|
129
129
|
volume: float,
|
|
130
130
|
flow_rate: float = 1.0,
|
|
131
131
|
movement_delay: Optional[float] = None,
|
|
132
|
+
end_critical_point: Optional[CriticalPoint] = None,
|
|
132
133
|
) -> None:
|
|
133
134
|
"""
|
|
134
135
|
Aspirate a volume of liquid (in microliters/uL) while moving the z axis synchronously.
|
|
135
136
|
|
|
136
137
|
:param mount: A robot mount that the instrument is on.
|
|
137
|
-
:param
|
|
138
|
+
:param end_point: The deck coordinate point to move the tip to during the aspirate.
|
|
138
139
|
:param volume: The volume of liquid to be aspirated.
|
|
139
140
|
:param flow_rate: The flow rate to aspirate with.
|
|
140
141
|
:param movement_delay: Time to wait after the pipette starts aspirating before x/y/z movement.
|
|
142
|
+
:param end_critical_point: The critical point for the end_point position.
|
|
141
143
|
"""
|
|
142
144
|
...
|
|
143
145
|
|
|
@@ -172,15 +174,17 @@ class LiquidHandler(
|
|
|
172
174
|
flow_rate: float = 1.0,
|
|
173
175
|
is_full_dispense: bool = False,
|
|
174
176
|
movement_delay: Optional[float] = None,
|
|
177
|
+
end_critical_point: Optional[CriticalPoint] = None,
|
|
175
178
|
) -> None:
|
|
176
179
|
"""
|
|
177
180
|
Dispense a volume of liquid (in microliters/uL) while moving the z axis synchronously.
|
|
178
181
|
|
|
179
182
|
:param mount: A robot mount that the instrument is on.
|
|
180
|
-
:param
|
|
183
|
+
:param end_point: The deck coordinate point to move the tip to during the dispense.
|
|
181
184
|
:param volume: The volume of liquid to be dispensed.
|
|
182
185
|
:param flow_rate: The flow rate to dispense with.
|
|
183
186
|
:param movement_delay: Time to wait after the pipette starts dispensing before x/y/z movement.
|
|
187
|
+
:param end_critical_point: The critical point for the end_point position.
|
|
184
188
|
"""
|
|
185
189
|
...
|
|
186
190
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""A Protocol-Engine-friendly wrapper for opentrons.motion_planning.deck_conflict."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
import logging
|
|
4
5
|
from typing import (
|
|
5
|
-
Optional,
|
|
6
6
|
Tuple,
|
|
7
7
|
Union,
|
|
8
8
|
List,
|
|
@@ -12,7 +12,6 @@ from opentrons_shared_data.errors.exceptions import MotionPlanningFailureError
|
|
|
12
12
|
from opentrons.protocol_engine.errors import LocationIsStagingSlotError
|
|
13
13
|
from opentrons_shared_data.module import FLEX_TC_LID_COLLISION_ZONE
|
|
14
14
|
|
|
15
|
-
from opentrons.hardware_control import CriticalPoint
|
|
16
15
|
from opentrons.motion_planning import adjacent_slots_getters
|
|
17
16
|
|
|
18
17
|
from opentrons.protocol_engine import (
|
|
@@ -101,7 +100,9 @@ def check_safe_for_pipette_movement( # noqa: C901
|
|
|
101
100
|
)
|
|
102
101
|
primary_nozzle = engine_state.pipettes.get_primary_nozzle(pipette_id)
|
|
103
102
|
|
|
104
|
-
destination_cp =
|
|
103
|
+
destination_cp = engine_state.motion.get_critical_point_for_wells_in_labware(
|
|
104
|
+
labware_id
|
|
105
|
+
)
|
|
105
106
|
pipette_bounds_at_well_location = (
|
|
106
107
|
engine_state.pipettes.get_pipette_bounds_at_specified_move_to_position(
|
|
107
108
|
pipette_id=pipette_id,
|
|
@@ -189,21 +190,6 @@ def check_safe_for_pipette_movement( # noqa: C901
|
|
|
189
190
|
)
|
|
190
191
|
|
|
191
192
|
|
|
192
|
-
def _get_critical_point_to_use(
|
|
193
|
-
engine_state: StateView, labware_id: str
|
|
194
|
-
) -> Optional[CriticalPoint]:
|
|
195
|
-
"""Return the critical point to use when accessing the given labware."""
|
|
196
|
-
# TODO (spp, 2024-09-17): looks like Y_CENTER of column is the same as its XY_CENTER.
|
|
197
|
-
# I'm using this if-else ladder to be consistent with what we do in
|
|
198
|
-
# `MotionPlanning.get_movement_waypoints_to_well()`.
|
|
199
|
-
# We should probably use only XY_CENTER in both places.
|
|
200
|
-
if engine_state.labware.get_should_center_column_on_target_well(labware_id):
|
|
201
|
-
return CriticalPoint.Y_CENTER
|
|
202
|
-
elif engine_state.labware.get_should_center_pipette_on_target_well(labware_id):
|
|
203
|
-
return CriticalPoint.XY_CENTER
|
|
204
|
-
return None
|
|
205
|
-
|
|
206
|
-
|
|
207
193
|
def _slot_has_potential_colliding_object(
|
|
208
194
|
engine_state: StateView,
|
|
209
195
|
pipette_bounds: Tuple[Point, Point, Point, Point],
|
|
@@ -242,14 +242,14 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
242
242
|
:param flow_rate: The absolute flow rate in µL/s. If ``flow_rate`` is specified,
|
|
243
243
|
``rate`` must not be set.
|
|
244
244
|
:type flow_rate: float
|
|
245
|
-
:param end_location: Tells the robot to move
|
|
246
|
-
while aspirating liquid. When this argument is used the location and
|
|
247
|
-
end_location must both be :py:class:`.Location`.
|
|
245
|
+
:param end_location: Tells the robot to move from the specified ``location`` to the specified ``end_location``
|
|
246
|
+
while aspirating liquid. When this argument is used, the ``location`` and
|
|
247
|
+
``end_location`` must both be a :py:class:`.Location`.
|
|
248
248
|
:type end_location: :py:class:`.Location`
|
|
249
|
-
:param movement_delay:
|
|
250
|
-
This option is only valid when using end_location
|
|
251
|
-
is used, the
|
|
252
|
-
starts to aspirate before moving. This may help when
|
|
249
|
+
:param movement_delay: Time in seconds to delay after the pipette starts aspirating and before it begins moving from ``location`` to ``end_location``.
|
|
250
|
+
This option is only valid when using ``end_location``. When this argument
|
|
251
|
+
is used, the pipette will wait the specified time after the pipette
|
|
252
|
+
starts to aspirate before moving. This may help when aspirating very viscous liquids
|
|
253
253
|
that need to build up some pressure before liquid starts to flow.
|
|
254
254
|
:type movement_delay: float
|
|
255
255
|
:returns: This instance.
|
|
@@ -263,6 +263,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
263
263
|
|
|
264
264
|
.. versionchanged:: 2.24
|
|
265
265
|
Added the ``flow_rate`` parameter.
|
|
266
|
+
.. versionchanged:: 2.27
|
|
267
|
+
Added the ``end_location`` and ``movement_delay`` parameters.
|
|
266
268
|
"""
|
|
267
269
|
if flow_rate is not None:
|
|
268
270
|
if self.api_version < APIVersion(2, 24):
|
|
@@ -479,13 +481,13 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
479
481
|
``rate`` must not be set.
|
|
480
482
|
:type flow_rate: float
|
|
481
483
|
|
|
482
|
-
:param end_location: Tells the robot to move
|
|
483
|
-
while dispensing liquid held in the pipette. When this argument is used
|
|
484
|
-
the location and end_location must both be a :py:class:`.Location`.
|
|
484
|
+
:param end_location: Tells the robot to move from the specified ``location`` to the specified ``end_location``
|
|
485
|
+
while dispensing liquid held in the pipette. When this argument is used,
|
|
486
|
+
the ``location`` and ``end_location`` must both be a :py:class:`.Location`.
|
|
485
487
|
:type end_location: :py:class:`.Location`
|
|
486
|
-
:param movement_delay:
|
|
487
|
-
This option is only valid when using end_location
|
|
488
|
-
is used, the
|
|
488
|
+
:param movement_delay: Time in seconds to delay after the pipette starts dispensing and before it begins moving from ``location`` to ``end_location``.
|
|
489
|
+
This option is only valid when using ``end_location``. When this argument
|
|
490
|
+
is used, the pipette will wait the specified time after the pipette
|
|
489
491
|
starts to dispense before moving. This may help when dispensing very viscous liquids
|
|
490
492
|
that need to build up some pressure before liquid starts to flow.
|
|
491
493
|
:type movement_delay: float
|
|
@@ -510,6 +512,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
510
512
|
.. versionchanged:: 2.24
|
|
511
513
|
``location`` is no longer required if the pipette just moved to, dispensed, or blew out
|
|
512
514
|
into a trash bin or waste chute.
|
|
515
|
+
|
|
516
|
+
.. versionchanged:: 2.27
|
|
517
|
+
Added the ``end_location`` and ``movement_delay`` parameters.
|
|
513
518
|
"""
|
|
514
519
|
if self.api_version < APIVersion(2, 15) and push_out:
|
|
515
520
|
raise APIVersionError(
|
|
@@ -849,7 +854,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
849
854
|
"""
|
|
850
855
|
Mix a volume of liquid by repeatedly aspirating and dispensing it in a multiple locations.
|
|
851
856
|
|
|
852
|
-
See :ref:`
|
|
857
|
+
See :ref:`dynamic-mix` for examples.
|
|
853
858
|
|
|
854
859
|
:param repetitions: Number of times to mix (default is 1).
|
|
855
860
|
:param volume: The volume to mix, measured in µL. If unspecified, defaults
|
|
@@ -860,13 +865,13 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
860
865
|
it will behave the same as a volume of ``None``/unspecified: mix
|
|
861
866
|
the full working volume of the pipette. On API levels at or above 2.16,
|
|
862
867
|
no liquid will be mixed.
|
|
863
|
-
:param aspirate_start_location: The :py:class:`~.types.Location` where the pipette will
|
|
864
|
-
:param aspirate_end_location:
|
|
865
|
-
the pipette will move between aspirate_start_location and aspirate_end_location
|
|
868
|
+
:param aspirate_start_location: The :py:class:`~.types.Location` where the pipette will start aspirating from.
|
|
869
|
+
:param aspirate_end_location: A :py:class:`~.types.Location`. If specified,
|
|
870
|
+
the pipette will move between the ``aspirate_start_location`` and the ``aspirate_end_location``
|
|
866
871
|
while performing the aspirate.
|
|
867
|
-
:param dispense_start_location: The :py:class:`~.types.Location` where the pipette will
|
|
868
|
-
:param dispense_end_location:
|
|
869
|
-
the pipette will move between dispense_start_location and dispense_end_location
|
|
872
|
+
:param dispense_start_location: The :py:class:`~.types.Location` where the pipette will start dispensing to.
|
|
873
|
+
:param dispense_end_location: A :py:class:`~.types.Location`. If specified,
|
|
874
|
+
the pipette will move between the ``dispense_start_location`` and the ``dispense_end_location``
|
|
870
875
|
while performing the dispense.
|
|
871
876
|
:param rate: How quickly the pipette aspirates and dispenses liquid while
|
|
872
877
|
mixing. The aspiration flow rate is calculated as ``rate``
|
|
@@ -884,10 +889,10 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
884
889
|
pipette will not push out after earlier repetitions. If
|
|
885
890
|
not specified or ``None``, the pipette will push out the
|
|
886
891
|
default non-zero amount. See :ref:`push-out-dispense`.
|
|
887
|
-
:param movement_delay:
|
|
888
|
-
This option is only valid when using aspirate_end_location or dispense_end_location
|
|
889
|
-
When this argument is used, the
|
|
890
|
-
after the pipette starts to aspirate
|
|
892
|
+
:param movement_delay: Time in seconds to delay after the pipette starts aspirating or dispensing and before it begins moving from the ``aspirate_start_location`` or ``dispense_start_location`` to the ``aspirate_end_location`` or ``dispense_end_location``.
|
|
893
|
+
This option is only valid when using ``aspirate_end_location`` or ``dispense_end_location``.
|
|
894
|
+
When this argument is used, the pipette will wait the specified time
|
|
895
|
+
after the pipette starts to aspirate or dispense before moving. This may help when mixing
|
|
891
896
|
very viscous liquids that need to build up some pressure before liquid starts to flow.
|
|
892
897
|
:type movement_delay: float
|
|
893
898
|
:raises: ``UnexpectedTipRemovalError`` -- If no tip is attached to the pipette.
|
|
@@ -895,10 +900,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
895
900
|
|
|
896
901
|
.. note::
|
|
897
902
|
|
|
898
|
-
|
|
899
|
-
all subsequent arguments must be passed as keyword arguments. For instance,
|
|
900
|
-
``pipette.mix(1, location=wellplate['A1'])`` is a valid call, but
|
|
901
|
-
``pipette.mix(1, wellplate['A1'])`` is not.
|
|
903
|
+
The ``aspirate_start_location`` and ``dispense_start_location`` arguments of ``dynamic_mix`` are required.
|
|
902
904
|
|
|
903
905
|
"""
|
|
904
906
|
_log.debug(
|
|
@@ -2267,9 +2269,11 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2267
2269
|
trash_location=transfer_args.trash_location,
|
|
2268
2270
|
return_tip=return_tip,
|
|
2269
2271
|
keep_last_tip=verified_keep_last_tip,
|
|
2270
|
-
tips=
|
|
2271
|
-
|
|
2272
|
-
|
|
2272
|
+
tips=(
|
|
2273
|
+
[tip._core for tip in transfer_args.tips]
|
|
2274
|
+
if transfer_args.tips is not None
|
|
2275
|
+
else None
|
|
2276
|
+
),
|
|
2273
2277
|
)
|
|
2274
2278
|
|
|
2275
2279
|
return self
|
|
@@ -2441,9 +2445,11 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2441
2445
|
trash_location=transfer_args.trash_location,
|
|
2442
2446
|
return_tip=return_tip,
|
|
2443
2447
|
keep_last_tip=verified_keep_last_tip,
|
|
2444
|
-
tips=
|
|
2445
|
-
|
|
2446
|
-
|
|
2448
|
+
tips=(
|
|
2449
|
+
[tip._core for tip in transfer_args.tips]
|
|
2450
|
+
if transfer_args.tips is not None
|
|
2451
|
+
else None
|
|
2452
|
+
),
|
|
2447
2453
|
)
|
|
2448
2454
|
|
|
2449
2455
|
return self
|
|
@@ -2615,9 +2621,11 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2615
2621
|
trash_location=transfer_args.trash_location,
|
|
2616
2622
|
return_tip=return_tip,
|
|
2617
2623
|
keep_last_tip=verified_keep_last_tip,
|
|
2618
|
-
tips=
|
|
2619
|
-
|
|
2620
|
-
|
|
2624
|
+
tips=(
|
|
2625
|
+
[tip._core for tip in transfer_args.tips]
|
|
2626
|
+
if transfer_args.tips is not None
|
|
2627
|
+
else None
|
|
2628
|
+
),
|
|
2621
2629
|
)
|
|
2622
2630
|
|
|
2623
2631
|
return self
|
|
@@ -456,13 +456,14 @@ class TemperatureModuleContext(ModuleContext):
|
|
|
456
456
|
@publish(command=cmds.tempdeck_set_temp)
|
|
457
457
|
@requires_version(2, 3)
|
|
458
458
|
def start_set_temperature(self, celsius: float) -> Task:
|
|
459
|
-
"""
|
|
459
|
+
"""Sets the Temperature Module's target temperature and returns immediately without waiting for the module to reach the target. Allows the protocol to proceed while the Temperature Module heats.
|
|
460
460
|
|
|
461
461
|
.. versionchanged:: 2.27
|
|
462
|
-
Returns a
|
|
463
|
-
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the
|
|
462
|
+
Returns a :py:class:`Task` object that represents concurrent heating.
|
|
463
|
+
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the module to finish heating.
|
|
464
|
+
|
|
465
|
+
In API version 2.26 or below, this function returns ``None``.
|
|
464
466
|
|
|
465
|
-
On version 2.26 or below, this function returns ``None``.
|
|
466
467
|
:param celsius: A value between 4 and 95, representing the target temperature in °C.
|
|
467
468
|
"""
|
|
468
469
|
task = self._core.set_target_temperature(celsius)
|
|
@@ -715,9 +716,9 @@ class ThermocyclerContext(ModuleContext):
|
|
|
715
716
|
ramp_rate: Optional[float] = None,
|
|
716
717
|
block_max_volume: Optional[float] = None,
|
|
717
718
|
) -> Task:
|
|
718
|
-
"""
|
|
719
|
+
"""Sets the target temperature for the Thermocycler Module's well block, in °C.
|
|
719
720
|
|
|
720
|
-
Returns a
|
|
721
|
+
Returns a :py:class:`Task` object that represents concurrent heating.
|
|
721
722
|
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for
|
|
722
723
|
the preheat to complete.
|
|
723
724
|
|
|
@@ -726,10 +727,10 @@ class ThermocyclerContext(ModuleContext):
|
|
|
726
727
|
:param block_max_volume: The greatest volume of liquid contained in any
|
|
727
728
|
individual well of the loaded labware, in µL.
|
|
728
729
|
If not specified, the default is 25 µL.
|
|
729
|
-
|
|
730
|
-
the liquid tracking
|
|
731
|
-
then
|
|
732
|
-
or loaded liquid.
|
|
730
|
+
In API version 2.27 and newer, the API will first attempt to use
|
|
731
|
+
the liquid tracking in labware,
|
|
732
|
+
then default to 25 µL if the protocol lacks probed
|
|
733
|
+
or loaded liquid information.
|
|
733
734
|
"""
|
|
734
735
|
|
|
735
736
|
if block_max_volume is None:
|
|
@@ -746,10 +747,6 @@ class ThermocyclerContext(ModuleContext):
|
|
|
746
747
|
def set_lid_temperature(self, temperature: float) -> None:
|
|
747
748
|
"""Set the target temperature for the heated lid, in °C.
|
|
748
749
|
|
|
749
|
-
Returns a task object that represents concurrent preheating.
|
|
750
|
-
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for
|
|
751
|
-
the preheat to complete.
|
|
752
|
-
|
|
753
750
|
:param temperature: A value between 37 and 110, representing the target
|
|
754
751
|
temperature in °C.
|
|
755
752
|
|
|
@@ -765,20 +762,14 @@ class ThermocyclerContext(ModuleContext):
|
|
|
765
762
|
@publish(command=cmds.thermocycler_start_set_lid_temperature)
|
|
766
763
|
@requires_version(2, 27)
|
|
767
764
|
def start_set_lid_temperature(self, temperature: float) -> Task:
|
|
768
|
-
"""
|
|
765
|
+
"""Sets a target temperature to heat the Thermocycler Module's lid, in °C. Returns a :py:class:`Task` object that represents concurrent heating.
|
|
769
766
|
|
|
770
|
-
Returns a task object that represents concurrent preheating.
|
|
771
767
|
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for
|
|
772
|
-
the
|
|
768
|
+
the lid to reach the target temperature.
|
|
773
769
|
|
|
774
770
|
:param temperature: A value between 37 and 110, representing the target
|
|
775
771
|
temperature in °C.
|
|
776
772
|
|
|
777
|
-
.. note::
|
|
778
|
-
|
|
779
|
-
The Thermocycler will proceed to the next command immediately after
|
|
780
|
-
``temperature`` is reached.
|
|
781
|
-
|
|
782
773
|
"""
|
|
783
774
|
task = self._core.start_set_target_lid_temperature(celsius=temperature)
|
|
784
775
|
return Task(api_version=self._api_version, core=task)
|
|
@@ -824,11 +815,10 @@ class ThermocyclerContext(ModuleContext):
|
|
|
824
815
|
repetitions: int,
|
|
825
816
|
block_max_volume: Optional[float] = None,
|
|
826
817
|
) -> Task:
|
|
827
|
-
"""
|
|
818
|
+
"""Starts a defined Thermocycler Module profile and return a :py:class:`Task` representing its concurrent execution.
|
|
828
819
|
Profile is defined as a cycle of ``steps``, for a given number of ``repetitions``.
|
|
829
820
|
|
|
830
|
-
|
|
831
|
-
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the preheat to complete.
|
|
821
|
+
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the profile run to complete.
|
|
832
822
|
|
|
833
823
|
:param steps: List of steps that make up a single cycle.
|
|
834
824
|
Each list item should be a dictionary that maps to the parameters
|
|
@@ -1104,17 +1094,17 @@ class HeaterShakerContext(ModuleContext):
|
|
|
1104
1094
|
"""Set target temperature and return immediately.
|
|
1105
1095
|
|
|
1106
1096
|
Sets the Heater-Shaker's target temperature and returns immediately without
|
|
1107
|
-
waiting for the target to be reached.
|
|
1108
|
-
target temperature
|
|
1097
|
+
waiting for the target to be reached. Allows the protocol to proceed while the module
|
|
1098
|
+
reaches the target temperature.
|
|
1109
1099
|
Use :py:meth:`~.HeaterShakerContext.wait_for_temperature` to delay
|
|
1110
|
-
protocol execution for
|
|
1100
|
+
protocol execution for API levels below 2.27.
|
|
1111
1101
|
|
|
1112
1102
|
.. versionchanged:: 2.25
|
|
1113
1103
|
Removed the minimum temperature limit of 37 °C. Note that temperatures under ambient are
|
|
1114
1104
|
not achievable.
|
|
1115
1105
|
.. versionchanged:: 2.27
|
|
1116
|
-
Returns a
|
|
1117
|
-
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the
|
|
1106
|
+
Returns a :py:class:`Task` object that represents concurrent heating.
|
|
1107
|
+
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the module to reach the target temperature.
|
|
1118
1108
|
|
|
1119
1109
|
:param celsius: A value under 95, representing the target temperature in °C.
|
|
1120
1110
|
Values are automatically truncated to two decimal places,
|
|
@@ -1158,11 +1148,11 @@ class HeaterShakerContext(ModuleContext):
|
|
|
1158
1148
|
@requires_version(2, 27)
|
|
1159
1149
|
@publish(command=cmds.heater_shaker_set_shake_speed)
|
|
1160
1150
|
def set_shake_speed(self, rpm: int) -> Task:
|
|
1161
|
-
"""
|
|
1151
|
+
"""Sets the Heater-Shaker's shake speed in RPM and returns a :py:class:`Task` that represents concurrent shaking.
|
|
1162
1152
|
|
|
1163
1153
|
.. note::
|
|
1164
1154
|
|
|
1165
|
-
Before shaking, this command
|
|
1155
|
+
Before shaking, this command retracts pipettes upward if they are adjacent to the Heater-Shaker Module.
|
|
1166
1156
|
|
|
1167
1157
|
:param rpm: A value between 200 and 3000, representing the target shake speed in revolutions per minute.
|
|
1168
1158
|
"""
|
|
@@ -1289,7 +1289,7 @@ class ProtocolContext(CommandPublisher):
|
|
|
1289
1289
|
def wait_for_tasks(self, tasks: list[Task]) -> None:
|
|
1290
1290
|
"""Wait for a list of tasks to complete before executing subsequent commands.
|
|
1291
1291
|
|
|
1292
|
-
:param list Task: tasks: A list of Task objects to wait for.
|
|
1292
|
+
:param list Task: tasks: A list of :py:class:`Task` objects to wait for.
|
|
1293
1293
|
|
|
1294
1294
|
Task objects can be commands that are allowed to run concurrently.
|
|
1295
1295
|
"""
|
|
@@ -1299,7 +1299,7 @@ class ProtocolContext(CommandPublisher):
|
|
|
1299
1299
|
@publish(command=cmds.create_timer)
|
|
1300
1300
|
@requires_version(2, 27)
|
|
1301
1301
|
def create_timer(self, seconds: float) -> Task:
|
|
1302
|
-
"""Create a timer
|
|
1302
|
+
"""Create a timer :py:class:`Task` that runs in the background.
|
|
1303
1303
|
|
|
1304
1304
|
:param float seconds: The time to delay in seconds.
|
|
1305
1305
|
|
|
@@ -1833,17 +1833,15 @@ class ProtocolContext(CommandPublisher):
|
|
|
1833
1833
|
brightness: Optional[float] = None,
|
|
1834
1834
|
saturation: Optional[float] = None,
|
|
1835
1835
|
) -> None:
|
|
1836
|
-
"""Capture an image using the camera. Captured images
|
|
1837
|
-
|
|
1838
|
-
:param home_before:
|
|
1839
|
-
:param filename:
|
|
1840
|
-
:param resolution:
|
|
1841
|
-
:param zoom:
|
|
1842
|
-
:param contrast:
|
|
1843
|
-
:param brightness:
|
|
1844
|
-
:param saturation:
|
|
1845
|
-
|
|
1846
|
-
.. versionadded:: 2.27
|
|
1836
|
+
"""Capture an image using the camera. Captured images are saved as during the protocol run.
|
|
1837
|
+
|
|
1838
|
+
:param home_before: If ``True``, homes the pipette before capturing an image.
|
|
1839
|
+
:param filename: Custom name to use when saving the captured image as a file. The custom name is added as the beginning of the filename, followed by the robot and protocol name, a timestamp for the protocol run, the step number, and a timestamp for the command running when the image was captured.
|
|
1840
|
+
:param resolution: Accepts a width and height (as a tuple) to determine the camera's resolution when capturing the image.
|
|
1841
|
+
:param zoom: Zoom level the camera will use. Defaults to the minimum of 1x zoom (``1.0``) and has a maximum of 2x zoom (``2.0``).
|
|
1842
|
+
:param contrast: The contrast level to be applied to the image. The acceptable range is from 0 to 100; provided as a percentage (``0.0`` to ``100.0``).
|
|
1843
|
+
:param brightness: The brightness level to be applied to the image. The acceptable range is from 0 to 100; provided as a percentage (``0.0`` to ``100.0``).
|
|
1844
|
+
:param saturation: The saturation level to be applied to the image. The acceptable range is from 0 to 100; provided as a percentage (``0.0`` to ``100.0``).
|
|
1847
1845
|
|
|
1848
1846
|
"""
|
|
1849
1847
|
if home_before is True:
|
|
@@ -147,7 +147,17 @@ class AspirateWhileTrackingImplementation(
|
|
|
147
147
|
model_utils=self._model_utils,
|
|
148
148
|
movement_delay=params.movement_delay,
|
|
149
149
|
)
|
|
150
|
+
state_update.append(aspirate_result.state_update)
|
|
150
151
|
if isinstance(aspirate_result, DefinedErrorData):
|
|
152
|
+
state_update.set_liquid_operated(
|
|
153
|
+
labware_id=params.labwareId,
|
|
154
|
+
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
155
|
+
params.labwareId,
|
|
156
|
+
params.wellName,
|
|
157
|
+
params.pipetteId,
|
|
158
|
+
),
|
|
159
|
+
volume_added=CLEAR,
|
|
160
|
+
)
|
|
151
161
|
if isinstance(aspirate_result.public, OverpressureError):
|
|
152
162
|
return DefinedErrorData(
|
|
153
163
|
public=OverpressureError(
|
|
@@ -156,15 +166,7 @@ class AspirateWhileTrackingImplementation(
|
|
|
156
166
|
wrappedErrors=aspirate_result.public.wrappedErrors,
|
|
157
167
|
errorInfo=aspirate_result.public.errorInfo,
|
|
158
168
|
),
|
|
159
|
-
state_update=
|
|
160
|
-
labware_id=params.labwareId,
|
|
161
|
-
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
162
|
-
params.labwareId,
|
|
163
|
-
params.wellName,
|
|
164
|
-
params.pipetteId,
|
|
165
|
-
),
|
|
166
|
-
volume_added=CLEAR,
|
|
167
|
-
),
|
|
169
|
+
state_update=state_update,
|
|
168
170
|
state_update_if_false_positive=aspirate_result.state_update_if_false_positive,
|
|
169
171
|
)
|
|
170
172
|
elif isinstance(aspirate_result.public, StallOrCollisionError):
|
|
@@ -175,15 +177,7 @@ class AspirateWhileTrackingImplementation(
|
|
|
175
177
|
wrappedErrors=aspirate_result.public.wrappedErrors,
|
|
176
178
|
errorInfo=aspirate_result.public.errorInfo,
|
|
177
179
|
),
|
|
178
|
-
state_update=
|
|
179
|
-
labware_id=params.labwareId,
|
|
180
|
-
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
181
|
-
params.labwareId,
|
|
182
|
-
params.wellName,
|
|
183
|
-
params.pipetteId,
|
|
184
|
-
),
|
|
185
|
-
volume_added=CLEAR,
|
|
186
|
-
),
|
|
180
|
+
state_update=state_update,
|
|
187
181
|
state_update_if_false_positive=aspirate_result.state_update_if_false_positive,
|
|
188
182
|
)
|
|
189
183
|
|
|
@@ -200,7 +194,7 @@ class AspirateWhileTrackingImplementation(
|
|
|
200
194
|
volume=aspirate_result.public.volume,
|
|
201
195
|
position=result_deck_point,
|
|
202
196
|
),
|
|
203
|
-
state_update=
|
|
197
|
+
state_update=state_update.set_liquid_operated(
|
|
204
198
|
labware_id=params.labwareId,
|
|
205
199
|
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
206
200
|
params.labwareId,
|
|
@@ -143,8 +143,17 @@ class DispenseWhileTrackingImplementation(
|
|
|
143
143
|
model_utils=self._model_utils,
|
|
144
144
|
movement_delay=params.movement_delay,
|
|
145
145
|
)
|
|
146
|
-
|
|
146
|
+
state_update.append(dispense_result.state_update)
|
|
147
147
|
if isinstance(dispense_result, DefinedErrorData):
|
|
148
|
+
state_update.set_liquid_operated(
|
|
149
|
+
labware_id=params.labwareId,
|
|
150
|
+
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
151
|
+
params.labwareId,
|
|
152
|
+
params.wellName,
|
|
153
|
+
params.pipetteId,
|
|
154
|
+
),
|
|
155
|
+
volume_added=CLEAR,
|
|
156
|
+
)
|
|
148
157
|
if isinstance(dispense_result.public, OverpressureError):
|
|
149
158
|
return DefinedErrorData(
|
|
150
159
|
public=OverpressureError(
|
|
@@ -153,15 +162,7 @@ class DispenseWhileTrackingImplementation(
|
|
|
153
162
|
wrappedErrors=dispense_result.public.wrappedErrors,
|
|
154
163
|
errorInfo=dispense_result.public.errorInfo,
|
|
155
164
|
),
|
|
156
|
-
state_update=
|
|
157
|
-
labware_id=params.labwareId,
|
|
158
|
-
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
159
|
-
params.labwareId,
|
|
160
|
-
params.wellName,
|
|
161
|
-
params.pipetteId,
|
|
162
|
-
),
|
|
163
|
-
volume_added=CLEAR,
|
|
164
|
-
),
|
|
165
|
+
state_update=state_update,
|
|
165
166
|
state_update_if_false_positive=dispense_result.state_update_if_false_positive,
|
|
166
167
|
)
|
|
167
168
|
elif isinstance(dispense_result.public, StallOrCollisionError):
|
|
@@ -172,15 +173,7 @@ class DispenseWhileTrackingImplementation(
|
|
|
172
173
|
wrappedErrors=dispense_result.public.wrappedErrors,
|
|
173
174
|
errorInfo=dispense_result.public.errorInfo,
|
|
174
175
|
),
|
|
175
|
-
state_update=
|
|
176
|
-
labware_id=params.labwareId,
|
|
177
|
-
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
178
|
-
params.labwareId,
|
|
179
|
-
params.wellName,
|
|
180
|
-
params.pipetteId,
|
|
181
|
-
),
|
|
182
|
-
volume_added=CLEAR,
|
|
183
|
-
),
|
|
176
|
+
state_update=state_update,
|
|
184
177
|
state_update_if_false_positive=dispense_result.state_update_if_false_positive,
|
|
185
178
|
)
|
|
186
179
|
|
|
@@ -197,7 +190,7 @@ class DispenseWhileTrackingImplementation(
|
|
|
197
190
|
volume=dispense_result.public.volume,
|
|
198
191
|
position=result_deck_point,
|
|
199
192
|
),
|
|
200
|
-
state_update=
|
|
193
|
+
state_update=state_update.set_liquid_operated(
|
|
201
194
|
labware_id=params.labwareId,
|
|
202
195
|
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
203
196
|
params.labwareId,
|
|
@@ -248,7 +248,7 @@ class CommandExecutor:
|
|
|
248
248
|
# Only capture photos of errors if the setting to do so is enabled
|
|
249
249
|
if (
|
|
250
250
|
camera_enablement.cameraEnabled
|
|
251
|
-
and camera_enablement.
|
|
251
|
+
and camera_enablement.errorRecoveryCameraEnabled
|
|
252
252
|
):
|
|
253
253
|
# todo(chb, 2025-10-25): Eventually we will need to pass in client provided global settings here
|
|
254
254
|
image_data = await self._camera_provider.capture_image(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Pipetting command handling."""
|
|
2
|
+
|
|
2
3
|
from typing import Optional, Iterator, Tuple
|
|
3
4
|
from typing_extensions import Protocol as TypingProtocol
|
|
4
5
|
from contextlib import contextmanager
|
|
@@ -208,6 +209,9 @@ class HardwarePipettingHandler(PipettingHandler):
|
|
|
208
209
|
end_point=end_point,
|
|
209
210
|
volume=adjusted_volume,
|
|
210
211
|
movement_delay=movement_delay,
|
|
212
|
+
end_critical_point=self.get_state_view().motion.get_critical_point_for_wells_in_labware(
|
|
213
|
+
labware_id
|
|
214
|
+
),
|
|
211
215
|
)
|
|
212
216
|
return adjusted_volume
|
|
213
217
|
|
|
@@ -239,6 +243,9 @@ class HardwarePipettingHandler(PipettingHandler):
|
|
|
239
243
|
push_out=push_out,
|
|
240
244
|
is_full_dispense=is_full_dispense,
|
|
241
245
|
movement_delay=movement_delay,
|
|
246
|
+
end_critical_point=self.get_state_view().motion.get_critical_point_for_wells_in_labware(
|
|
247
|
+
labware_id
|
|
248
|
+
),
|
|
242
249
|
)
|
|
243
250
|
return adjusted_volume
|
|
244
251
|
|
|
@@ -27,7 +27,7 @@ class CameraSettings(BaseModel):
|
|
|
27
27
|
liveStreamEnabled: bool = Field(
|
|
28
28
|
..., description="Enablement status for the Opentrons Live Stream service."
|
|
29
29
|
)
|
|
30
|
-
|
|
30
|
+
errorRecoveryCameraEnabled: bool = Field(
|
|
31
31
|
..., description="Enablement status for camera usage with Error Recovery."
|
|
32
32
|
)
|
|
33
33
|
|
|
@@ -83,7 +83,7 @@ class CameraProvider:
|
|
|
83
83
|
return self._camera_settings_callback()
|
|
84
84
|
# If we are in analysis or simulation, return as if the camera is enabled
|
|
85
85
|
return CameraSettings(
|
|
86
|
-
cameraEnabled=True, liveStreamEnabled=True,
|
|
86
|
+
cameraEnabled=True, liveStreamEnabled=True, errorRecoveryCameraEnabled=True
|
|
87
87
|
)
|
|
88
88
|
|
|
89
89
|
async def capture_image(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Motion state store and getters."""
|
|
2
|
+
|
|
2
3
|
from dataclasses import dataclass
|
|
3
4
|
from typing import List, Optional, Union
|
|
4
5
|
import logging
|
|
@@ -78,14 +79,9 @@ class MotionView:
|
|
|
78
79
|
isinstance(current_location, CurrentWell)
|
|
79
80
|
and current_location.pipette_id == pipette_id
|
|
80
81
|
):
|
|
81
|
-
|
|
82
|
-
current_location.labware_id
|
|
83
|
-
):
|
|
84
|
-
critical_point = CriticalPoint.Y_CENTER
|
|
85
|
-
elif self._labware.get_should_center_pipette_on_target_well(
|
|
82
|
+
critical_point = self.get_critical_point_for_wells_in_labware(
|
|
86
83
|
current_location.labware_id
|
|
87
|
-
)
|
|
88
|
-
critical_point = CriticalPoint.XY_CENTER
|
|
84
|
+
)
|
|
89
85
|
return PipetteLocationData(mount=mount, critical_point=critical_point)
|
|
90
86
|
|
|
91
87
|
def _get_pipette_offset_for_reservoirs(
|
|
@@ -124,6 +120,17 @@ class MotionView:
|
|
|
124
120
|
x_offset = -1 * well_x_dim / 24
|
|
125
121
|
return Point(x=x_offset, y=y_offset)
|
|
126
122
|
|
|
123
|
+
def get_critical_point_for_wells_in_labware(
|
|
124
|
+
self, labware_id: str
|
|
125
|
+
) -> CriticalPoint | None:
|
|
126
|
+
"""Get the appropriate critical point override for this labware."""
|
|
127
|
+
if self._labware.get_should_center_column_on_target_well(labware_id):
|
|
128
|
+
return CriticalPoint.Y_CENTER
|
|
129
|
+
elif self._labware.get_should_center_pipette_on_target_well(labware_id):
|
|
130
|
+
return CriticalPoint.XY_CENTER
|
|
131
|
+
else:
|
|
132
|
+
return None
|
|
133
|
+
|
|
127
134
|
def get_movement_waypoints_to_well(
|
|
128
135
|
self,
|
|
129
136
|
pipette_id: str,
|
|
@@ -142,11 +149,7 @@ class MotionView:
|
|
|
142
149
|
"""Calculate waypoints to a destination that's specified as a well."""
|
|
143
150
|
location = current_well or self._pipettes.get_current_location()
|
|
144
151
|
|
|
145
|
-
destination_cp
|
|
146
|
-
if self._labware.get_should_center_column_on_target_well(labware_id):
|
|
147
|
-
destination_cp = CriticalPoint.Y_CENTER
|
|
148
|
-
elif self._labware.get_should_center_pipette_on_target_well(labware_id):
|
|
149
|
-
destination_cp = CriticalPoint.XY_CENTER
|
|
152
|
+
destination_cp = self.get_critical_point_for_wells_in_labware(labware_id)
|
|
150
153
|
|
|
151
154
|
destination = self._geometry.get_well_position(
|
|
152
155
|
labware_id=labware_id,
|
|
@@ -397,12 +400,7 @@ class MotionView:
|
|
|
397
400
|
mm_from_edge=mm_from_edge,
|
|
398
401
|
edge_path_type=edge_path_type,
|
|
399
402
|
)
|
|
400
|
-
critical_point
|
|
401
|
-
|
|
402
|
-
if self._labware.get_should_center_column_on_target_well(labware_id):
|
|
403
|
-
critical_point = CriticalPoint.Y_CENTER
|
|
404
|
-
elif self._labware.get_should_center_pipette_on_target_well(labware_id):
|
|
405
|
-
critical_point = CriticalPoint.XY_CENTER
|
|
403
|
+
critical_point = self.get_critical_point_for_wells_in_labware(labware_id)
|
|
406
404
|
|
|
407
405
|
return [
|
|
408
406
|
motion_planning.Waypoint(position=p, critical_point=critical_point)
|
|
@@ -841,8 +841,16 @@ class LegacyCommandMapper:
|
|
|
841
841
|
# We just set this above, so we know it's not None.
|
|
842
842
|
started_at=succeeded_command.startedAt, # type: ignore[arg-type]
|
|
843
843
|
)
|
|
844
|
+
state_update = StateUpdate()
|
|
845
|
+
state_update.set_load_module(
|
|
846
|
+
module_id=module_id,
|
|
847
|
+
definition=loaded_definition,
|
|
848
|
+
slot_name=module_load_info.deck_slot,
|
|
849
|
+
requested_model=requested_model,
|
|
850
|
+
serial_number=module_load_info.module_serial,
|
|
851
|
+
)
|
|
844
852
|
succeed_action = pe_actions.SucceedCommandAction(
|
|
845
|
-
command=succeeded_command, state_update=
|
|
853
|
+
command=succeeded_command, state_update=state_update
|
|
846
854
|
)
|
|
847
855
|
|
|
848
856
|
self._command_count["LOAD_MODULE"] = count + 1
|
opentrons/system/camera.py
CHANGED
|
@@ -158,7 +158,7 @@ async def update_live_stream_status(
|
|
|
158
158
|
and camera_enable_settings.liveStreamEnabled
|
|
159
159
|
):
|
|
160
160
|
# Check to see if the camera device is available
|
|
161
|
-
raw_device = str(contents["SOURCE"])
|
|
161
|
+
raw_device = str(contents["SOURCE"])
|
|
162
162
|
if not os.path.exists(raw_device):
|
|
163
163
|
log.error(
|
|
164
164
|
f"Opentrons Live Stream cannot sample the camera. No video device found with device path: {raw_device}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opentrons
|
|
3
|
-
Version: 8.8.
|
|
3
|
+
Version: 8.8.1
|
|
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.8.
|
|
27
|
+
Requires-Dist: opentrons-shared-data==8.8.1
|
|
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.8.
|
|
35
|
+
Requires-Dist: opentrons-hardware[flex]==8.8.1; extra == 'flex-hardware'
|
|
36
36
|
Provides-Extra: ot2-hardware
|
|
37
|
-
Requires-Dist: opentrons-hardware==8.8.
|
|
37
|
+
Requires-Dist: opentrons-hardware==8.8.1; 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=eQUIXJRYEBbJqcRjwHRZJ0kk0C6ZLf5dDS9zB1kUSBg,704
|
|
3
3
|
opentrons/execute.py,sha256=J7kZFRxpbrj_e5XS37Zc9fsliBqxZBMrITT7jdUgJvw,29478
|
|
4
4
|
opentrons/legacy_broker.py,sha256=XnuEBBlrHCThc31RFW2UR0tGqctqWZ-CZ9vSC4L9whU,1553
|
|
5
5
|
opentrons/ordered_set.py,sha256=g-SB3qA14yxHu9zjGyc2wC7d2TUCBE6fKZlHAtbPzI8,4082
|
|
@@ -53,7 +53,7 @@ opentrons/drivers/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
53
53
|
opentrons/drivers/asyncio/communication/__init__.py,sha256=b-rd_I0ecbexGm6b9T91JLfFUrCyui9V1N1j-fzy0SQ,523
|
|
54
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
|
-
opentrons/drivers/asyncio/communication/serial_connection.py,sha256=
|
|
56
|
+
opentrons/drivers/asyncio/communication/serial_connection.py,sha256=_gBhJxuoGN8Z8qNhOELHDC5PSXHp0G5M-0ZShoWlmrY,22973
|
|
57
57
|
opentrons/drivers/flex_stacker/__init__.py,sha256=LiM0onRlgC-JfFBd0QseQU0-3WuuIxa7GNFj7Douiq8,351
|
|
58
58
|
opentrons/drivers/flex_stacker/abstract.py,sha256=50xrkTC5qI_BsvlBGpdBLwF3GVi7HhKVSgloKwcrzNA,6744
|
|
59
59
|
opentrons/drivers/flex_stacker/driver.py,sha256=m43LDktLtRXSco_SgM-6yfx0GwoxkrV8Gz5aDtLgfN4,31670
|
|
@@ -111,7 +111,7 @@ opentrons/hardware_control/module_control.py,sha256=id1W3xqT-W-zyt2PVodo2Abx127t
|
|
|
111
111
|
opentrons/hardware_control/motion_utilities.py,sha256=aIaT-qzkRpZaSmfTTSqs1wl6m7LBxwKHIhgkFean01o,10274
|
|
112
112
|
opentrons/hardware_control/nozzle_manager.py,sha256=AG4HKrV4n0Bm0UOEsaAYAURtkJwuEyk97e9Nqv2_nD0,17021
|
|
113
113
|
opentrons/hardware_control/ot3_calibration.py,sha256=vHB17U-FBzytvM8QeEu5kRYPo8lFwAo31ZEpiU4yf_0,45000
|
|
114
|
-
opentrons/hardware_control/ot3api.py,sha256=
|
|
114
|
+
opentrons/hardware_control/ot3api.py,sha256=TNZnoe-52kobBcc622VAOdPByhw2DWl4H5_eO4fp9ag,131393
|
|
115
115
|
opentrons/hardware_control/pause_manager.py,sha256=wmNmraimE2yZQVqCxX_rtQHUWRzpzyQEaym9fLMgyww,888
|
|
116
116
|
opentrons/hardware_control/poller.py,sha256=6aqR0UM36w-Fk1ozjp-74VHthZTfT8Yurh5Zb4OnZX8,4392
|
|
117
117
|
opentrons/hardware_control/robot_calibration.py,sha256=ilszGjZPspKiEk8MQPaHm2B-ljeisAYflKl8UyQ_D0U,7155
|
|
@@ -198,7 +198,7 @@ opentrons/hardware_control/protocols/gripper_controller.py,sha256=EEfL-KUzegZBm_
|
|
|
198
198
|
opentrons/hardware_control/protocols/hardware_manager.py,sha256=S9BSJ0XsnU5A9nFLMDZfmiizx3T41WhU_91VYj4bUVE,1629
|
|
199
199
|
opentrons/hardware_control/protocols/identifiable.py,sha256=YmhScb4Tr4mxVObL1i7pI-EouTMAmV-2oqKbovhdnrE,575
|
|
200
200
|
opentrons/hardware_control/protocols/instrument_configurer.py,sha256=5zUCAchtoJ6QPFqcGRb7FOsnt2nxjxlRJdt18IidKqQ,7729
|
|
201
|
-
opentrons/hardware_control/protocols/liquid_handler.py,sha256=
|
|
201
|
+
opentrons/hardware_control/protocols/liquid_handler.py,sha256=OvGf1LSPZC3imLO0GsFitXA4GObhT-xUnArChuf-gm8,10765
|
|
202
202
|
opentrons/hardware_control/protocols/module_provider.py,sha256=QDKCWqrW-6IeI91IICBTJClK0C__mgq3A0-M3Wa9ee8,487
|
|
203
203
|
opentrons/hardware_control/protocols/motion_controller.py,sha256=mWUHVDqju9gcMDU9adk6UzueZ9i-x2nU5hmcd_fHHyk,9737
|
|
204
204
|
opentrons/hardware_control/protocols/position_estimator.py,sha256=BrqK5AJn9747c4LX0ZWBJWgWHjyX977CHBI7WVvO-9Q,1922
|
|
@@ -239,11 +239,11 @@ opentrons/protocol_api/config.py,sha256=r9lyvXjagTX_g3q5FGURPpcz2IA9sSF7Oa_1mKx-
|
|
|
239
239
|
opentrons/protocol_api/create_protocol_context.py,sha256=wwsZje0L__oDnu1Yrihau320_f-ASloR9eL1QCtkOh8,7612
|
|
240
240
|
opentrons/protocol_api/deck.py,sha256=94vFceg1SC1bAGd7TvC1ZpYwnJR-VlzurEZ6jkacYeg,8910
|
|
241
241
|
opentrons/protocol_api/disposal_locations.py,sha256=NRiSGmDR0LnbyEkWSOM-o64uR2fUoB1NWJG7Y7SsJSs,7920
|
|
242
|
-
opentrons/protocol_api/instrument_context.py,sha256=
|
|
242
|
+
opentrons/protocol_api/instrument_context.py,sha256=vTHZaNgQYNTDykggobDwbT4ATHC0yan6erCgW3tm86w,161119
|
|
243
243
|
opentrons/protocol_api/labware.py,sha256=ET9dymBh64jGUDlucdrlmBiOCVUJIOj1o2ePYxZ8U4g,63383
|
|
244
|
-
opentrons/protocol_api/module_contexts.py,sha256=
|
|
244
|
+
opentrons/protocol_api/module_contexts.py,sha256=_O23kVJSQ87JXVWNVoDTrwn2Ou4LsRdZiVvVHxXbqnM,73678
|
|
245
245
|
opentrons/protocol_api/module_validation_and_errors.py,sha256=ljst-M_KK78GnyG3pyZ_6yoYkMY3HORS1QyQyWrme-U,2250
|
|
246
|
-
opentrons/protocol_api/protocol_context.py,sha256=
|
|
246
|
+
opentrons/protocol_api/protocol_context.py,sha256=t4RMmw57mVuct41gIpgnnmhsrJryC08_cugjw-pPlNs,80261
|
|
247
247
|
opentrons/protocol_api/robot_context.py,sha256=OoxwSNsWkMXVf3SY_r1kUxokMDxIWT0A_9NqSTD37Z8,12962
|
|
248
248
|
opentrons/protocol_api/tasks.py,sha256=aAGXS9yGjdd9NNosf-o8K_DNRuPea9mimfX6L0Y7q38,1390
|
|
249
249
|
opentrons/protocol_api/validation.py,sha256=MZGafzegOBuK7TTXlkkGE2YQSY71RDrdxp4puKQBclc,30995
|
|
@@ -268,7 +268,7 @@ opentrons/protocol_api/core/engine/labware.py,sha256=YUkoCogqLQpDee-wlcMPV90ZUi7
|
|
|
268
268
|
opentrons/protocol_api/core/engine/load_labware_params.py,sha256=CxSbCBXVXHtBszP-3Ko8hsQTjvvogKRo0CCzCmMfIic,3003
|
|
269
269
|
opentrons/protocol_api/core/engine/module_core.py,sha256=SBglcDmhwTrk_IfIgkzHsux9NEDQZ4OgzycAoO0qRdY,43222
|
|
270
270
|
opentrons/protocol_api/core/engine/overlap_versions.py,sha256=PyGvQtQUg1wzNtkuGZtxwXm019PoIjq7em2JiWaxbXc,675
|
|
271
|
-
opentrons/protocol_api/core/engine/pipette_movement_conflict.py,sha256=
|
|
271
|
+
opentrons/protocol_api/core/engine/pipette_movement_conflict.py,sha256=vjKuEmKU67M43dTTNoRvRwjPFx1a6sDEHNDp-8KuiuI,17386
|
|
272
272
|
opentrons/protocol_api/core/engine/point_calculations.py,sha256=C2eF0fvJQGMqQv3DzNhc1-m8HTAXTyTsHPJEPrEUEmo,2502
|
|
273
273
|
opentrons/protocol_api/core/engine/protocol.py,sha256=nZCWd6vq6PAzZVU_0kl3PPtcgtshN3xgWE2ixhiRK2g,50017
|
|
274
274
|
opentrons/protocol_api/core/engine/robot.py,sha256=bzUt23NG-clD-9-QFsV_6nm3fMgSmvYEG9DyyZI1xgw,5366
|
|
@@ -313,7 +313,7 @@ opentrons/protocol_engine/commands/__init__.py,sha256=0RzukdT-cYTbDjx1ZSeVzF-42f
|
|
|
313
313
|
opentrons/protocol_engine/commands/air_gap_in_place.py,sha256=3O0FnIRgiEYtW1_LjBKElL7iSP5iBQUnNi7tNUlLnyg,5444
|
|
314
314
|
opentrons/protocol_engine/commands/aspirate.py,sha256=DmUHHWQ1NYUv19bjR-o4CawWaNt0eQomlISWG_YI2FQ,7977
|
|
315
315
|
opentrons/protocol_engine/commands/aspirate_in_place.py,sha256=ZHvq8zcgAhDRScwFxCAySSnW0FCtOElSypcSUMom-3k,6587
|
|
316
|
-
opentrons/protocol_engine/commands/aspirate_while_tracking.py,sha256=
|
|
316
|
+
opentrons/protocol_engine/commands/aspirate_while_tracking.py,sha256=btThzAABeNqvfRsRwX3SPAZp-2PDHnEYmCk7algxyxE,8642
|
|
317
317
|
opentrons/protocol_engine/commands/blow_out.py,sha256=3gboq4x5S8fq7j4ZZGNClXFDlOjcdW1v2g58GPdhaPI,4338
|
|
318
318
|
opentrons/protocol_engine/commands/blow_out_in_place.py,sha256=jm2XXyJfIP9-AAFwXhD59_13nX18-i6QqpLGb-lK7sI,3391
|
|
319
319
|
opentrons/protocol_engine/commands/capture_image.py,sha256=z2FngPAT345FH7-vPQZv-HwUqRMvF6yopJ-8WmAUcFE,10928
|
|
@@ -326,7 +326,7 @@ opentrons/protocol_engine/commands/create_timer.py,sha256=xK2uxexIbIN6gCjci1P7Wb
|
|
|
326
326
|
opentrons/protocol_engine/commands/custom.py,sha256=vOJc7QSNnYTpLvJm98OfDKjgcvVFRZs1eEKEd9WkPN0,2157
|
|
327
327
|
opentrons/protocol_engine/commands/dispense.py,sha256=dEx24qS1Rhrc5-g_HwuLVqUeNZxpSjevqKX_josj60U,6501
|
|
328
328
|
opentrons/protocol_engine/commands/dispense_in_place.py,sha256=gcj0HXUkPrU3Qz_DbWzP3XZHuB8tXSMTo9CFoGi25lw,6263
|
|
329
|
-
opentrons/protocol_engine/commands/dispense_while_tracking.py,sha256=
|
|
329
|
+
opentrons/protocol_engine/commands/dispense_while_tracking.py,sha256=GKwjhY9AzqnjdiQpTourTjEOUwCNj8Mik6qPD1lcZOk,8051
|
|
330
330
|
opentrons/protocol_engine/commands/drop_tip.py,sha256=LpgwnsaHYPCHqewI2mHs9fWFCvhhVgzkPMlCk155Ja0,9077
|
|
331
331
|
opentrons/protocol_engine/commands/drop_tip_in_place.py,sha256=88dPdt48hnURavIE46E7Zaxv-h9YN5Bq8XczCwHlW_I,7262
|
|
332
332
|
opentrons/protocol_engine/commands/generate_command_schema.py,sha256=e88q7DCxjEM1xSrnXV8jBdo6AgMc15_W8cC-i-ESvy0,2312
|
|
@@ -437,7 +437,7 @@ opentrons/protocol_engine/errors/__init__.py,sha256=S3JMMqRTT4f36RwwVhyg-Kcqu1M2
|
|
|
437
437
|
opentrons/protocol_engine/errors/error_occurrence.py,sha256=ODyXHxVO4iXDxpcLaC3uO7ocTOOGPqWwcC1uaiytv0c,7846
|
|
438
438
|
opentrons/protocol_engine/errors/exceptions.py,sha256=TawUeV_qaIPf-U0Rfihnxfz6a4_3Zt7f4klMZyXNl9A,50065
|
|
439
439
|
opentrons/protocol_engine/execution/__init__.py,sha256=9R8ux152aTGKDoZ3x7KyisQAOj6MIZOtrPQmPNIOjKY,1518
|
|
440
|
-
opentrons/protocol_engine/execution/command_executor.py,sha256=
|
|
440
|
+
opentrons/protocol_engine/execution/command_executor.py,sha256=29CMlYbtepfExSVDyWl-mM0oZDtyLBcGVXCyHkQv0C8,11135
|
|
441
441
|
opentrons/protocol_engine/execution/create_queue_worker.py,sha256=JqbMIT7nqwgKdRs86GL5LoA6cC42G3IT_eqOZYVEIhg,3740
|
|
442
442
|
opentrons/protocol_engine/execution/door_watcher.py,sha256=C1CojQj_ddNAC5rS8YMZZbJtfmz2K9zYqllWTg5NKgU,4634
|
|
443
443
|
opentrons/protocol_engine/execution/equipment.py,sha256=Jbg9ZR7vTw3i3WDy0xNe9J5idFuXkdxPSzfWaYH2DyI,30046
|
|
@@ -447,7 +447,7 @@ opentrons/protocol_engine/execution/hardware_stopper.py,sha256=ZlhVYEdFfuKqp5slZ
|
|
|
447
447
|
opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py,sha256=BSFLzSSeELAYZCrCUfJZx5DdlrwU06Ur92TYd0T-hzM,9084
|
|
448
448
|
opentrons/protocol_engine/execution/labware_movement.py,sha256=RJMkWHGvoKc0GXjEZ2ZXWo1v9cvPlmbEdFBs0szROfo,12965
|
|
449
449
|
opentrons/protocol_engine/execution/movement.py,sha256=NJUs1mtC8R8qR1x2RVTI3q9hyVuLkvCvIM1SnD8sPH0,12899
|
|
450
|
-
opentrons/protocol_engine/execution/pipetting.py,sha256=
|
|
450
|
+
opentrons/protocol_engine/execution/pipetting.py,sha256=0hRu_erRItLj_TYfKx-NTibprYKfzros8HWsbZRf_q8,22067
|
|
451
451
|
opentrons/protocol_engine/execution/queue_worker.py,sha256=2cfyplUWdPyxxLbH3H8TbtB9Fvjx__ASluiJXyJBoqU,3537
|
|
452
452
|
opentrons/protocol_engine/execution/rail_lights.py,sha256=eiJT6oI_kFk7rFuFkZzISZiLNnpf7Kkh86Kyk9wQ_Jo,590
|
|
453
453
|
opentrons/protocol_engine/execution/run_control.py,sha256=Wn3FGuBZrYddf7Dzcz5v1hHF0DbzRxCykl6vs15BZP0,1450
|
|
@@ -459,7 +459,7 @@ opentrons/protocol_engine/execution/tip_handler.py,sha256=Ouunj3KVqz-UMbkjFIbJJr
|
|
|
459
459
|
opentrons/protocol_engine/notes/__init__.py,sha256=G0bIQswsov7MrJU0ArrOaWcOTxJU9BCUmNR3LRoNg-Q,311
|
|
460
460
|
opentrons/protocol_engine/notes/notes.py,sha256=A5C9xHExlS9GAK7o_mYiKJgibBm6EEgHQ4PJor0IET0,1993
|
|
461
461
|
opentrons/protocol_engine/resources/__init__.py,sha256=URDW9VirxadLU6tPOQ4-MCDvQBE3nGCnkKzdAJVicyo,952
|
|
462
|
-
opentrons/protocol_engine/resources/camera_provider.py,sha256=
|
|
462
|
+
opentrons/protocol_engine/resources/camera_provider.py,sha256=waidRhgCP0hMOKvineDU-gkIb15G6s70e2gpAAhXaD4,4807
|
|
463
463
|
opentrons/protocol_engine/resources/concurrency_provider.py,sha256=iEi1jOaOTQAFTKSkGex0GRMihKvouftbxuDH8GdVRkI,941
|
|
464
464
|
opentrons/protocol_engine/resources/deck_configuration_provider.py,sha256=8gA5gHaXbTf03-60QSg5qsBHrAIcfvNSaOTcyJJw9EA,9712
|
|
465
465
|
opentrons/protocol_engine/resources/deck_data_provider.py,sha256=63c-Hmwy5IbVSoAL3hYoZxizxwzCqbB2KgJptpLX3Bc,3001
|
|
@@ -489,7 +489,7 @@ opentrons/protocol_engine/state/labware.py,sha256=y-vZnirUS84RatzUu960CsbGb2lW9f
|
|
|
489
489
|
opentrons/protocol_engine/state/liquid_classes.py,sha256=u_z75UYdiFAKG0yB3mr1il4T3qaS0Sotq8sL7KLODP8,2990
|
|
490
490
|
opentrons/protocol_engine/state/liquids.py,sha256=NoesktcQdJUjIVmet1uqqJPf-rzbo4SGemXwQC295W0,2338
|
|
491
491
|
opentrons/protocol_engine/state/modules.py,sha256=rL_Xm7vNQrYsa6F3VYUJZVrehMfAnwvf0wXPyPH19PU,63087
|
|
492
|
-
opentrons/protocol_engine/state/motion.py,sha256=
|
|
492
|
+
opentrons/protocol_engine/state/motion.py,sha256=1pqxThXdUG7TQqYxyxUX3x49CUcdKqAAV-6o4jeKICo,16737
|
|
493
493
|
opentrons/protocol_engine/state/pipettes.py,sha256=Q-aDiVvOVvUXq930vvMvAWhK7aZ06-8FLZB6jO95dwQ,38531
|
|
494
494
|
opentrons/protocol_engine/state/preconditions.py,sha256=Qvv2Mnwdw2SzkVkfV1vcXNT-M9mbnITBPq9qkhZAa2o,2198
|
|
495
495
|
opentrons/protocol_engine/state/state.py,sha256=-Lrag0Az9eh9A4xUcv1qE2sqC6ZX3nXnoElk2a3hZuI,17193
|
|
@@ -548,7 +548,7 @@ opentrons/protocol_runner/__init__.py,sha256=Sr0gBDzNv3nuHPapeNy_IWadhohtwmlhfnB
|
|
|
548
548
|
opentrons/protocol_runner/create_simulating_orchestrator.py,sha256=yqDNIeOaZR20cQTQfQJuzyJKXchJ_-BGbkP2x79qGJo,5245
|
|
549
549
|
opentrons/protocol_runner/json_file_reader.py,sha256=dE9ujq3sWyKF1yFg0AN8h-roGVfvqf1tEcIq5wxHbxE,2341
|
|
550
550
|
opentrons/protocol_runner/json_translator.py,sha256=lrDzHOOkQ19ac4KEdUbfEOnfx-F_QCO-6oGqQZegy4g,12134
|
|
551
|
-
opentrons/protocol_runner/legacy_command_mapper.py,sha256=
|
|
551
|
+
opentrons/protocol_runner/legacy_command_mapper.py,sha256=vg_HlQOdncBFo3u2pTJ6lU3ZfmRCUTuFc0WByDs4LEc,37437
|
|
552
552
|
opentrons/protocol_runner/legacy_context_plugin.py,sha256=G_qpeyaLvsCjb72_n96Luy8CPSfgPZpt0QKVzKc6LKY,4730
|
|
553
553
|
opentrons/protocol_runner/protocol_runner.py,sha256=yK-A4x4Wue7TBAd3CafrbNYEXdoKx-qGSxyIJeOBdKU,22227
|
|
554
554
|
opentrons/protocol_runner/python_protocol_wrappers.py,sha256=KEuM4M7rYD4zLjTqK89T47CiBIZJ42kG0JXWarLUq4E,6511
|
|
@@ -602,7 +602,7 @@ opentrons/protocols/parameters/validation.py,sha256=uNwoU3cUlnV5NdvnR6vyxoTNUwos
|
|
|
602
602
|
opentrons/resources/smoothie-edge-8414642.hex,sha256=1hiY8t0wTnMSLtIVe_lVhgFR6pdEsh4PEPjv99xbVVA,1035222
|
|
603
603
|
opentrons/resources/scripts/lpc21isp,sha256=tioSU5T7a9otaalLK91_jTcgmRRXb10JQGfmGO_iKn8,329864
|
|
604
604
|
opentrons/system/__init__.py,sha256=_0_HR5vwNng4bsxU_gI0KAREkvb1TogdsNmOHR3V71g,307
|
|
605
|
-
opentrons/system/camera.py,sha256=
|
|
605
|
+
opentrons/system/camera.py,sha256=1phNw_grGL4419JxMvCnhylzI8dzCJp8Le-OLrQbRQI,13742
|
|
606
606
|
opentrons/system/ffmpeg.py,sha256=BMSICDtviItldSOPZ8kLMBlK1w-Tyjb8CFnYj7Yzm-I,4086
|
|
607
607
|
opentrons/system/log_control.py,sha256=4whbd1AFbRJOByQ6bZaiOQ8Dhi3YceBHYzIBStY38Vw,1535
|
|
608
608
|
opentrons/system/nmcli.py,sha256=OBLIBlP5wwjh-tzO5p2-h7jJ4-1kgI-mCti6NS7589Y,30317
|
|
@@ -623,8 +623,8 @@ opentrons/util/linal.py,sha256=IlKAP9HkNBBgULeSf4YVwSKHdx9jnCjSr7nvDvlRALg,5753
|
|
|
623
623
|
opentrons/util/logging_config.py,sha256=7et4YYuQdWdq_e50U-8vFS_QyNBRgdnqPGAQJm8qrIo,9954
|
|
624
624
|
opentrons/util/logging_queue_handler.py,sha256=ZsSJwy-oV8DXwpYiZisQ1PbYwmK2cOslD46AcyJ1E4I,2484
|
|
625
625
|
opentrons/util/performance_helpers.py,sha256=ew7H8XD20iS6-2TJAzbQeyzStZkkE6PzHt_Adx3wbZQ,5172
|
|
626
|
-
opentrons-8.8.
|
|
627
|
-
opentrons-8.8.
|
|
628
|
-
opentrons-8.8.
|
|
629
|
-
opentrons-8.8.
|
|
630
|
-
opentrons-8.8.
|
|
626
|
+
opentrons-8.8.1.dist-info/METADATA,sha256=pXtrtXzADhKNCss5qKplRrffvEXB0Hu9XJ4fPUVhfjs,1599
|
|
627
|
+
opentrons-8.8.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
628
|
+
opentrons-8.8.1.dist-info/entry_points.txt,sha256=fTa6eGCYkvOtv0ov-KVE8LLGetgb35LQLF9x85OWPVw,106
|
|
629
|
+
opentrons-8.8.1.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
630
|
+
opentrons-8.8.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|