opentrons 8.1.0__py2.py3-none-any.whl → 8.2.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opentrons/cli/analyze.py +71 -7
- opentrons/config/__init__.py +9 -0
- opentrons/config/advanced_settings.py +22 -0
- opentrons/config/defaults_ot3.py +14 -36
- opentrons/config/feature_flags.py +4 -0
- opentrons/config/types.py +6 -17
- opentrons/drivers/absorbance_reader/abstract.py +27 -3
- opentrons/drivers/absorbance_reader/async_byonoy.py +208 -154
- opentrons/drivers/absorbance_reader/driver.py +24 -15
- opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
- opentrons/drivers/absorbance_reader/simulator.py +32 -6
- opentrons/drivers/types.py +23 -1
- opentrons/execute.py +2 -2
- opentrons/hardware_control/api.py +18 -10
- opentrons/hardware_control/backends/controller.py +3 -2
- opentrons/hardware_control/backends/flex_protocol.py +11 -5
- opentrons/hardware_control/backends/ot3controller.py +18 -50
- opentrons/hardware_control/backends/ot3simulator.py +7 -6
- opentrons/hardware_control/backends/ot3utils.py +1 -0
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
- opentrons/hardware_control/module_control.py +43 -2
- opentrons/hardware_control/modules/__init__.py +7 -1
- opentrons/hardware_control/modules/absorbance_reader.py +232 -83
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/heater_shaker.py +8 -3
- opentrons/hardware_control/modules/magdeck.py +12 -3
- opentrons/hardware_control/modules/mod_abc.py +27 -2
- opentrons/hardware_control/modules/tempdeck.py +15 -7
- opentrons/hardware_control/modules/thermocycler.py +69 -3
- opentrons/hardware_control/modules/types.py +11 -5
- opentrons/hardware_control/modules/update.py +11 -5
- opentrons/hardware_control/modules/utils.py +3 -1
- opentrons/hardware_control/ot3_calibration.py +6 -6
- opentrons/hardware_control/ot3api.py +131 -94
- opentrons/hardware_control/poller.py +15 -11
- opentrons/hardware_control/protocols/__init__.py +1 -7
- opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
- opentrons/hardware_control/protocols/liquid_handler.py +5 -0
- opentrons/hardware_control/protocols/position_estimator.py +3 -1
- opentrons/hardware_control/types.py +2 -0
- opentrons/legacy_commands/helpers.py +8 -2
- opentrons/motion_planning/__init__.py +2 -0
- opentrons/motion_planning/waypoints.py +32 -0
- opentrons/protocol_api/__init__.py +2 -1
- opentrons/protocol_api/_liquid.py +87 -1
- opentrons/protocol_api/_parameter_context.py +10 -1
- opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
- opentrons/protocol_api/core/engine/instrument.py +29 -25
- opentrons/protocol_api/core/engine/labware.py +20 -4
- opentrons/protocol_api/core/engine/module_core.py +166 -17
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +362 -0
- opentrons/protocol_api/core/engine/protocol.py +30 -2
- opentrons/protocol_api/core/instrument.py +2 -0
- opentrons/protocol_api/core/labware.py +4 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +5 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +6 -2
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/module.py +22 -4
- opentrons/protocol_api/core/protocol.py +6 -2
- opentrons/protocol_api/instrument_context.py +52 -20
- opentrons/protocol_api/labware.py +13 -1
- opentrons/protocol_api/module_contexts.py +115 -17
- opentrons/protocol_api/protocol_context.py +49 -5
- opentrons/protocol_api/validation.py +5 -3
- opentrons/protocol_engine/__init__.py +10 -9
- opentrons/protocol_engine/actions/__init__.py +3 -0
- opentrons/protocol_engine/actions/actions.py +30 -25
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/sync_client.py +1 -1
- opentrons/protocol_engine/clients/transports.py +1 -1
- opentrons/protocol_engine/commands/__init__.py +0 -4
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +148 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +65 -9
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +148 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +200 -0
- opentrons/protocol_engine/commands/aspirate.py +29 -16
- opentrons/protocol_engine/commands/aspirate_in_place.py +33 -16
- opentrons/protocol_engine/commands/blow_out.py +63 -14
- opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
- opentrons/protocol_engine/commands/command.py +31 -18
- opentrons/protocol_engine/commands/command_unions.py +37 -24
- opentrons/protocol_engine/commands/comment.py +5 -3
- opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
- opentrons/protocol_engine/commands/custom.py +5 -3
- opentrons/protocol_engine/commands/dispense.py +42 -20
- opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
- opentrons/protocol_engine/commands/drop_tip.py +70 -16
- opentrons/protocol_engine/commands/drop_tip_in_place.py +59 -13
- opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
- opentrons/protocol_engine/commands/home.py +11 -5
- opentrons/protocol_engine/commands/liquid_probe.py +146 -88
- opentrons/protocol_engine/commands/load_labware.py +28 -5
- opentrons/protocol_engine/commands/load_liquid.py +18 -7
- opentrons/protocol_engine/commands/load_module.py +4 -6
- opentrons/protocol_engine/commands/load_pipette.py +18 -17
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
- opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
- opentrons/protocol_engine/commands/move_labware.py +155 -23
- opentrons/protocol_engine/commands/move_relative.py +15 -3
- opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
- opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
- opentrons/protocol_engine/commands/move_to_well.py +37 -10
- opentrons/protocol_engine/commands/pick_up_tip.py +51 -30
- opentrons/protocol_engine/commands/pipetting_common.py +47 -16
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
- opentrons/protocol_engine/commands/reload_labware.py +13 -4
- opentrons/protocol_engine/commands/retract_axis.py +6 -3
- opentrons/protocol_engine/commands/save_position.py +2 -3
- opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
- opentrons/protocol_engine/commands/set_status_bar.py +5 -3
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
- opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
- opentrons/protocol_engine/commands/touch_tip.py +19 -7
- opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +10 -4
- opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
- opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
- opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
- opentrons/protocol_engine/create_protocol_engine.py +60 -10
- opentrons/protocol_engine/engine_support.py +2 -1
- opentrons/protocol_engine/error_recovery_policy.py +14 -3
- opentrons/protocol_engine/errors/__init__.py +20 -0
- opentrons/protocol_engine/errors/error_occurrence.py +8 -3
- opentrons/protocol_engine/errors/exceptions.py +127 -2
- opentrons/protocol_engine/execution/__init__.py +2 -0
- opentrons/protocol_engine/execution/command_executor.py +22 -13
- opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
- opentrons/protocol_engine/execution/door_watcher.py +1 -1
- opentrons/protocol_engine/execution/equipment.py +2 -1
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +4 -2
- opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
- opentrons/protocol_engine/execution/labware_movement.py +73 -22
- opentrons/protocol_engine/execution/movement.py +17 -7
- opentrons/protocol_engine/execution/pipetting.py +7 -4
- opentrons/protocol_engine/execution/queue_worker.py +6 -2
- opentrons/protocol_engine/execution/run_control.py +1 -1
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
- opentrons/protocol_engine/execution/tip_handler.py +77 -43
- opentrons/protocol_engine/notes/__init__.py +14 -2
- opentrons/protocol_engine/notes/notes.py +18 -1
- opentrons/protocol_engine/plugins.py +1 -1
- opentrons/protocol_engine/protocol_engine.py +47 -31
- opentrons/protocol_engine/resources/__init__.py +2 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +19 -5
- opentrons/protocol_engine/resources/file_provider.py +161 -0
- opentrons/protocol_engine/resources/fixture_validation.py +11 -1
- opentrons/protocol_engine/resources/labware_validation.py +10 -0
- opentrons/protocol_engine/state/__init__.py +0 -70
- opentrons/protocol_engine/state/addressable_areas.py +1 -1
- opentrons/protocol_engine/state/command_history.py +21 -2
- opentrons/protocol_engine/state/commands.py +110 -31
- opentrons/protocol_engine/state/files.py +59 -0
- opentrons/protocol_engine/state/frustum_helpers.py +440 -0
- opentrons/protocol_engine/state/geometry.py +445 -59
- opentrons/protocol_engine/state/labware.py +264 -84
- opentrons/protocol_engine/state/liquids.py +1 -1
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +21 -3
- opentrons/protocol_engine/state/modules.py +145 -90
- opentrons/protocol_engine/state/motion.py +33 -14
- opentrons/protocol_engine/state/pipettes.py +157 -317
- opentrons/protocol_engine/state/state.py +30 -1
- opentrons/protocol_engine/state/state_summary.py +3 -0
- opentrons/protocol_engine/state/tips.py +69 -114
- opentrons/protocol_engine/state/update_types.py +424 -0
- opentrons/protocol_engine/state/wells.py +236 -0
- opentrons/protocol_engine/types.py +90 -0
- opentrons/protocol_reader/file_format_validator.py +83 -15
- opentrons/protocol_runner/json_translator.py +21 -5
- opentrons/protocol_runner/legacy_command_mapper.py +27 -6
- opentrons/protocol_runner/legacy_context_plugin.py +27 -71
- opentrons/protocol_runner/protocol_runner.py +6 -3
- opentrons/protocol_runner/run_orchestrator.py +41 -6
- opentrons/protocols/advanced_control/mix.py +3 -5
- opentrons/protocols/advanced_control/transfers.py +125 -56
- opentrons/protocols/api_support/constants.py +1 -1
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/labware_like.py +4 -4
- opentrons/protocols/api_support/tip_tracker.py +2 -2
- opentrons/protocols/api_support/types.py +15 -2
- opentrons/protocols/api_support/util.py +30 -42
- opentrons/protocols/duration/errors.py +1 -1
- opentrons/protocols/duration/estimator.py +50 -29
- opentrons/protocols/execution/dev_types.py +2 -2
- opentrons/protocols/execution/execute_json_v4.py +15 -10
- opentrons/protocols/execution/execute_python.py +8 -3
- opentrons/protocols/geometry/planning.py +12 -12
- opentrons/protocols/labware.py +17 -33
- opentrons/protocols/parameters/csv_parameter_interface.py +3 -1
- opentrons/simulate.py +3 -3
- opentrons/types.py +30 -3
- opentrons/util/logging_config.py +34 -0
- {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/METADATA +5 -4
- {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/RECORD +235 -223
- opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
- opentrons/protocol_engine/commands/configuring_common.py +0 -26
- opentrons/protocol_runner/thread_async_queue.py +0 -174
- /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
- /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
- {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/LICENSE +0 -0
- {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/WHEEL +0 -0
- {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.1.0.dist-info → opentrons-8.2.0.dist-info}/top_level.txt +0 -0
|
@@ -2,9 +2,12 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Dict, Optional
|
|
6
6
|
|
|
7
|
-
from opentrons.hardware_control.modules.types import
|
|
7
|
+
from opentrons.hardware_control.modules.types import (
|
|
8
|
+
ModuleDisconnectedCallback,
|
|
9
|
+
TemperatureStatus,
|
|
10
|
+
)
|
|
8
11
|
from opentrons.hardware_control.poller import Reader, Poller
|
|
9
12
|
from typing_extensions import Final
|
|
10
13
|
from opentrons.drivers.types import Temperature
|
|
@@ -15,7 +18,7 @@ from opentrons.drivers.temp_deck import (
|
|
|
15
18
|
)
|
|
16
19
|
from opentrons.drivers.rpi_drivers.types import USBPort
|
|
17
20
|
from opentrons.hardware_control.execution_manager import ExecutionManager
|
|
18
|
-
from opentrons.hardware_control.modules import update, mod_abc, types
|
|
21
|
+
from opentrons.hardware_control.modules import update, mod_abc, types, errors
|
|
19
22
|
|
|
20
23
|
log = logging.getLogger(__name__)
|
|
21
24
|
|
|
@@ -26,7 +29,7 @@ SIM_TEMP_POLL_INTERVAL_SECS = TEMP_POLL_INTERVAL_SECS / 20.0
|
|
|
26
29
|
class TempDeck(mod_abc.AbstractModule):
|
|
27
30
|
"""Hardware control interface for an attached Temperature Module."""
|
|
28
31
|
|
|
29
|
-
MODULE_TYPE = types.ModuleType
|
|
32
|
+
MODULE_TYPE = types.ModuleType["TEMPERATURE"]
|
|
30
33
|
FIRST_GEN2_REVISION = 20
|
|
31
34
|
|
|
32
35
|
@classmethod
|
|
@@ -40,6 +43,7 @@ class TempDeck(mod_abc.AbstractModule):
|
|
|
40
43
|
simulating: bool = False,
|
|
41
44
|
sim_model: Optional[str] = None,
|
|
42
45
|
sim_serial_number: Optional[str] = None,
|
|
46
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
43
47
|
) -> "TempDeck":
|
|
44
48
|
"""
|
|
45
49
|
Build a TempDeck
|
|
@@ -52,6 +56,7 @@ class TempDeck(mod_abc.AbstractModule):
|
|
|
52
56
|
poll_interval_seconds: Poll interval override.
|
|
53
57
|
simulating: whether to build a simulating driver
|
|
54
58
|
sim_model: The model name used by simulator
|
|
59
|
+
disconnected_callback: Callback to inform the module controller that the device was disconnected
|
|
55
60
|
|
|
56
61
|
Returns:
|
|
57
62
|
Tempdeck instance
|
|
@@ -77,6 +82,7 @@ class TempDeck(mod_abc.AbstractModule):
|
|
|
77
82
|
poller=poller,
|
|
78
83
|
device_info=await driver.get_device_info(),
|
|
79
84
|
hw_control_loop=hw_control_loop,
|
|
85
|
+
disconnected_callback=disconnected_callback,
|
|
80
86
|
)
|
|
81
87
|
|
|
82
88
|
try:
|
|
@@ -94,8 +100,9 @@ class TempDeck(mod_abc.AbstractModule):
|
|
|
94
100
|
driver: AbstractTempDeckDriver,
|
|
95
101
|
reader: TempDeckReader,
|
|
96
102
|
poller: Poller,
|
|
97
|
-
device_info:
|
|
103
|
+
device_info: Dict[str, str],
|
|
98
104
|
hw_control_loop: asyncio.AbstractEventLoop,
|
|
105
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
99
106
|
) -> None:
|
|
100
107
|
"""Constructor"""
|
|
101
108
|
super().__init__(
|
|
@@ -103,6 +110,7 @@ class TempDeck(mod_abc.AbstractModule):
|
|
|
103
110
|
usb_port=usb_port,
|
|
104
111
|
hw_control_loop=hw_control_loop,
|
|
105
112
|
execution_manager=execution_manager,
|
|
113
|
+
disconnected_callback=disconnected_callback,
|
|
106
114
|
)
|
|
107
115
|
self._device_info = device_info
|
|
108
116
|
self._driver = driver
|
|
@@ -182,7 +190,7 @@ class TempDeck(mod_abc.AbstractModule):
|
|
|
182
190
|
await self._reader.read()
|
|
183
191
|
|
|
184
192
|
@property
|
|
185
|
-
def device_info(self) ->
|
|
193
|
+
def device_info(self) -> Dict[str, str]:
|
|
186
194
|
return self._device_info
|
|
187
195
|
|
|
188
196
|
@property
|
|
@@ -211,7 +219,7 @@ class TempDeck(mod_abc.AbstractModule):
|
|
|
211
219
|
async def prep_for_update(self) -> str:
|
|
212
220
|
model = self._device_info and self._device_info.get("model")
|
|
213
221
|
if model in ("temp_deck_v1", "temp_deck_v1.1", "temp_deck_v2"):
|
|
214
|
-
raise
|
|
222
|
+
raise errors.UpdateError(
|
|
215
223
|
"This Temperature Module can't be updated."
|
|
216
224
|
"Please contact Opentrons Support."
|
|
217
225
|
)
|
|
@@ -2,12 +2,15 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
|
-
from typing import Callable, Optional, List, Dict, Mapping
|
|
5
|
+
from typing import Callable, Optional, List, Dict, Mapping, Union, cast
|
|
6
6
|
from opentrons.drivers.rpi_drivers.types import USBPort
|
|
7
7
|
from opentrons.drivers.types import ThermocyclerLidStatus, Temperature, PlateTemperature
|
|
8
8
|
from opentrons.hardware_control.modules.lid_temp_status import LidTemperatureStatus
|
|
9
9
|
from opentrons.hardware_control.modules.plate_temp_status import PlateTemperatureStatus
|
|
10
|
-
from opentrons.hardware_control.modules.types import
|
|
10
|
+
from opentrons.hardware_control.modules.types import (
|
|
11
|
+
ModuleDisconnectedCallback,
|
|
12
|
+
TemperatureStatus,
|
|
13
|
+
)
|
|
11
14
|
from opentrons.hardware_control.poller import Reader, Poller
|
|
12
15
|
|
|
13
16
|
from ..execution_manager import ExecutionManager
|
|
@@ -64,6 +67,7 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
64
67
|
simulating: bool = False,
|
|
65
68
|
sim_model: Optional[str] = None,
|
|
66
69
|
sim_serial_number: Optional[str] = None,
|
|
70
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
67
71
|
) -> "Thermocycler":
|
|
68
72
|
"""
|
|
69
73
|
Build and connect to a Thermocycler
|
|
@@ -77,6 +81,7 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
77
81
|
simulating: whether to build a simulating driver
|
|
78
82
|
loop: Loop
|
|
79
83
|
sim_model: The model name used by simulator
|
|
84
|
+
disconnected_callback: Callback to inform the module controller that the device was disconnected
|
|
80
85
|
|
|
81
86
|
Returns:
|
|
82
87
|
Thermocycler instance.
|
|
@@ -102,6 +107,7 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
102
107
|
device_info=await driver.get_device_info(),
|
|
103
108
|
hw_control_loop=hw_control_loop,
|
|
104
109
|
execution_manager=execution_manager,
|
|
110
|
+
disconnected_callback=disconnected_callback,
|
|
105
111
|
)
|
|
106
112
|
|
|
107
113
|
try:
|
|
@@ -121,6 +127,7 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
121
127
|
poller: Poller,
|
|
122
128
|
device_info: Dict[str, str],
|
|
123
129
|
hw_control_loop: asyncio.AbstractEventLoop,
|
|
130
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
124
131
|
) -> None:
|
|
125
132
|
"""
|
|
126
133
|
Constructor
|
|
@@ -134,6 +141,7 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
134
141
|
poller: A poll controller for reads.
|
|
135
142
|
device_info: The thermocycler device info.
|
|
136
143
|
hw_control_loop: The event loop running in the hardware control thread.
|
|
144
|
+
disconnected_callback: Callback to inform the module controller that the device was disconnected
|
|
137
145
|
"""
|
|
138
146
|
self._driver = driver
|
|
139
147
|
super().__init__(
|
|
@@ -141,6 +149,7 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
141
149
|
usb_port=usb_port,
|
|
142
150
|
hw_control_loop=hw_control_loop,
|
|
143
151
|
execution_manager=execution_manager,
|
|
152
|
+
disconnected_callback=disconnected_callback,
|
|
144
153
|
)
|
|
145
154
|
self._device_info = device_info
|
|
146
155
|
self._reader = reader
|
|
@@ -354,6 +363,39 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
354
363
|
self.make_cancellable(task)
|
|
355
364
|
await task
|
|
356
365
|
|
|
366
|
+
async def execute_profile(
|
|
367
|
+
self,
|
|
368
|
+
profile: List[Union[types.ThermocyclerCycle, types.ThermocyclerStep]],
|
|
369
|
+
volume: Optional[float] = None,
|
|
370
|
+
) -> None:
|
|
371
|
+
"""Begin a set temperature profile, with both repeating and non-repeating steps.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
profile: The temperature profile to follow.
|
|
375
|
+
volume: Optional volume
|
|
376
|
+
|
|
377
|
+
Returns: None
|
|
378
|
+
"""
|
|
379
|
+
await self.wait_for_is_running()
|
|
380
|
+
self._total_cycle_count = 0
|
|
381
|
+
self._total_step_count = 0
|
|
382
|
+
self._current_cycle_index = 0
|
|
383
|
+
self._current_step_index = 0
|
|
384
|
+
for step_or_cycle in profile:
|
|
385
|
+
if "steps" in step_or_cycle:
|
|
386
|
+
# basically https://github.com/python/mypy/issues/14766
|
|
387
|
+
this_cycle = cast(types.ThermocyclerCycle, step_or_cycle)
|
|
388
|
+
self._total_cycle_count += this_cycle["repetitions"]
|
|
389
|
+
self._total_step_count += (
|
|
390
|
+
len(this_cycle["steps"]) * this_cycle["repetitions"]
|
|
391
|
+
)
|
|
392
|
+
else:
|
|
393
|
+
self._total_step_count += 1
|
|
394
|
+
self._total_cycle_count += 1
|
|
395
|
+
task = self._loop.create_task(self._execute_profile(profile, volume))
|
|
396
|
+
self.make_cancellable(task)
|
|
397
|
+
await task
|
|
398
|
+
|
|
357
399
|
async def set_lid_temperature(self, temperature: float) -> None:
|
|
358
400
|
"""Set the lid temperature in degrees Celsius"""
|
|
359
401
|
await self.wait_for_is_running()
|
|
@@ -565,7 +607,7 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
565
607
|
self,
|
|
566
608
|
steps: List[types.ThermocyclerStep],
|
|
567
609
|
repetitions: int,
|
|
568
|
-
volume: Optional[float]
|
|
610
|
+
volume: Optional[float],
|
|
569
611
|
) -> None:
|
|
570
612
|
"""
|
|
571
613
|
Execute cycles.
|
|
@@ -583,6 +625,30 @@ class Thermocycler(mod_abc.AbstractModule):
|
|
|
583
625
|
self._current_step_index = step_idx + 1 # science starts at 1
|
|
584
626
|
await self._execute_cycle_step(step, volume)
|
|
585
627
|
|
|
628
|
+
async def _execute_profile(
|
|
629
|
+
self,
|
|
630
|
+
profile: List[Union[types.ThermocyclerCycle, types.ThermocyclerStep]],
|
|
631
|
+
volume: Optional[float],
|
|
632
|
+
) -> None:
|
|
633
|
+
"""
|
|
634
|
+
Execute profiles.
|
|
635
|
+
|
|
636
|
+
Profiles command a thermocycler pattern that can contain multiple cycles and out-of-cycle steps.
|
|
637
|
+
"""
|
|
638
|
+
self._current_cycle_index = 0
|
|
639
|
+
self._current_step_index = 0
|
|
640
|
+
for step_or_cycle in profile:
|
|
641
|
+
self._current_cycle_index += 1
|
|
642
|
+
if "repetitions" in step_or_cycle:
|
|
643
|
+
# basically https://github.com/python/mypy/issues/14766
|
|
644
|
+
this_cycle = cast(types.ThermocyclerCycle, step_or_cycle)
|
|
645
|
+
for rep in range(this_cycle["repetitions"]):
|
|
646
|
+
for step in this_cycle["steps"]:
|
|
647
|
+
self._current_step_index += 1
|
|
648
|
+
await self._execute_cycle_step(step, volume)
|
|
649
|
+
else:
|
|
650
|
+
await self._execute_cycle_step(step_or_cycle, volume)
|
|
651
|
+
|
|
586
652
|
# TODO(mc, 2022-10-13): why does this exist?
|
|
587
653
|
# Do the driver and poller really need to be disconnected?
|
|
588
654
|
# Could we accomplish the same thing by latching the error state
|
|
@@ -3,6 +3,7 @@ from enum import Enum
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from typing import (
|
|
5
5
|
Dict,
|
|
6
|
+
List,
|
|
6
7
|
NamedTuple,
|
|
7
8
|
Callable,
|
|
8
9
|
Any,
|
|
@@ -38,12 +39,20 @@ class ThermocyclerStep(ThermocyclerStepBase, total=False):
|
|
|
38
39
|
hold_time_minutes: float
|
|
39
40
|
|
|
40
41
|
|
|
42
|
+
class ThermocyclerCycle(TypedDict):
|
|
43
|
+
steps: List[ThermocyclerStep]
|
|
44
|
+
repetitions: int
|
|
45
|
+
|
|
46
|
+
|
|
41
47
|
UploadFunction = Callable[[str, str, Dict[str, Any]], Awaitable[Tuple[bool, str]]]
|
|
42
48
|
|
|
43
49
|
|
|
50
|
+
ModuleDisconnectedCallback = Optional[Callable[[str, str | None], None]]
|
|
51
|
+
|
|
52
|
+
|
|
44
53
|
class LiveData(TypedDict):
|
|
45
54
|
status: str
|
|
46
|
-
data: Dict[str, Union[float, str, bool, None]]
|
|
55
|
+
data: Dict[str, Union[float, str, bool, List[int], None]]
|
|
47
56
|
|
|
48
57
|
|
|
49
58
|
class ModuleType(str, Enum):
|
|
@@ -135,6 +144,7 @@ def module_model_from_string(model_string: str) -> ModuleModel:
|
|
|
135
144
|
class ModuleAtPort:
|
|
136
145
|
port: str
|
|
137
146
|
name: str
|
|
147
|
+
serial: Optional[str] = None
|
|
138
148
|
usb_port: USBPort = USBPort(name="", port_number=0)
|
|
139
149
|
|
|
140
150
|
|
|
@@ -159,10 +169,6 @@ class BundledFirmware(NamedTuple):
|
|
|
159
169
|
return f"<BundledFirmware {self.version}, path={self.path}>"
|
|
160
170
|
|
|
161
171
|
|
|
162
|
-
class UpdateError(RuntimeError):
|
|
163
|
-
pass
|
|
164
|
-
|
|
165
|
-
|
|
166
172
|
class ModuleInfo(NamedTuple):
|
|
167
173
|
model: str # A module model such as "magneticModuleV2"
|
|
168
174
|
fw_version: str # The version of the firmware
|
|
@@ -4,7 +4,8 @@ import os
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from glob import glob
|
|
6
6
|
from typing import Any, AsyncGenerator, Dict, Tuple, Union
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
from .errors import UpdateError
|
|
8
9
|
from .mod_abc import AbstractModule
|
|
9
10
|
from opentrons.hardware_control.threaded_async_lock import ThreadedAsyncLock
|
|
10
11
|
from contextlib import asynccontextmanager
|
|
@@ -33,6 +34,7 @@ async def update_firmware(
|
|
|
33
34
|
kwargs: Dict[str, Any] = {
|
|
34
35
|
"stdout": asyncio.subprocess.PIPE,
|
|
35
36
|
"stderr": asyncio.subprocess.PIPE,
|
|
37
|
+
"module": module,
|
|
36
38
|
}
|
|
37
39
|
successful, res = await module.bootloader()(
|
|
38
40
|
flash_port_or_dfu_serial, str(firmware_file), kwargs
|
|
@@ -139,7 +141,8 @@ async def upload_via_avrdude(
|
|
|
139
141
|
"-b{}".format(BAUDRATE),
|
|
140
142
|
"-D",
|
|
141
143
|
"-Uflash:w:{}:i".format(firmware_file_path),
|
|
142
|
-
|
|
144
|
+
stdout=kwargs["stdout"],
|
|
145
|
+
stderr=kwargs["stderr"],
|
|
143
146
|
)
|
|
144
147
|
await proc.wait()
|
|
145
148
|
|
|
@@ -191,8 +194,9 @@ async def upload_via_bossa(
|
|
|
191
194
|
"--offset=0x2000",
|
|
192
195
|
f"{firmware_file_path}",
|
|
193
196
|
]
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
proc = await asyncio.create_subprocess_exec(
|
|
198
|
+
*bossa_args, stdout=kwargs["stdout"], stderr=kwargs["stderr"]
|
|
199
|
+
)
|
|
196
200
|
stdout, stderr = await proc.communicate()
|
|
197
201
|
res = stdout.decode()
|
|
198
202
|
if "Verify successful" in res:
|
|
@@ -231,7 +235,9 @@ async def upload_via_dfu(
|
|
|
231
235
|
f"-D{firmware_file_path}",
|
|
232
236
|
"-R",
|
|
233
237
|
]
|
|
234
|
-
proc = await asyncio.create_subprocess_exec(
|
|
238
|
+
proc = await asyncio.create_subprocess_exec(
|
|
239
|
+
*dfu_args, stdout=kwargs["stdout"], stderr=kwargs["stderr"]
|
|
240
|
+
)
|
|
235
241
|
stdout, stderr = await proc.communicate()
|
|
236
242
|
res = stdout.decode()
|
|
237
243
|
|
|
@@ -6,7 +6,7 @@ from opentrons.drivers.rpi_drivers.types import USBPort
|
|
|
6
6
|
|
|
7
7
|
from ..execution_manager import ExecutionManager
|
|
8
8
|
|
|
9
|
-
from .types import ModuleType, SpeedStatus
|
|
9
|
+
from .types import ModuleDisconnectedCallback, ModuleType, SpeedStatus
|
|
10
10
|
from .mod_abc import AbstractModule
|
|
11
11
|
from .tempdeck import TempDeck
|
|
12
12
|
from .magdeck import MagDeck
|
|
@@ -46,6 +46,7 @@ async def build(
|
|
|
46
46
|
execution_manager: ExecutionManager,
|
|
47
47
|
sim_model: Optional[str] = None,
|
|
48
48
|
sim_serial_number: Optional[str] = None,
|
|
49
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
49
50
|
) -> AbstractModule:
|
|
50
51
|
return await _MODULE_CLS_BY_TYPE[type].build(
|
|
51
52
|
port=port,
|
|
@@ -55,6 +56,7 @@ async def build(
|
|
|
55
56
|
execution_manager=execution_manager,
|
|
56
57
|
sim_model=sim_model,
|
|
57
58
|
sim_serial_number=sim_serial_number,
|
|
59
|
+
disconnected_callback=disconnected_callback,
|
|
58
60
|
)
|
|
59
61
|
|
|
60
62
|
|
|
@@ -819,13 +819,13 @@ async def find_pipette_offset(
|
|
|
819
819
|
try:
|
|
820
820
|
if reset_instrument_offset:
|
|
821
821
|
await hcapi.reset_instrument_offset(mount)
|
|
822
|
-
|
|
822
|
+
hcapi.add_tip(mount, hcapi.config.calibration.probe_length)
|
|
823
823
|
offset = await _calibrate_mount(
|
|
824
824
|
hcapi, mount, slot, method, raise_verify_error, probe=probe
|
|
825
825
|
)
|
|
826
826
|
return offset
|
|
827
827
|
finally:
|
|
828
|
-
|
|
828
|
+
hcapi.remove_tip(mount)
|
|
829
829
|
|
|
830
830
|
|
|
831
831
|
async def calibrate_pipette(
|
|
@@ -877,7 +877,7 @@ async def calibrate_module(
|
|
|
877
877
|
if mount == OT3Mount.GRIPPER:
|
|
878
878
|
hcapi.add_gripper_probe(GripperProbe.FRONT)
|
|
879
879
|
else:
|
|
880
|
-
|
|
880
|
+
hcapi.add_tip(mount, hcapi.config.calibration.probe_length)
|
|
881
881
|
|
|
882
882
|
LOG.info(
|
|
883
883
|
f"Starting module calibration for {module_id} at {nominal_position} using {mount}"
|
|
@@ -903,7 +903,7 @@ async def calibrate_module(
|
|
|
903
903
|
hcapi.remove_gripper_probe()
|
|
904
904
|
await hcapi.ungrip()
|
|
905
905
|
else:
|
|
906
|
-
|
|
906
|
+
hcapi.remove_tip(mount)
|
|
907
907
|
|
|
908
908
|
|
|
909
909
|
async def calibrate_belts(
|
|
@@ -927,7 +927,7 @@ async def calibrate_belts(
|
|
|
927
927
|
raise RuntimeError("Must use pipette mount, not gripper")
|
|
928
928
|
try:
|
|
929
929
|
hcapi.reset_deck_calibration()
|
|
930
|
-
|
|
930
|
+
hcapi.add_tip(mount, hcapi.config.calibration.probe_length)
|
|
931
931
|
belt_attitude, alignment_details = await _determine_transform_matrix(
|
|
932
932
|
hcapi, mount
|
|
933
933
|
)
|
|
@@ -935,7 +935,7 @@ async def calibrate_belts(
|
|
|
935
935
|
return belt_attitude, alignment_details
|
|
936
936
|
finally:
|
|
937
937
|
hcapi.load_deck_calibration()
|
|
938
|
-
|
|
938
|
+
hcapi.remove_tip(mount)
|
|
939
939
|
|
|
940
940
|
|
|
941
941
|
def apply_machine_transform(
|