opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.0a0__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 +207 -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/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 +230 -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 +126 -89
- 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/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 +10 -2
- opentrons/protocol_api/core/engine/module_core.py +129 -17
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +355 -0
- opentrons/protocol_api/core/engine/protocol.py +55 -2
- opentrons/protocol_api/core/instrument.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +5 -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 +5 -2
- opentrons/protocol_api/instrument_context.py +52 -20
- opentrons/protocol_api/labware.py +13 -1
- opentrons/protocol_api/module_contexts.py +68 -13
- opentrons/protocol_api/protocol_context.py +38 -4
- opentrons/protocol_api/validation.py +5 -3
- opentrons/protocol_engine/__init__.py +10 -9
- opentrons/protocol_engine/actions/__init__.py +5 -0
- opentrons/protocol_engine/actions/actions.py +42 -25
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/sync_client.py +7 -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 +161 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +53 -9
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +160 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +196 -0
- opentrons/protocol_engine/commands/aspirate.py +29 -16
- opentrons/protocol_engine/commands/aspirate_in_place.py +32 -15
- 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 +28 -17
- 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 +68 -15
- opentrons/protocol_engine/commands/drop_tip_in_place.py +52 -11
- 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 +19 -5
- opentrons/protocol_engine/commands/load_liquid.py +18 -7
- opentrons/protocol_engine/commands/load_module.py +43 -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 +106 -19
- 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 +50 -29
- opentrons/protocol_engine/commands/pipetting_common.py +39 -15
- 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 +194 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +75 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +5 -3
- 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 +41 -8
- opentrons/protocol_engine/engine_support.py +2 -1
- opentrons/protocol_engine/error_recovery_policy.py +14 -3
- opentrons/protocol_engine/errors/__init__.py +18 -0
- opentrons/protocol_engine/errors/exceptions.py +114 -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 +6 -3
- opentrons/protocol_engine/execution/movement.py +8 -3
- 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 +54 -31
- opentrons/protocol_engine/resources/__init__.py +2 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +58 -5
- opentrons/protocol_engine/resources/file_provider.py +157 -0
- opentrons/protocol_engine/resources/fixture_validation.py +5 -0
- 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 +359 -15
- opentrons/protocol_engine/state/labware.py +166 -63
- opentrons/protocol_engine/state/liquids.py +1 -1
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +19 -3
- opentrons/protocol_engine/state/modules.py +167 -85
- opentrons/protocol_engine/state/motion.py +16 -9
- 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 +408 -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 +26 -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/simulate.py +3 -3
- opentrons/types.py +30 -3
- opentrons/util/logging_config.py +34 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/METADATA +5 -4
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/RECORD +227 -215
- 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.0a0.dist-info → opentrons-8.2.0a0.dist-info}/LICENSE +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/WHEEL +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/top_level.txt +0 -0
|
@@ -13,7 +13,6 @@ from typing import (
|
|
|
13
13
|
Sequence,
|
|
14
14
|
Iterator,
|
|
15
15
|
TypeVar,
|
|
16
|
-
overload,
|
|
17
16
|
)
|
|
18
17
|
import numpy
|
|
19
18
|
|
|
@@ -415,7 +414,7 @@ class PipetteHandlerProvider(Generic[MountType]):
|
|
|
415
414
|
if instr:
|
|
416
415
|
instr.reset_nozzle_configuration()
|
|
417
416
|
|
|
418
|
-
|
|
417
|
+
def add_tip(self, mount: MountType, tip_length: float) -> None:
|
|
419
418
|
instr = self._attached_instruments[mount]
|
|
420
419
|
attached = self.attached_instruments
|
|
421
420
|
instr_dict = attached[mount]
|
|
@@ -430,7 +429,15 @@ class PipetteHandlerProvider(Generic[MountType]):
|
|
|
430
429
|
f"attach tip called while tip already attached to {instr}"
|
|
431
430
|
)
|
|
432
431
|
|
|
433
|
-
|
|
432
|
+
def cache_tip(self, mount: MountType, tip_length: float) -> None:
|
|
433
|
+
instrument = self.get_pipette(mount)
|
|
434
|
+
if instrument.has_tip:
|
|
435
|
+
# instrument.add_tip() would raise an AssertionError if we tried to overwrite an existing tip.
|
|
436
|
+
instrument.remove_tip()
|
|
437
|
+
instrument.add_tip(tip_length=tip_length)
|
|
438
|
+
instrument.set_current_volume(0)
|
|
439
|
+
|
|
440
|
+
def remove_tip(self, mount: MountType) -> None:
|
|
434
441
|
instr = self._attached_instruments[mount]
|
|
435
442
|
attached = self.attached_instruments
|
|
436
443
|
instr_dict = attached[mount]
|
|
@@ -495,25 +502,12 @@ class PipetteHandlerProvider(Generic[MountType]):
|
|
|
495
502
|
ul_per_s = mm_per_s * instr.ul_per_mm(instr.liquid_class.max_volume, action)
|
|
496
503
|
return round(ul_per_s, 6)
|
|
497
504
|
|
|
498
|
-
@overload
|
|
499
505
|
def plan_check_aspirate(
|
|
500
|
-
self, mount: top_types.Mount, volume: Optional[float], rate: float
|
|
501
|
-
) -> Optional[LiquidActionSpec]:
|
|
502
|
-
...
|
|
503
|
-
|
|
504
|
-
@overload
|
|
505
|
-
def plan_check_aspirate(
|
|
506
|
-
self, mount: OT3Mount, volume: Optional[float], rate: float
|
|
507
|
-
) -> Optional[LiquidActionSpec]:
|
|
508
|
-
...
|
|
509
|
-
|
|
510
|
-
# note on this type ignore: see motion_utilities
|
|
511
|
-
def plan_check_aspirate( # type: ignore[no-untyped-def]
|
|
512
506
|
self,
|
|
513
|
-
mount,
|
|
514
|
-
volume,
|
|
515
|
-
rate,
|
|
516
|
-
):
|
|
507
|
+
mount: MountType,
|
|
508
|
+
volume: Optional[float],
|
|
509
|
+
rate: float,
|
|
510
|
+
) -> Optional[LiquidActionSpec]:
|
|
517
511
|
"""Check preconditions for aspirate, parse args, and calculate positions.
|
|
518
512
|
|
|
519
513
|
While the mechanics of issuing an aspirate move itself are left to child
|
|
@@ -572,28 +566,12 @@ class PipetteHandlerProvider(Generic[MountType]):
|
|
|
572
566
|
current=instrument.plunger_motor_current.run,
|
|
573
567
|
)
|
|
574
568
|
|
|
575
|
-
@overload
|
|
576
569
|
def plan_check_dispense(
|
|
577
570
|
self,
|
|
578
|
-
mount:
|
|
579
|
-
volume: Optional[float],
|
|
580
|
-
rate: float,
|
|
581
|
-
push_out: Optional[float],
|
|
582
|
-
) -> Optional[LiquidActionSpec]:
|
|
583
|
-
...
|
|
584
|
-
|
|
585
|
-
@overload
|
|
586
|
-
def plan_check_dispense(
|
|
587
|
-
self,
|
|
588
|
-
mount: OT3Mount,
|
|
571
|
+
mount: MountType,
|
|
589
572
|
volume: Optional[float],
|
|
590
573
|
rate: float,
|
|
591
574
|
push_out: Optional[float],
|
|
592
|
-
) -> Optional[LiquidActionSpec]:
|
|
593
|
-
...
|
|
594
|
-
|
|
595
|
-
def plan_check_dispense( # type: ignore[no-untyped-def]
|
|
596
|
-
self, mount, volume, rate, push_out
|
|
597
575
|
) -> Optional[LiquidActionSpec]:
|
|
598
576
|
"""Check preconditions for dispense, parse args, and calculate positions.
|
|
599
577
|
|
|
@@ -687,15 +665,7 @@ class PipetteHandlerProvider(Generic[MountType]):
|
|
|
687
665
|
current=instrument.plunger_motor_current.run,
|
|
688
666
|
)
|
|
689
667
|
|
|
690
|
-
|
|
691
|
-
def plan_check_blow_out(self, mount: top_types.Mount) -> LiquidActionSpec:
|
|
692
|
-
...
|
|
693
|
-
|
|
694
|
-
@overload
|
|
695
|
-
def plan_check_blow_out(self, mount: OT3Mount) -> LiquidActionSpec:
|
|
696
|
-
...
|
|
697
|
-
|
|
698
|
-
def plan_check_blow_out(self, mount): # type: ignore[no-untyped-def]
|
|
668
|
+
def plan_check_blow_out(self, mount: MountType) -> LiquidActionSpec:
|
|
699
669
|
"""Check preconditions and calculate values for blowout."""
|
|
700
670
|
instrument = self.get_pipette(mount)
|
|
701
671
|
speed = self.plunger_speed(
|
|
@@ -743,33 +713,13 @@ class PipetteHandlerProvider(Generic[MountType]):
|
|
|
743
713
|
else:
|
|
744
714
|
return []
|
|
745
715
|
|
|
746
|
-
@overload
|
|
747
716
|
def plan_check_pick_up_tip(
|
|
748
717
|
self,
|
|
749
|
-
mount:
|
|
750
|
-
presses: Optional[int],
|
|
751
|
-
increment: Optional[float],
|
|
752
|
-
tip_length: float = 0,
|
|
753
|
-
) -> Tuple[PickUpTipSpec, Callable[[], None]]:
|
|
754
|
-
...
|
|
755
|
-
|
|
756
|
-
@overload
|
|
757
|
-
def plan_check_pick_up_tip(
|
|
758
|
-
self,
|
|
759
|
-
mount: OT3Mount,
|
|
718
|
+
mount: MountType,
|
|
760
719
|
presses: Optional[int],
|
|
761
720
|
increment: Optional[float],
|
|
762
721
|
tip_length: float = 0,
|
|
763
722
|
) -> Tuple[PickUpTipSpec, Callable[[], None]]:
|
|
764
|
-
...
|
|
765
|
-
|
|
766
|
-
def plan_check_pick_up_tip( # type: ignore[no-untyped-def]
|
|
767
|
-
self,
|
|
768
|
-
mount,
|
|
769
|
-
presses,
|
|
770
|
-
increment,
|
|
771
|
-
tip_length=0,
|
|
772
|
-
):
|
|
773
723
|
# Prechecks: ready for pickup tip and press/increment are valid
|
|
774
724
|
instrument = self.get_pipette(mount)
|
|
775
725
|
if instrument.has_tip:
|
|
@@ -917,23 +867,13 @@ class PipetteHandlerProvider(Generic[MountType]):
|
|
|
917
867
|
|
|
918
868
|
return build
|
|
919
869
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
self, mount: top_types.Mount, home_after: bool
|
|
923
|
-
) -> Tuple[DropTipSpec, Callable[[], None]]:
|
|
924
|
-
...
|
|
925
|
-
|
|
926
|
-
@overload
|
|
870
|
+
# todo(mm, 2024-10-17): The returned _remove_tips() callable is not used by anything
|
|
871
|
+
# anymore. Delete it.
|
|
927
872
|
def plan_check_drop_tip(
|
|
928
|
-
self, mount: OT3Mount, home_after: bool
|
|
929
|
-
) -> Tuple[DropTipSpec, Callable[[], None]]:
|
|
930
|
-
...
|
|
931
|
-
|
|
932
|
-
def plan_check_drop_tip( # type: ignore[no-untyped-def]
|
|
933
873
|
self,
|
|
934
|
-
mount,
|
|
935
|
-
home_after,
|
|
936
|
-
):
|
|
874
|
+
mount: MountType,
|
|
875
|
+
home_after: bool,
|
|
876
|
+
) -> Tuple[DropTipSpec, Callable[[], None]]:
|
|
937
877
|
instrument = self.get_pipette(mount)
|
|
938
878
|
|
|
939
879
|
if not instrument.drop_configurations.plunger_eject:
|
|
@@ -425,7 +425,7 @@ class OT3PipetteHandler:
|
|
|
425
425
|
if instr:
|
|
426
426
|
instr.reset_nozzle_configuration()
|
|
427
427
|
|
|
428
|
-
|
|
428
|
+
def add_tip(self, mount: OT3Mount, tip_length: float) -> None:
|
|
429
429
|
instr = self._attached_instruments[mount]
|
|
430
430
|
attached = self.attached_instruments
|
|
431
431
|
instr_dict = attached[mount]
|
|
@@ -440,7 +440,15 @@ class OT3PipetteHandler:
|
|
|
440
440
|
"attach tip called while tip already attached to {instr}"
|
|
441
441
|
)
|
|
442
442
|
|
|
443
|
-
|
|
443
|
+
def cache_tip(self, mount: OT3Mount, tip_length: float) -> None:
|
|
444
|
+
instrument = self.get_pipette(mount)
|
|
445
|
+
if instrument.has_tip:
|
|
446
|
+
# instrument.add_tip() would raise an AssertionError if we tried to overwrite an existing tip.
|
|
447
|
+
instrument.remove_tip()
|
|
448
|
+
instrument.add_tip(tip_length=tip_length)
|
|
449
|
+
instrument.set_current_volume(0)
|
|
450
|
+
|
|
451
|
+
def remove_tip(self, mount: OT3Mount) -> None:
|
|
444
452
|
instr = self._attached_instruments[mount]
|
|
445
453
|
attached = self.attached_instruments
|
|
446
454
|
instr_dict = attached[mount]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
import asyncio
|
|
2
3
|
import logging
|
|
3
4
|
import re
|
|
4
5
|
from typing import TYPE_CHECKING, List, Optional, Union
|
|
@@ -9,12 +10,13 @@ from opentrons.drivers.rpi_drivers import types, interfaces, usb, usb_simulator
|
|
|
9
10
|
from opentrons.hardware_control.emulation.module_server.helpers import (
|
|
10
11
|
listen_module_connection,
|
|
11
12
|
)
|
|
13
|
+
from opentrons.hardware_control.modules.absorbance_reader import AbsorbanceReader
|
|
12
14
|
from opentrons.hardware_control.modules.module_calibration import (
|
|
13
15
|
ModuleCalibrationOffset,
|
|
14
16
|
load_module_calibration_offset,
|
|
15
17
|
save_module_calibration_offset,
|
|
16
18
|
)
|
|
17
|
-
from opentrons.hardware_control.modules.types import ModuleType
|
|
19
|
+
from opentrons.hardware_control.modules.types import ModuleAtPort, ModuleType
|
|
18
20
|
from opentrons.hardware_control.modules import SimulatingModuleAtPort
|
|
19
21
|
|
|
20
22
|
from opentrons.types import Point
|
|
@@ -99,6 +101,15 @@ class AttachedModulesControl:
|
|
|
99
101
|
execution_manager=self._api._execution_manager,
|
|
100
102
|
sim_model=sim_model,
|
|
101
103
|
sim_serial_number=sim_serial_number,
|
|
104
|
+
disconnected_callback=self._disconnected_callback,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def _disconnected_callback(self, port: str, serial: Optional[str]) -> None:
|
|
108
|
+
"""Used by the module to indicate that it was disconnected and should be deleted."""
|
|
109
|
+
mod = ModuleAtPort(port=port, serial=serial, name="")
|
|
110
|
+
asyncio.run_coroutine_threadsafe(
|
|
111
|
+
self.unregister_modules([mod]),
|
|
112
|
+
self._api.loop,
|
|
102
113
|
)
|
|
103
114
|
|
|
104
115
|
async def unregister_modules(
|
|
@@ -115,8 +126,12 @@ class AttachedModulesControl:
|
|
|
115
126
|
removed_modules = []
|
|
116
127
|
for mod in mods_at_ports:
|
|
117
128
|
for attached_mod in self.available_modules:
|
|
118
|
-
if
|
|
129
|
+
if (
|
|
130
|
+
attached_mod.serial_number == mod.serial
|
|
131
|
+
or attached_mod.port == mod.port
|
|
132
|
+
):
|
|
119
133
|
removed_modules.append(attached_mod)
|
|
134
|
+
|
|
120
135
|
for removed_mod in removed_modules:
|
|
121
136
|
try:
|
|
122
137
|
self._available_modules.remove(removed_mod)
|
|
@@ -231,9 +246,35 @@ class AttachedModulesControl:
|
|
|
231
246
|
removed_modules = None
|
|
232
247
|
if maybe_module_at_port is not None:
|
|
233
248
|
if hasattr(event.flags, "DELETE") or hasattr(event.flags, "MOVED_FROM"):
|
|
249
|
+
# NOTE: The absorbance reader is a hidraw device, when we first
|
|
250
|
+
# plug it into the Flex, udev rules create a
|
|
251
|
+
# /dev/ot_module_absorbancereader(n) symlink which aionotify
|
|
252
|
+
# detects as a CREATE event and registers an absorbance module.
|
|
253
|
+
# When we create this Absorbance module and connect to it,
|
|
254
|
+
# the Byonoy library opens the device via hidapi which removes
|
|
255
|
+
# the symlink and triggers a DELETE action from aionoify.
|
|
256
|
+
# When the device is deleted, we disconnect from it causing
|
|
257
|
+
# the /dev/ot_module_absorbance(n) symlink to get created, repeating
|
|
258
|
+
# the cycle.
|
|
259
|
+
|
|
260
|
+
# This DELETE action would normally delete the device, but in this case
|
|
261
|
+
# Lets ignore these events for the absorbance reader and handle
|
|
262
|
+
# cleanup when the poller attempts to read data and fails.
|
|
263
|
+
if maybe_module_at_port.name == "absorbancereader":
|
|
264
|
+
return
|
|
234
265
|
removed_modules = [maybe_module_at_port]
|
|
235
266
|
log.info(f"Module Removed: {maybe_module_at_port}")
|
|
236
267
|
elif hasattr(event.flags, "CREATE") or hasattr(event.flags, "MOVED_TO"):
|
|
268
|
+
# NOTE: Absorbance reader gets disonnected when updating, so
|
|
269
|
+
# if the device is updating, dont create a new instance.
|
|
270
|
+
for module in self._available_modules:
|
|
271
|
+
if (
|
|
272
|
+
maybe_module_at_port.name == "absorbancereader"
|
|
273
|
+
and isinstance(module, AbsorbanceReader)
|
|
274
|
+
and module.updating
|
|
275
|
+
):
|
|
276
|
+
return
|
|
277
|
+
|
|
237
278
|
new_modules = [maybe_module_at_port]
|
|
238
279
|
log.info(f"Module Added: {maybe_module_at_port}")
|
|
239
280
|
try:
|
|
@@ -10,7 +10,6 @@ from .types import (
|
|
|
10
10
|
ThermocyclerStep,
|
|
11
11
|
UploadFunction,
|
|
12
12
|
BundledFirmware,
|
|
13
|
-
UpdateError,
|
|
14
13
|
ModuleAtPort,
|
|
15
14
|
SimulatingModuleAtPort,
|
|
16
15
|
SimulatingModule,
|
|
@@ -23,6 +22,11 @@ from .types import (
|
|
|
23
22
|
SpeedStatus,
|
|
24
23
|
LiveData,
|
|
25
24
|
)
|
|
25
|
+
from .errors import (
|
|
26
|
+
UpdateError,
|
|
27
|
+
AbsorbanceReaderDisconnectedError,
|
|
28
|
+
)
|
|
29
|
+
|
|
26
30
|
|
|
27
31
|
__all__ = [
|
|
28
32
|
"MODULE_TYPE_BY_NAME",
|
|
@@ -49,4 +53,6 @@ __all__ = [
|
|
|
49
53
|
"LiveData",
|
|
50
54
|
"AbsorbanceReader",
|
|
51
55
|
"AbsorbanceReaderStatus",
|
|
56
|
+
"AbsorbanceReaderDisconnectedError",
|
|
57
|
+
"ModuleDisconnectedCallback",
|
|
52
58
|
]
|