opentrons 8.7.0a9__py3-none-any.whl → 8.8.0a8__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/cli/analyze.py +4 -1
- opentrons/config/__init__.py +7 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +126 -49
- opentrons/drivers/heater_shaker/abstract.py +5 -0
- opentrons/drivers/heater_shaker/driver.py +10 -0
- opentrons/drivers/heater_shaker/simulator.py +4 -0
- opentrons/drivers/thermocycler/abstract.py +6 -0
- opentrons/drivers/thermocycler/driver.py +61 -10
- opentrons/drivers/thermocycler/simulator.py +6 -0
- opentrons/drivers/vacuum_module/__init__.py +5 -0
- opentrons/drivers/vacuum_module/abstract.py +93 -0
- opentrons/drivers/vacuum_module/driver.py +208 -0
- opentrons/drivers/vacuum_module/errors.py +39 -0
- opentrons/drivers/vacuum_module/simulator.py +85 -0
- opentrons/drivers/vacuum_module/types.py +79 -0
- opentrons/execute.py +3 -0
- opentrons/hardware_control/api.py +24 -5
- opentrons/hardware_control/backends/controller.py +8 -2
- opentrons/hardware_control/backends/flex_protocol.py +1 -0
- opentrons/hardware_control/backends/ot3controller.py +35 -2
- opentrons/hardware_control/backends/ot3simulator.py +3 -1
- opentrons/hardware_control/backends/ot3utils.py +37 -0
- opentrons/hardware_control/backends/simulator.py +2 -1
- opentrons/hardware_control/backends/subsystem_manager.py +5 -2
- opentrons/hardware_control/emulation/abstract_emulator.py +6 -4
- opentrons/hardware_control/emulation/connection_handler.py +8 -5
- opentrons/hardware_control/emulation/heater_shaker.py +12 -3
- opentrons/hardware_control/emulation/settings.py +1 -1
- opentrons/hardware_control/emulation/thermocycler.py +67 -15
- opentrons/hardware_control/module_control.py +105 -10
- opentrons/hardware_control/modules/__init__.py +3 -0
- opentrons/hardware_control/modules/absorbance_reader.py +11 -4
- opentrons/hardware_control/modules/flex_stacker.py +38 -9
- opentrons/hardware_control/modules/heater_shaker.py +42 -5
- opentrons/hardware_control/modules/magdeck.py +8 -4
- opentrons/hardware_control/modules/mod_abc.py +14 -6
- opentrons/hardware_control/modules/tempdeck.py +25 -5
- opentrons/hardware_control/modules/thermocycler.py +68 -11
- opentrons/hardware_control/modules/types.py +20 -1
- opentrons/hardware_control/modules/utils.py +11 -4
- opentrons/hardware_control/motion_utilities.py +6 -6
- opentrons/hardware_control/nozzle_manager.py +3 -0
- opentrons/hardware_control/ot3api.py +92 -17
- opentrons/hardware_control/poller.py +22 -8
- opentrons/hardware_control/protocols/liquid_handler.py +12 -4
- opentrons/hardware_control/scripts/update_module_fw.py +5 -0
- opentrons/hardware_control/types.py +43 -2
- opentrons/legacy_commands/commands.py +58 -5
- opentrons/legacy_commands/module_commands.py +52 -0
- opentrons/legacy_commands/protocol_commands.py +53 -1
- opentrons/legacy_commands/types.py +155 -1
- opentrons/motion_planning/deck_conflict.py +17 -12
- opentrons/motion_planning/waypoints.py +15 -29
- opentrons/protocol_api/__init__.py +5 -1
- opentrons/protocol_api/_transfer_liquid_validation.py +17 -2
- opentrons/protocol_api/_types.py +8 -1
- opentrons/protocol_api/core/common.py +3 -1
- opentrons/protocol_api/core/engine/_default_labware_versions.py +33 -11
- opentrons/protocol_api/core/engine/deck_conflict.py +3 -1
- opentrons/protocol_api/core/engine/instrument.py +109 -26
- opentrons/protocol_api/core/engine/labware.py +8 -1
- opentrons/protocol_api/core/engine/module_core.py +95 -4
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +4 -18
- opentrons/protocol_api/core/engine/protocol.py +51 -2
- opentrons/protocol_api/core/engine/stringify.py +2 -0
- opentrons/protocol_api/core/engine/tasks.py +48 -0
- opentrons/protocol_api/core/engine/well.py +8 -0
- opentrons/protocol_api/core/instrument.py +19 -2
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +19 -2
- opentrons/protocol_api/core/legacy/legacy_module_core.py +33 -2
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +23 -1
- opentrons/protocol_api/core/legacy/legacy_well_core.py +4 -0
- opentrons/protocol_api/core/legacy/tasks.py +19 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +19 -2
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +14 -2
- opentrons/protocol_api/core/legacy_simulator/tasks.py +19 -0
- opentrons/protocol_api/core/module.py +58 -2
- opentrons/protocol_api/core/protocol.py +23 -2
- opentrons/protocol_api/core/tasks.py +31 -0
- opentrons/protocol_api/core/well.py +4 -0
- opentrons/protocol_api/instrument_context.py +388 -2
- opentrons/protocol_api/labware.py +10 -2
- opentrons/protocol_api/module_contexts.py +170 -6
- opentrons/protocol_api/protocol_context.py +87 -21
- opentrons/protocol_api/robot_context.py +41 -25
- opentrons/protocol_api/tasks.py +48 -0
- opentrons/protocol_api/validation.py +49 -3
- opentrons/protocol_engine/__init__.py +4 -0
- opentrons/protocol_engine/actions/__init__.py +6 -2
- opentrons/protocol_engine/actions/actions.py +31 -9
- opentrons/protocol_engine/clients/sync_client.py +42 -7
- opentrons/protocol_engine/commands/__init__.py +56 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +2 -15
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +2 -15
- opentrons/protocol_engine/commands/absorbance_reader/read.py +22 -23
- opentrons/protocol_engine/commands/aspirate.py +1 -0
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +52 -19
- opentrons/protocol_engine/commands/capture_image.py +302 -0
- opentrons/protocol_engine/commands/command.py +2 -0
- opentrons/protocol_engine/commands/command_unions.py +62 -0
- opentrons/protocol_engine/commands/create_timer.py +83 -0
- opentrons/protocol_engine/commands/dispense.py +1 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +56 -19
- opentrons/protocol_engine/commands/drop_tip.py +32 -8
- opentrons/protocol_engine/commands/flex_stacker/common.py +35 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +7 -0
- opentrons/protocol_engine/commands/heater_shaker/__init__.py +14 -0
- opentrons/protocol_engine/commands/heater_shaker/common.py +20 -0
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +5 -4
- opentrons/protocol_engine/commands/heater_shaker/set_shake_speed.py +136 -0
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +31 -5
- opentrons/protocol_engine/commands/move_labware.py +3 -4
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +1 -1
- opentrons/protocol_engine/commands/movement_common.py +31 -2
- opentrons/protocol_engine/commands/pick_up_tip.py +21 -11
- opentrons/protocol_engine/commands/pipetting_common.py +48 -3
- opentrons/protocol_engine/commands/set_tip_state.py +97 -0
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +38 -7
- opentrons/protocol_engine/commands/thermocycler/__init__.py +16 -0
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +6 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +8 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +44 -7
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +43 -14
- opentrons/protocol_engine/commands/thermocycler/start_run_extended_profile.py +191 -0
- opentrons/protocol_engine/commands/touch_tip.py +1 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +6 -22
- opentrons/protocol_engine/commands/wait_for_tasks.py +98 -0
- opentrons/protocol_engine/create_protocol_engine.py +12 -0
- opentrons/protocol_engine/engine_support.py +3 -0
- opentrons/protocol_engine/errors/__init__.py +12 -0
- opentrons/protocol_engine/errors/exceptions.py +119 -0
- opentrons/protocol_engine/execution/__init__.py +4 -0
- opentrons/protocol_engine/execution/command_executor.py +62 -1
- opentrons/protocol_engine/execution/create_queue_worker.py +9 -2
- opentrons/protocol_engine/execution/labware_movement.py +13 -15
- opentrons/protocol_engine/execution/movement.py +2 -0
- opentrons/protocol_engine/execution/pipetting.py +26 -25
- opentrons/protocol_engine/execution/queue_worker.py +4 -0
- opentrons/protocol_engine/execution/run_control.py +8 -0
- opentrons/protocol_engine/execution/task_handler.py +157 -0
- opentrons/protocol_engine/protocol_engine.py +137 -36
- opentrons/protocol_engine/resources/__init__.py +4 -0
- opentrons/protocol_engine/resources/camera_provider.py +110 -0
- opentrons/protocol_engine/resources/concurrency_provider.py +27 -0
- opentrons/protocol_engine/resources/deck_configuration_provider.py +7 -0
- opentrons/protocol_engine/resources/file_provider.py +133 -58
- opentrons/protocol_engine/resources/labware_validation.py +10 -6
- opentrons/protocol_engine/slot_standardization.py +2 -0
- opentrons/protocol_engine/state/_well_math.py +60 -18
- opentrons/protocol_engine/state/addressable_areas.py +2 -0
- opentrons/protocol_engine/state/camera.py +54 -0
- opentrons/protocol_engine/state/commands.py +37 -14
- opentrons/protocol_engine/state/geometry.py +276 -379
- opentrons/protocol_engine/state/labware.py +62 -108
- opentrons/protocol_engine/state/labware_origin_math/errors.py +94 -0
- opentrons/protocol_engine/state/labware_origin_math/stackup_origin_to_labware_origin.py +1336 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +37 -0
- opentrons/protocol_engine/state/modules.py +30 -8
- opentrons/protocol_engine/state/motion.py +60 -18
- opentrons/protocol_engine/state/preconditions.py +59 -0
- opentrons/protocol_engine/state/state.py +44 -0
- opentrons/protocol_engine/state/state_summary.py +4 -0
- opentrons/protocol_engine/state/tasks.py +139 -0
- opentrons/protocol_engine/state/tips.py +177 -258
- opentrons/protocol_engine/state/update_types.py +26 -9
- opentrons/protocol_engine/types/__init__.py +23 -4
- opentrons/protocol_engine/types/command_preconditions.py +18 -0
- opentrons/protocol_engine/types/deck_configuration.py +5 -1
- opentrons/protocol_engine/types/instrument.py +8 -1
- opentrons/protocol_engine/types/labware.py +1 -13
- opentrons/protocol_engine/types/location.py +26 -2
- opentrons/protocol_engine/types/module.py +11 -1
- opentrons/protocol_engine/types/tasks.py +38 -0
- opentrons/protocol_engine/types/tip.py +9 -0
- opentrons/protocol_runner/create_simulating_orchestrator.py +29 -2
- opentrons/protocol_runner/protocol_runner.py +14 -1
- opentrons/protocol_runner/run_orchestrator.py +49 -2
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +2 -2
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/types.py +2 -1
- opentrons/simulate.py +51 -15
- opentrons/system/camera.py +334 -4
- opentrons/system/ffmpeg.py +110 -0
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/METADATA +4 -4
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/RECORD +189 -161
- opentrons/protocol_engine/state/_labware_origin_math.py +0 -636
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/WHEEL +0 -0
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/entry_points.txt +0 -0
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/licenses/LICENSE +0 -0
|
@@ -43,7 +43,8 @@ from .module_validation_and_errors import (
|
|
|
43
43
|
)
|
|
44
44
|
from .labware import Labware
|
|
45
45
|
from . import validation
|
|
46
|
-
|
|
46
|
+
from . import Task
|
|
47
|
+
from opentrons.drivers.thermocycler.driver import BLOCK_VOL_MIN, BLOCK_VOL_MAX
|
|
47
48
|
|
|
48
49
|
_MAGNETIC_MODULE_HEIGHT_PARAM_REMOVED_IN = APIVersion(2, 14)
|
|
49
50
|
|
|
@@ -447,18 +448,28 @@ class TemperatureModuleContext(ModuleContext):
|
|
|
447
448
|
No other protocol commands will execute while waiting for the temperature.
|
|
448
449
|
|
|
449
450
|
:param celsius: A value between 4 and 95, representing the target temperature in °C.
|
|
451
|
+
|
|
450
452
|
"""
|
|
451
453
|
self._core.set_target_temperature(celsius)
|
|
452
454
|
self._core.wait_for_target_temperature()
|
|
453
455
|
|
|
454
456
|
@publish(command=cmds.tempdeck_set_temp)
|
|
455
457
|
@requires_version(2, 3)
|
|
456
|
-
def start_set_temperature(self, celsius: float) ->
|
|
458
|
+
def start_set_temperature(self, celsius: float) -> Task:
|
|
457
459
|
"""Set the target temperature without waiting for the target to be hit.
|
|
458
460
|
|
|
461
|
+
.. versionchanged:: 2.27
|
|
462
|
+
Returns a task object that represents concurrent preheating.
|
|
463
|
+
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the preheat to complete.
|
|
464
|
+
|
|
465
|
+
On version 2.26 or below, this function returns ``None``.
|
|
459
466
|
:param celsius: A value between 4 and 95, representing the target temperature in °C.
|
|
460
467
|
"""
|
|
461
|
-
self._core.set_target_temperature(celsius)
|
|
468
|
+
task = self._core.set_target_temperature(celsius)
|
|
469
|
+
if self._api_version >= APIVersion(2, 27):
|
|
470
|
+
return Task(api_version=self._api_version, core=task)
|
|
471
|
+
else:
|
|
472
|
+
return cast(Task, None)
|
|
462
473
|
|
|
463
474
|
@publish(command=cmds.tempdeck_await_temp)
|
|
464
475
|
@requires_version(2, 3)
|
|
@@ -672,6 +683,10 @@ class ThermocyclerContext(ModuleContext):
|
|
|
672
683
|
:param block_max_volume: The greatest volume of liquid contained in any
|
|
673
684
|
individual well of the loaded labware, in µL.
|
|
674
685
|
If not specified, the default is 25 µL.
|
|
686
|
+
After API version 2.27 it will attempt to use
|
|
687
|
+
the liquid tracking of the labware first and
|
|
688
|
+
then fall back to the 25 if there is no probed
|
|
689
|
+
or loaded liquid.
|
|
675
690
|
|
|
676
691
|
.. note::
|
|
677
692
|
|
|
@@ -682,18 +697,59 @@ class ThermocyclerContext(ModuleContext):
|
|
|
682
697
|
seconds = validation.ensure_hold_time_seconds(
|
|
683
698
|
seconds=hold_time_seconds, minutes=hold_time_minutes
|
|
684
699
|
)
|
|
700
|
+
if self._api_version >= APIVersion(2, 27) and block_max_volume is None:
|
|
701
|
+
block_max_volume = self._get_current_labware_max_vol()
|
|
685
702
|
self._core.set_target_block_temperature(
|
|
686
703
|
celsius=temperature,
|
|
687
704
|
hold_time_seconds=seconds,
|
|
688
705
|
block_max_volume=block_max_volume,
|
|
706
|
+
ramp_rate=ramp_rate,
|
|
689
707
|
)
|
|
690
708
|
self._core.wait_for_block_temperature()
|
|
691
709
|
|
|
710
|
+
@publish(command=cmds.thermocycler_start_set_block_temp)
|
|
711
|
+
@requires_version(2, 27)
|
|
712
|
+
def start_set_block_temperature(
|
|
713
|
+
self,
|
|
714
|
+
temperature: float,
|
|
715
|
+
ramp_rate: Optional[float] = None,
|
|
716
|
+
block_max_volume: Optional[float] = None,
|
|
717
|
+
) -> Task:
|
|
718
|
+
"""Starts to set the target temperature for the well block, in °C.
|
|
719
|
+
|
|
720
|
+
Returns a task object that represents concurrent preheating.
|
|
721
|
+
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for
|
|
722
|
+
the preheat to complete.
|
|
723
|
+
|
|
724
|
+
:param temperature: A value between 4 and 99, representing the target
|
|
725
|
+
temperature in °C.
|
|
726
|
+
:param block_max_volume: The greatest volume of liquid contained in any
|
|
727
|
+
individual well of the loaded labware, in µL.
|
|
728
|
+
If not specified, the default is 25 µL.
|
|
729
|
+
After API version 2.27 it will attempt to use
|
|
730
|
+
the liquid tracking of the labware first and
|
|
731
|
+
then fall back to the 25 if there is no probed
|
|
732
|
+
or loaded liquid.
|
|
733
|
+
"""
|
|
734
|
+
|
|
735
|
+
if block_max_volume is None:
|
|
736
|
+
block_max_volume = self._get_current_labware_max_vol()
|
|
737
|
+
task = self._core.start_set_target_block_temperature(
|
|
738
|
+
celsius=temperature,
|
|
739
|
+
block_max_volume=block_max_volume,
|
|
740
|
+
ramp_rate=ramp_rate,
|
|
741
|
+
)
|
|
742
|
+
return Task(api_version=self._api_version, core=task)
|
|
743
|
+
|
|
692
744
|
@publish(command=cmds.thermocycler_set_lid_temperature)
|
|
693
745
|
@requires_version(2, 0)
|
|
694
746
|
def set_lid_temperature(self, temperature: float) -> None:
|
|
695
747
|
"""Set the target temperature for the heated lid, in °C.
|
|
696
748
|
|
|
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
|
+
|
|
697
753
|
:param temperature: A value between 37 and 110, representing the target
|
|
698
754
|
temperature in °C.
|
|
699
755
|
|
|
@@ -706,6 +762,27 @@ class ThermocyclerContext(ModuleContext):
|
|
|
706
762
|
self._core.set_target_lid_temperature(celsius=temperature)
|
|
707
763
|
self._core.wait_for_lid_temperature()
|
|
708
764
|
|
|
765
|
+
@publish(command=cmds.thermocycler_start_set_lid_temperature)
|
|
766
|
+
@requires_version(2, 27)
|
|
767
|
+
def start_set_lid_temperature(self, temperature: float) -> Task:
|
|
768
|
+
"""Set the target temperature for the heated lid, in °C.
|
|
769
|
+
|
|
770
|
+
Returns a task object that represents concurrent preheating.
|
|
771
|
+
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for
|
|
772
|
+
the preheat to complete.
|
|
773
|
+
|
|
774
|
+
:param temperature: A value between 37 and 110, representing the target
|
|
775
|
+
temperature in °C.
|
|
776
|
+
|
|
777
|
+
.. note::
|
|
778
|
+
|
|
779
|
+
The Thermocycler will proceed to the next command immediately after
|
|
780
|
+
``temperature`` is reached.
|
|
781
|
+
|
|
782
|
+
"""
|
|
783
|
+
task = self._core.start_set_target_lid_temperature(celsius=temperature)
|
|
784
|
+
return Task(api_version=self._api_version, core=task)
|
|
785
|
+
|
|
709
786
|
@publish(command=cmds.thermocycler_execute_profile)
|
|
710
787
|
@requires_version(2, 0)
|
|
711
788
|
def execute_profile(
|
|
@@ -739,6 +816,39 @@ class ThermocyclerContext(ModuleContext):
|
|
|
739
816
|
block_max_volume=block_max_volume,
|
|
740
817
|
)
|
|
741
818
|
|
|
819
|
+
@publish(command=cmds.thermocycler_start_execute_profile)
|
|
820
|
+
@requires_version(2, 27)
|
|
821
|
+
def start_execute_profile(
|
|
822
|
+
self,
|
|
823
|
+
steps: List[ThermocyclerStep],
|
|
824
|
+
repetitions: int,
|
|
825
|
+
block_max_volume: Optional[float] = None,
|
|
826
|
+
) -> Task:
|
|
827
|
+
"""Start a Thermocycler profile and return a :py:class:`Task` representing its execution.
|
|
828
|
+
Profile is defined as a cycle of ``steps``, for a given number of ``repetitions``.
|
|
829
|
+
|
|
830
|
+
Returns a task object that represents concurrent execution of the profile.
|
|
831
|
+
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the preheat to complete.
|
|
832
|
+
|
|
833
|
+
:param steps: List of steps that make up a single cycle.
|
|
834
|
+
Each list item should be a dictionary that maps to the parameters
|
|
835
|
+
of the :py:meth:`set_block_temperature` method. The dictionary's
|
|
836
|
+
keys must be ``temperature`` and one or both of
|
|
837
|
+
``hold_time_seconds`` and ``hold_time_minutes``.
|
|
838
|
+
:param repetitions: The number of times to repeat the cycled steps.
|
|
839
|
+
:param block_max_volume: The greatest volume of liquid contained in any
|
|
840
|
+
individual well of the loaded labware, in µL.
|
|
841
|
+
If not specified, the default is 25 µL.
|
|
842
|
+
"""
|
|
843
|
+
repetitions = validation.ensure_thermocycler_repetition_count(repetitions)
|
|
844
|
+
validated_steps = validation.ensure_thermocycler_profile_steps(steps)
|
|
845
|
+
task = self._core.start_execute_profile(
|
|
846
|
+
steps=validated_steps,
|
|
847
|
+
repetitions=repetitions,
|
|
848
|
+
block_max_volume=block_max_volume,
|
|
849
|
+
)
|
|
850
|
+
return Task(api_version=self._api_version, core=task)
|
|
851
|
+
|
|
742
852
|
@publish(command=cmds.thermocycler_deactivate_lid)
|
|
743
853
|
@requires_version(2, 0)
|
|
744
854
|
def deactivate_lid(self) -> None:
|
|
@@ -860,6 +970,23 @@ class ThermocyclerContext(ModuleContext):
|
|
|
860
970
|
"""Index of the current step within the current cycle"""
|
|
861
971
|
return self._core.get_current_step_index()
|
|
862
972
|
|
|
973
|
+
def _get_current_labware_max_vol(self) -> Optional[float]:
|
|
974
|
+
max_vol: Optional[float] = None
|
|
975
|
+
if self.labware is not None:
|
|
976
|
+
for well in self.labware.wells():
|
|
977
|
+
if well.has_tracked_liquid():
|
|
978
|
+
# make sure that max vol is a float first if we have liquid
|
|
979
|
+
max_vol = 0.0 if max_vol is None else max_vol
|
|
980
|
+
well_vol = well.current_liquid_volume()
|
|
981
|
+
# ignore simulated probe results
|
|
982
|
+
if isinstance(well_vol, float):
|
|
983
|
+
max_vol = max(max_vol, well_vol)
|
|
984
|
+
if max_vol > BLOCK_VOL_MAX:
|
|
985
|
+
max_vol = BLOCK_VOL_MAX
|
|
986
|
+
elif max_vol < BLOCK_VOL_MIN:
|
|
987
|
+
max_vol = BLOCK_VOL_MIN
|
|
988
|
+
return max_vol
|
|
989
|
+
|
|
863
990
|
|
|
864
991
|
class HeaterShakerContext(ModuleContext):
|
|
865
992
|
"""An object representing a connected Heater-Shaker Module.
|
|
@@ -973,18 +1100,21 @@ class HeaterShakerContext(ModuleContext):
|
|
|
973
1100
|
|
|
974
1101
|
@requires_version(2, 13)
|
|
975
1102
|
@publish(command=cmds.heater_shaker_set_target_temperature)
|
|
976
|
-
def set_target_temperature(self, celsius: float) ->
|
|
1103
|
+
def set_target_temperature(self, celsius: float) -> Task:
|
|
977
1104
|
"""Set target temperature and return immediately.
|
|
978
1105
|
|
|
979
1106
|
Sets the Heater-Shaker's target temperature and returns immediately without
|
|
980
1107
|
waiting for the target to be reached. Does not delay the protocol until
|
|
981
1108
|
target temperature has reached.
|
|
982
1109
|
Use :py:meth:`~.HeaterShakerContext.wait_for_temperature` to delay
|
|
983
|
-
protocol execution.
|
|
1110
|
+
protocol execution for api levels below 2.27.
|
|
984
1111
|
|
|
985
1112
|
.. versionchanged:: 2.25
|
|
986
1113
|
Removed the minimum temperature limit of 37 °C. Note that temperatures under ambient are
|
|
987
1114
|
not achievable.
|
|
1115
|
+
.. versionchanged:: 2.27
|
|
1116
|
+
Returns a task object that represents concurrent preheating.
|
|
1117
|
+
Pass the task object to :py:meth:`ProtocolContext.wait_for_tasks` to wait for the preheat to complete.
|
|
988
1118
|
|
|
989
1119
|
:param celsius: A value under 95, representing the target temperature in °C.
|
|
990
1120
|
Values are automatically truncated to two decimal places,
|
|
@@ -993,7 +1123,11 @@ class HeaterShakerContext(ModuleContext):
|
|
|
993
1123
|
validated_temp = validate_heater_shaker_temperature(
|
|
994
1124
|
celsius=celsius, api_version=self.api_version
|
|
995
1125
|
)
|
|
996
|
-
self._core.set_target_temperature(celsius=validated_temp)
|
|
1126
|
+
task = self._core.set_target_temperature(celsius=validated_temp)
|
|
1127
|
+
if self._api_version >= APIVersion(2, 27):
|
|
1128
|
+
return Task(api_version=self._api_version, core=task)
|
|
1129
|
+
else:
|
|
1130
|
+
return cast(Task, None)
|
|
997
1131
|
|
|
998
1132
|
@requires_version(2, 13)
|
|
999
1133
|
@publish(command=cmds.heater_shaker_wait_for_temperature)
|
|
@@ -1021,6 +1155,21 @@ class HeaterShakerContext(ModuleContext):
|
|
|
1021
1155
|
validated_speed = validate_heater_shaker_speed(rpm=rpm)
|
|
1022
1156
|
self._core.set_and_wait_for_shake_speed(rpm=validated_speed)
|
|
1023
1157
|
|
|
1158
|
+
@requires_version(2, 27)
|
|
1159
|
+
@publish(command=cmds.heater_shaker_set_shake_speed)
|
|
1160
|
+
def set_shake_speed(self, rpm: int) -> Task:
|
|
1161
|
+
"""Set a shake speed in rpm to run in the background.
|
|
1162
|
+
|
|
1163
|
+
.. note::
|
|
1164
|
+
|
|
1165
|
+
Before shaking, this command will retract the pipettes upward if they are parked adjacent to the Heater-Shaker.
|
|
1166
|
+
|
|
1167
|
+
:param rpm: A value between 200 and 3000, representing the target shake speed in revolutions per minute.
|
|
1168
|
+
"""
|
|
1169
|
+
validated_speed = validate_heater_shaker_speed(rpm=rpm)
|
|
1170
|
+
task = self._core.set_shake_speed(rpm=validated_speed)
|
|
1171
|
+
return Task(api_version=self._api_version, core=task)
|
|
1172
|
+
|
|
1024
1173
|
@requires_version(2, 13)
|
|
1025
1174
|
@publish(command=cmds.heater_shaker_open_labware_latch)
|
|
1026
1175
|
def open_labware_latch(self) -> None:
|
|
@@ -1431,9 +1580,15 @@ class FlexStackerContext(ModuleContext):
|
|
|
1431
1580
|
:param adapter_namespace: Applies to ``adapter`` the same way that ``namespace``
|
|
1432
1581
|
applies to ``load_name``.
|
|
1433
1582
|
|
|
1583
|
+
.. versionchanged:: 2.26
|
|
1584
|
+
``adapter_namespace`` may now be specified explicitly. When you've specified ``namespace`` for ``load_name`` but not ``adapter_namespace``, ``adapter_namespace`` now independently follows the same search rules described in ``namespace``. Formerly, it took the exact ``namespace`` value.
|
|
1585
|
+
|
|
1434
1586
|
:param adapter_version: Applies to ``adapter`` the same way that ``version``
|
|
1435
1587
|
applies to ``load_name``.
|
|
1436
1588
|
|
|
1589
|
+
.. versionchanged:: 2.26
|
|
1590
|
+
``adapter_version`` may now be specified explictly. When unspecified, improved search rules prevent selecting a version that does not exist.
|
|
1591
|
+
|
|
1437
1592
|
:param lid: A lid to load the on top of the main labware. Accepts the same
|
|
1438
1593
|
values as the ``load_name`` parameter of :py:meth:`~.ProtocolContext.load_lid_stack`. The
|
|
1439
1594
|
lid will use the same namespace as the labware, and the API will
|
|
@@ -1442,9 +1597,18 @@ class FlexStackerContext(ModuleContext):
|
|
|
1442
1597
|
:param lid_namespace: Applies to ``lid`` the same way that ``namespace``
|
|
1443
1598
|
applies to ``load_name``.
|
|
1444
1599
|
|
|
1600
|
+
.. versionchanged:: 2.26
|
|
1601
|
+
``lid_namespace`` may now be specified explicitly.
|
|
1602
|
+
When you've specified ``namespace`` for ``load_name`` but not ``lid_namespace``,
|
|
1603
|
+
``lid_namespace`` now independently follows the same search rules
|
|
1604
|
+
described in ``namespace``. Formerly, it took the exact ``namespace`` value.
|
|
1605
|
+
|
|
1445
1606
|
:param lid_version: Applies to ``lid`` the same way that ``version``
|
|
1446
1607
|
applies to ``load_name``.
|
|
1447
1608
|
|
|
1609
|
+
.. versionchanged:: 2.26
|
|
1610
|
+
``lid_version`` may now be specified explicitly. When unspecified, improved search rules prevent selecting a version that does not exist.
|
|
1611
|
+
|
|
1448
1612
|
:param count: The number of labware that the Flex Stacker should store. If not specified, this will be the maximum amount of this kind of
|
|
1449
1613
|
labware that the Flex Stacker is capable of storing.
|
|
1450
1614
|
|
|
@@ -11,6 +11,7 @@ from typing import (
|
|
|
11
11
|
Union,
|
|
12
12
|
Mapping,
|
|
13
13
|
cast,
|
|
14
|
+
Tuple,
|
|
14
15
|
)
|
|
15
16
|
|
|
16
17
|
from opentrons_shared_data.labware.types import LabwareDefinition
|
|
@@ -89,6 +90,7 @@ from .module_contexts import (
|
|
|
89
90
|
FlexStackerContext,
|
|
90
91
|
ModuleContext,
|
|
91
92
|
)
|
|
93
|
+
from .tasks import Task
|
|
92
94
|
from ._parameters import Parameters
|
|
93
95
|
|
|
94
96
|
|
|
@@ -234,10 +236,7 @@ class ProtocolContext(CommandPublisher):
|
|
|
234
236
|
@property
|
|
235
237
|
@requires_version(2, 22)
|
|
236
238
|
def robot(self) -> RobotContext:
|
|
237
|
-
"""The :py:class:`.RobotContext` for the protocol.
|
|
238
|
-
|
|
239
|
-
:meta private:
|
|
240
|
-
"""
|
|
239
|
+
"""The :py:class:`.RobotContext` for the protocol."""
|
|
241
240
|
if self._core.robot_type != "OT-3 Standard" or not self._robot:
|
|
242
241
|
raise RobotTypeError("The RobotContext is only available on Flex robots.")
|
|
243
242
|
return self._robot
|
|
@@ -470,17 +469,15 @@ class ProtocolContext(CommandPublisher):
|
|
|
470
469
|
|
|
471
470
|
.. versionchanged:: 2.26
|
|
472
471
|
``adapter_namespace`` may now be specified explicitly.
|
|
473
|
-
|
|
474
|
-
``adapter_namespace``
|
|
475
|
-
described in ``namespace``. Formerly, it took ``namespace``
|
|
472
|
+
When you've specified ``namespace`` for ``load_name`` but not ``adapter_namespace``,
|
|
473
|
+
``adapter_namespace`` now independently follows the same search rules
|
|
474
|
+
described in ``namespace``. Formerly, it took the exact ``namespace`` value.
|
|
476
475
|
|
|
477
476
|
:param adapter_version: The version of the adapter being loaded.
|
|
478
477
|
Applies to ``adapter`` the same way that ``version`` applies to ``load_name``.
|
|
479
478
|
|
|
480
479
|
.. versionchanged:: 2.26
|
|
481
|
-
``adapter_version`` may now be specified explicitly.
|
|
482
|
-
the algorithm to select a version automatically has improved to avoid
|
|
483
|
-
selecting versions that do not exist.
|
|
480
|
+
``adapter_version`` may now be specified explicitly. When unspecified, the API uses the newest version available for your protocol's API level.
|
|
484
481
|
|
|
485
482
|
:param lid: A lid to load on the top of the main labware. Accepts the same
|
|
486
483
|
values as the ``load_name`` parameter of :py:meth:`.load_lid_stack`. The
|
|
@@ -494,17 +491,15 @@ class ProtocolContext(CommandPublisher):
|
|
|
494
491
|
|
|
495
492
|
.. versionchanged:: 2.26
|
|
496
493
|
``lid_namespace`` may now be specified explicitly.
|
|
497
|
-
|
|
498
|
-
``lid_namespace``
|
|
499
|
-
described in ``namespace``. Formerly, it took ``namespace``
|
|
494
|
+
When you've specified ``namespace`` for ``load_name`` but not ``lid_namespace``,
|
|
495
|
+
``lid_namespace`` now independently follows the same search rules
|
|
496
|
+
described in ``namespace``. Formerly, it took the exact ``namespace`` value.
|
|
500
497
|
|
|
501
498
|
:param lid_version: The version of the adapter being loaded.
|
|
502
499
|
Applies to ``lid`` the same way that ``version`` applies to ``load_name``.
|
|
503
500
|
|
|
504
501
|
.. versionchanged:: 2.26
|
|
505
|
-
``lid_version`` may now be specified explicitly.
|
|
506
|
-
the algorithm to select a version automatically has improved to avoid
|
|
507
|
-
selecting versions that do not exist.
|
|
502
|
+
``lid_version`` may now be specified explicitly. When unspecified, the API uses the newest version available for your protocol's API level.
|
|
508
503
|
"""
|
|
509
504
|
|
|
510
505
|
if isinstance(location, OffDeckType) and self._api_version < APIVersion(2, 15):
|
|
@@ -1289,6 +1284,30 @@ class ProtocolContext(CommandPublisher):
|
|
|
1289
1284
|
delay_time = seconds + minutes * 60
|
|
1290
1285
|
self._core.delay(seconds=delay_time, msg=msg)
|
|
1291
1286
|
|
|
1287
|
+
@publish(command=cmds.wait_for_tasks)
|
|
1288
|
+
@requires_version(2, 27)
|
|
1289
|
+
def wait_for_tasks(self, tasks: list[Task]) -> None:
|
|
1290
|
+
"""Wait for a list of tasks to complete before executing subsequent commands.
|
|
1291
|
+
|
|
1292
|
+
:param list Task: tasks: A list of Task objects to wait for.
|
|
1293
|
+
|
|
1294
|
+
Task objects can be commands that are allowed to run concurrently.
|
|
1295
|
+
"""
|
|
1296
|
+
task_cores = [task._core for task in tasks]
|
|
1297
|
+
self._core.wait_for_tasks(task_cores)
|
|
1298
|
+
|
|
1299
|
+
@publish(command=cmds.create_timer)
|
|
1300
|
+
@requires_version(2, 27)
|
|
1301
|
+
def create_timer(self, seconds: float) -> Task:
|
|
1302
|
+
"""Create a timer task that runs in the background.
|
|
1303
|
+
|
|
1304
|
+
:param float seconds: The time to delay in seconds.
|
|
1305
|
+
|
|
1306
|
+
This timer will continue to run until it is complete and will not block subsequent commands.
|
|
1307
|
+
"""
|
|
1308
|
+
task_core = self._core.create_timer(seconds=seconds)
|
|
1309
|
+
return Task(core=task_core, api_version=self._api_version)
|
|
1310
|
+
|
|
1292
1311
|
@requires_version(2, 0)
|
|
1293
1312
|
def home(self) -> None:
|
|
1294
1313
|
"""Home the movement system of the robot."""
|
|
@@ -1483,8 +1502,8 @@ class ProtocolContext(CommandPublisher):
|
|
|
1483
1502
|
- ``"water"``: an Opentrons-verified liquid class based on deionized water.
|
|
1484
1503
|
- ``"glycerol_50"``: an Opentrons-verified liquid class for viscous liquid. Based on 50% glycerol.
|
|
1485
1504
|
- ``"ethanol_80"``: an Opentrons-verified liquid class for volatile liquid. Based on 80% ethanol.
|
|
1486
|
-
:param version:
|
|
1487
|
-
protocol's API
|
|
1505
|
+
:param version: Version of the liquid class to retrieve. If left unspecified, defaults to the latest version for the
|
|
1506
|
+
protocol's API level.
|
|
1488
1507
|
|
|
1489
1508
|
:raises: ``LiquidClassDefinitionDoesNotExist``: if the specified liquid class does not exist.
|
|
1490
1509
|
|
|
@@ -1601,9 +1620,9 @@ class ProtocolContext(CommandPublisher):
|
|
|
1601
1620
|
|
|
1602
1621
|
.. versionchanged:: 2.26
|
|
1603
1622
|
``adapter_namespace`` may now be specified explicitly.
|
|
1604
|
-
|
|
1605
|
-
``adapter_namespace``
|
|
1606
|
-
described in ``namespace``. Formerly, it took ``namespace``
|
|
1623
|
+
When you've specified ``namespace`` for ``load_name`` but not ``adapter_namespace``,
|
|
1624
|
+
``adapter_namespace`` now independently follows the same search rules
|
|
1625
|
+
described in ``namespace``. Formerly, it took the exact ``namespace`` value.
|
|
1607
1626
|
|
|
1608
1627
|
:param adapter_version: The version of the adapter being loaded.
|
|
1609
1628
|
Applies to ``adapter`` the same way that ``version`` applies to ``load_name``.
|
|
@@ -1803,6 +1822,53 @@ class ProtocolContext(CommandPublisher):
|
|
|
1803
1822
|
)
|
|
1804
1823
|
return None
|
|
1805
1824
|
|
|
1825
|
+
@requires_version(2, 27)
|
|
1826
|
+
def capture_image(
|
|
1827
|
+
self,
|
|
1828
|
+
home_before: Optional[bool] = False,
|
|
1829
|
+
filename: Optional[str] = None,
|
|
1830
|
+
resolution: Optional[Tuple[int, int]] = None,
|
|
1831
|
+
zoom: Optional[float] = None,
|
|
1832
|
+
contrast: Optional[float] = None,
|
|
1833
|
+
brightness: Optional[float] = None,
|
|
1834
|
+
saturation: Optional[float] = None,
|
|
1835
|
+
) -> None:
|
|
1836
|
+
"""Capture an image using the camera. Captured images get saved as a result of the protocol run.
|
|
1837
|
+
|
|
1838
|
+
:param home_before: Boolean to home the pipette before capturing an image.
|
|
1839
|
+
:param filename: Filename to use when saving the captured image as a file.
|
|
1840
|
+
:param resolution: Width/height tuple to determine the resolution to use when capturing an image.
|
|
1841
|
+
:param zoom: Optional zoom level, with minimum/default of 1x zoom and maximum of 2x zoom.
|
|
1842
|
+
:param contrast: Contrast level to be applied to an image, range is 0% to 100%.
|
|
1843
|
+
:param brightness: Brightness level to be applied to an image, range is 0% to 100%.
|
|
1844
|
+
:param saturation: Saturation level to be applied to an image, range is 0% to 100%.
|
|
1845
|
+
|
|
1846
|
+
.. versionadded:: 2.27
|
|
1847
|
+
|
|
1848
|
+
"""
|
|
1849
|
+
if home_before is True:
|
|
1850
|
+
self._core.home()
|
|
1851
|
+
|
|
1852
|
+
with publish_context(
|
|
1853
|
+
broker=self.broker,
|
|
1854
|
+
command=cmds.capture_image(
|
|
1855
|
+
resolution=resolution,
|
|
1856
|
+
zoom=zoom,
|
|
1857
|
+
contrast=contrast,
|
|
1858
|
+
brightness=brightness,
|
|
1859
|
+
saturation=saturation,
|
|
1860
|
+
),
|
|
1861
|
+
):
|
|
1862
|
+
self._core.capture_image(
|
|
1863
|
+
filename=filename,
|
|
1864
|
+
resolution=resolution,
|
|
1865
|
+
zoom=zoom,
|
|
1866
|
+
contrast=contrast,
|
|
1867
|
+
brightness=brightness,
|
|
1868
|
+
saturation=saturation,
|
|
1869
|
+
)
|
|
1870
|
+
return None
|
|
1871
|
+
|
|
1806
1872
|
|
|
1807
1873
|
def _create_module_context(
|
|
1808
1874
|
module_core: Union[ModuleCore, NonConnectedModuleCore],
|
|
@@ -15,7 +15,6 @@ from opentrons.legacy_commands import publisher
|
|
|
15
15
|
from opentrons.hardware_control import SyncHardwareAPI
|
|
16
16
|
from opentrons.protocols.api_support.util import requires_version
|
|
17
17
|
from opentrons.protocols.api_support.types import APIVersion
|
|
18
|
-
from opentrons_shared_data.pipette.types import PipetteNameType
|
|
19
18
|
|
|
20
19
|
from . import validation
|
|
21
20
|
from .core.common import ProtocolCore, RobotCore
|
|
@@ -46,7 +45,7 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
46
45
|
Objects in this class should not be instantiated directly. Instead, instances are
|
|
47
46
|
returned by :py:meth:`ProtocolContext.robot`.
|
|
48
47
|
|
|
49
|
-
.. versionadded:: 2.
|
|
48
|
+
.. versionadded:: 2.22
|
|
50
49
|
|
|
51
50
|
"""
|
|
52
51
|
|
|
@@ -83,15 +82,19 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
83
82
|
speed: Optional[float] = None,
|
|
84
83
|
) -> None:
|
|
85
84
|
"""
|
|
86
|
-
Move a specified mount to a
|
|
85
|
+
Move a specified mount to a location on the deck.
|
|
87
86
|
|
|
88
87
|
:param mount: The mount of the instrument you wish to move.
|
|
89
88
|
This can either be an instance of :py:class:`.types.Mount` or one
|
|
90
89
|
of the strings ``"left"``, ``"right"``, ``"extension"``, ``"gripper"``. Note
|
|
91
90
|
that the gripper mount can be referred to either as ``"extension"`` or ``"gripper"``.
|
|
92
91
|
:type mount: types.Mount or str
|
|
93
|
-
:param
|
|
94
|
-
|
|
92
|
+
:param destination: Any location on the deck, specified as:
|
|
93
|
+
|
|
94
|
+
- a slot, like ``"A1"``
|
|
95
|
+
- a defined location, like labware in a deck slot
|
|
96
|
+
- an absolute location, like a point {x=10 , y=10, z=10} or a deck location and point ("A1" + point {x=10 , y=10, z=10})
|
|
97
|
+
:param speed: The absolute speed in mm/s.
|
|
95
98
|
"""
|
|
96
99
|
mount = validation.ensure_instrument_mount(mount)
|
|
97
100
|
with publisher.publish_context(
|
|
@@ -116,13 +119,12 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
116
119
|
Move a set of axes to an absolute position on the deck.
|
|
117
120
|
|
|
118
121
|
:param axis_map: A dictionary mapping axes to an absolute position on the deck in mm.
|
|
119
|
-
:param critical_point: The critical point to move the axes with. It should only
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
in the axis map.
|
|
122
|
+
:param critical_point: The critical point, or specific point on the object being moved, to move the axes with. It should only specify the gantry axes (i.e. `x`, `y`, `z`). When you specify a critical point, you're specifying the object on the gantry to be moved. If not specified, the critical point defaults to the center of the carriage attached to the gantry.
|
|
123
|
+
:param float speed: The maximum speed with which to move all axes in mm/s.
|
|
124
|
+
|
|
123
125
|
"""
|
|
124
126
|
instrument_on_left = self._core.get_pipette_type_from_engine(Mount.LEFT)
|
|
125
|
-
is_96_channel = instrument_on_left
|
|
127
|
+
is_96_channel = validation.is_pipette_96_channel(instrument_on_left)
|
|
126
128
|
axis_map = validation.ensure_axis_map_type(
|
|
127
129
|
axis_map, self._protocol_core.robot_type, is_96_channel
|
|
128
130
|
)
|
|
@@ -154,14 +156,12 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
154
156
|
"""
|
|
155
157
|
Move a set of axes to a relative position on the deck.
|
|
156
158
|
|
|
157
|
-
:param axis_map: A dictionary mapping axes to relative movements in mm.
|
|
158
|
-
:type mount: types.Mount or str
|
|
159
|
+
:param axis_map: A dictionary mapping axes to relative movements from the current position in mm.
|
|
159
160
|
|
|
160
|
-
:param float speed: The maximum speed with which
|
|
161
|
-
in the axis map.
|
|
161
|
+
:param float speed: The maximum speed with which to move all axes in mm/s.
|
|
162
162
|
"""
|
|
163
163
|
instrument_on_left = self._core.get_pipette_type_from_engine(Mount.LEFT)
|
|
164
|
-
is_96_channel = instrument_on_left
|
|
164
|
+
is_96_channel = validation.is_pipette_96_channel(instrument_on_left)
|
|
165
165
|
|
|
166
166
|
axis_map = validation.ensure_axis_map_type(
|
|
167
167
|
axis_map, self._protocol_core.robot_type, is_96_channel
|
|
@@ -177,7 +177,10 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
177
177
|
self._core.move_axes_relative(axis_map, speed)
|
|
178
178
|
|
|
179
179
|
def close_gripper_jaw(self, force: Optional[float] = None) -> None:
|
|
180
|
-
"""
|
|
180
|
+
"""Closes the Flex Gripper jaws with a specified force.
|
|
181
|
+
|
|
182
|
+
:param force: Force with which to close the gripper jaws in newtons.
|
|
183
|
+
"""
|
|
181
184
|
with publisher.publish_context(
|
|
182
185
|
broker=self.broker,
|
|
183
186
|
command=cmds.close_gripper(
|
|
@@ -187,7 +190,10 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
187
190
|
self._core.close_gripper(force)
|
|
188
191
|
|
|
189
192
|
def open_gripper_jaw(self) -> None:
|
|
190
|
-
"""
|
|
193
|
+
"""Opens the Flex Gripper jaws with a specified force.
|
|
194
|
+
|
|
195
|
+
:param force: Force with which to open the gripper jaws in newtons.
|
|
196
|
+
"""
|
|
191
197
|
with publisher.publish_context(
|
|
192
198
|
broker=self.broker,
|
|
193
199
|
command=cmds.open_gripper(),
|
|
@@ -200,9 +206,9 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
200
206
|
location: Union[Location, ModuleContext, DeckLocation],
|
|
201
207
|
) -> AxisMapType:
|
|
202
208
|
"""
|
|
203
|
-
Build
|
|
209
|
+
Build an axis map from a location to provide to
|
|
204
210
|
either :py:meth:`.RobotContext.move_axes_to` or :py:meth:`.RobotContext.move_axes_relative`.
|
|
205
|
-
You must provide only one of `location`, `slot`, or `module` to build
|
|
211
|
+
You must provide only one of either a `location`, `slot`, or `module` to build
|
|
206
212
|
the axis map.
|
|
207
213
|
|
|
208
214
|
:param mount: The mount of the instrument you wish create an axis map for.
|
|
@@ -210,7 +216,10 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
210
216
|
of the strings ``"left"``, ``"right"``, ``"extension"``, ``"gripper"``. Note
|
|
211
217
|
that the gripper mount can be referred to either as ``"extension"`` or ``"gripper"``.
|
|
212
218
|
:type mount: types.Mount or str
|
|
213
|
-
:param location:
|
|
219
|
+
:param location: Any location on the deck, specified as:
|
|
220
|
+
|
|
221
|
+
- a deck location, like slot ``"A1"``.
|
|
222
|
+
- a defined location, like a module on the deck.
|
|
214
223
|
:type location: `Well`, `ModuleContext`, `DeckLocation` or `OffDeckType`
|
|
215
224
|
"""
|
|
216
225
|
mount = validation.ensure_instrument_mount(mount)
|
|
@@ -248,7 +257,11 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
248
257
|
self, mount: Union[Mount, str], volume: float, action: PipetteActionTypes
|
|
249
258
|
) -> AxisMapType:
|
|
250
259
|
"""
|
|
251
|
-
Build
|
|
260
|
+
Build an axis map to move a pipette plunger motor to complete liquid handling actions.
|
|
261
|
+
|
|
262
|
+
:mount: The left or right instrument mount the pipette is attached to.
|
|
263
|
+
:param volume: A volume to convert to an axis map for linear plunger displacement.
|
|
264
|
+
:param action: Choose to ``aspirate`` or ``dispense``.
|
|
252
265
|
|
|
253
266
|
"""
|
|
254
267
|
pipette_name = self._core.get_pipette_type_from_engine(mount)
|
|
@@ -268,7 +281,9 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
268
281
|
self, mount: Union[Mount, str], position_name: PlungerPositionTypes
|
|
269
282
|
) -> AxisMapType:
|
|
270
283
|
"""
|
|
271
|
-
Build
|
|
284
|
+
Build an axis map to move a pipette plunger motor to a named position.
|
|
285
|
+
|
|
286
|
+
:param position_name: A named position to move the pipette plunger to. Choose from ``top``, ``bottom``, ``blowout``, or ``drop`` plunger positions.
|
|
272
287
|
|
|
273
288
|
"""
|
|
274
289
|
pipette_name = self._core.get_pipette_type_from_engine(mount)
|
|
@@ -284,8 +299,9 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
284
299
|
return {pipette_axis: pipette_position}
|
|
285
300
|
|
|
286
301
|
def build_axis_map(self, axis_map: StringAxisMap) -> AxisMapType:
|
|
287
|
-
"""Take in a :py:class:`.types.StringAxisMap` and output
|
|
288
|
-
|
|
302
|
+
"""Take in a :py:class:`.types.StringAxisMap` and output an axis map.
|
|
303
|
+
|
|
304
|
+
The :py:class:`.types.StringAxisMap` is allowed to contain any of the following strings:
|
|
289
305
|
``"x"``, ``"y"``, "``z_l"``, "``z_r"``, "``z_g"``, ``"q"``.
|
|
290
306
|
|
|
291
307
|
An example of a valid axis map could be:
|
|
@@ -296,7 +312,7 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
296
312
|
|
|
297
313
|
"""
|
|
298
314
|
instrument_on_left = self._core.get_pipette_type_from_engine(Mount.LEFT)
|
|
299
|
-
is_96_channel = instrument_on_left
|
|
315
|
+
is_96_channel = validation.is_pipette_96_channel(instrument_on_left)
|
|
300
316
|
|
|
301
317
|
return validation.ensure_axis_map_type(
|
|
302
318
|
axis_map, self._protocol_core.robot_type, is_96_channel
|