diff --git a/hardware-testing/Makefile b/hardware-testing/Makefile index b1cff5c8170..884558290ed 100755 --- a/hardware-testing/Makefile +++ b/hardware-testing/Makefile @@ -223,12 +223,8 @@ cleanup" endef .PHONY: sync-sw-ot3 -sync-sw-ot3: - cd ../hardware && $(MAKE) push-ot3 host=$(host) - cd ../api && $(MAKE) push-ot3 host=$(host) - cd ../shared-data && $(MAKE) all push-ot3 host=$(host) - cd ../robot-server && $(MAKE) push-ot3 host=$(host) - cd ../hardware-testing && $(MAKE) push-ot3 host=$(host) +sync-sw-ot3: push-ot3 + cd .. && $(MAKE) push-ot3 host=$(host) .PHONY: sync-fw-ot3 sync-fw-ot3: diff --git a/hardware-testing/hardware_testing/gravimetric/execute.py b/hardware-testing/hardware_testing/gravimetric/execute.py index 79222060163..198e76ec85b 100644 --- a/hardware-testing/hardware_testing/gravimetric/execute.py +++ b/hardware-testing/hardware_testing/gravimetric/execute.py @@ -1,4 +1,5 @@ """Gravimetric.""" +from time import sleep from dataclasses import dataclass from inspect import getsource from statistics import stdev @@ -113,7 +114,7 @@ def _reduce_volumes_to_not_exceed_software_limit( liq_cls = get_liquid_class( cfg.pipette_volume, cfg.pipette_channels, cfg.tip_volume, int(v) ) - max_vol = cfg.tip_volume - liq_cls.aspirate.air_gap.trailing_air_gap + max_vol = cfg.tip_volume - liq_cls.aspirate.trailing_air_gap test_volumes[i] = min(v, max_vol - 0.1) return test_volumes @@ -663,7 +664,8 @@ def run(ctx: ProtocolContext, cfg: config.GravimetricConfig) -> None: setup_channel_offset = _get_channel_offset(cfg, channel=0) first_tip_location = first_tip.top().move(setup_channel_offset) _pick_up_tip(ctx, pipette, cfg, location=first_tip_location) - pipette.home() + mnt = OT3Mount.LEFT if cfg.pipette_mount == "left" else OT3Mount.RIGHT + ctx._core.get_hardware().retract(mnt) if not ctx.is_simulating(): ui.get_user_ready("REPLACE first tip with NEW TIP") ui.get_user_ready("CLOSE the door, and MOVE AWAY from machine") @@ -689,9 +691,10 @@ def run(ctx: ProtocolContext, cfg: config.GravimetricConfig) -> None: pipette.move_to(hover_pos) for i in range(config.SCALE_SECONDS_TO_TRUE_STABILIZE): print( - f"wait {i + 1}/{config.SCALE_SECONDS_TO_TRUE_STABILIZE} seconds before" - f" measuring evaporation" + f"wait for scale to stabilize " + f"({i + 1}/{config.SCALE_SECONDS_TO_TRUE_STABILIZE})" ) + sleep(1) actual_asp_list_evap: List[float] = [] actual_disp_list_evap: List[float] = [] for trial in range(config.NUM_BLANK_TRIALS): diff --git a/hardware-testing/hardware_testing/gravimetric/execute_photometric.py b/hardware-testing/hardware_testing/gravimetric/execute_photometric.py index 02b4166393b..bd5cbd78f1f 100644 --- a/hardware-testing/hardware_testing/gravimetric/execute_photometric.py +++ b/hardware-testing/hardware_testing/gravimetric/execute_photometric.py @@ -11,7 +11,7 @@ from hardware_testing.data.csv_report import CSVReport from hardware_testing.data import create_run_id_and_start_time, ui, get_git_description -from hardware_testing.opentrons_api.types import Point +from hardware_testing.opentrons_api.types import Point, OT3Mount from .measurement import ( MeasurementType, create_measurement_tag, @@ -72,7 +72,7 @@ def _reduce_volumes_to_not_exceed_software_limit( ) -> List[float]: for i, v in enumerate(test_volumes): liq_cls = get_liquid_class(cfg.pipette_volume, 96, cfg.tip_volume, int(v)) - max_vol = cfg.tip_volume - liq_cls.aspirate.air_gap.trailing_air_gap + max_vol = cfg.tip_volume - liq_cls.aspirate.trailing_air_gap test_volumes[i] = min(v, max_vol - 0.1) return test_volumes @@ -493,7 +493,8 @@ def _next_tip() -> Well: setup_tip = tips[0][0] volume_for_setup = max(test_volumes) _pick_up_tip(ctx, pipette, cfg, location=setup_tip.top()) - pipette.home() + mnt = OT3Mount.LEFT if cfg.pipette_mount == "left" else OT3Mount.RIGHT + ctx._core.get_hardware().retract(mnt) if not ctx.is_simulating(): ui.get_user_ready("REPLACE first tip with NEW TIP") required_ul = max( diff --git a/hardware-testing/hardware_testing/gravimetric/liquid_class/defaults.py b/hardware-testing/hardware_testing/gravimetric/liquid_class/defaults.py index f7437f6b956..bf31b7b4d14 100644 --- a/hardware-testing/hardware_testing/gravimetric/liquid_class/defaults.py +++ b/hardware-testing/hardware_testing/gravimetric/liquid_class/defaults.py @@ -5,14 +5,19 @@ LiquidClassSettings, AspirateSettings, DispenseSettings, - AirGapSettings, interpolate, ) -# submerge/retract Z distances _default_submerge_mm = 1.5 -_default_submerge_mm_t50 = 1.5 _default_retract_mm = 3.0 +_default_retract_discontinuity = 20 + +_default_aspirate_delay_seconds = 1.0 +_default_dispense_delay_seconds = 0.5 + +_default_accel_p50_ul_sec_sec = 1200 +_default_accel_p1000_ul_sec_sec = 24000 +_default_accel_96ch_ul_sec_sec = 16000 # dispense settings are constant across volumes _dispense_defaults = { @@ -20,108 +25,120 @@ 50: { # P50 50: { # T50 1: DispenseSettings( # 1uL - flow_rate=57, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=40000, # this is a fake number - deceleration=40000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=57, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=2, ), 10: DispenseSettings( # 10uL - flow_rate=57, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=40000, # this is a fake number - deceleration=40000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=57, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=2, ), 50: DispenseSettings( # 50uL - flow_rate=57, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=40000, # this is a fake number - deceleration=40000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=57, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=2, ), }, }, 1000: { # P1000 50: { # T50 5: DispenseSettings( # 5uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 10: DispenseSettings( # 10uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 50: DispenseSettings( # 10uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), }, 200: { # T200 5: DispenseSettings( # 5uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 50: DispenseSettings( # 50uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 200: DispenseSettings( # 200uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), }, 1000: { # T1000 10: DispenseSettings( # 10uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), 100: DispenseSettings( # 100uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), 1000: DispenseSettings( # 1000uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), }, }, @@ -130,108 +147,120 @@ 50: { # P50 50: { # T50 1: DispenseSettings( # 1uL - flow_rate=57, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=40000, # this is a fake number - deceleration=40000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=57, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=2, ), 10: DispenseSettings( # 5uL - flow_rate=57, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=40000, # this is a fake number - deceleration=40000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=57, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=2, ), 50: DispenseSettings( # 50uL - flow_rate=57, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=40000, # this is a fake number - deceleration=40000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=57, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=2, ), }, }, 1000: { # P1000 50: { # T50 5: DispenseSettings( # 5uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 10: DispenseSettings( # 10uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 50: DispenseSettings( # 50uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), }, 200: { # T200 5: DispenseSettings( # 5uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 50: DispenseSettings( # 50uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 200: DispenseSettings( # 200uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), }, 1000: { # T1000 10: DispenseSettings( # 10uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), 100: DispenseSettings( # 100uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), 1000: DispenseSettings( # 1000uL - flow_rate=160, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), }, }, @@ -240,80 +269,89 @@ 1000: { # P1000 50: { # T50 5: DispenseSettings( # 5uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 10: DispenseSettings( # 10uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 50: DispenseSettings( # 50uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), }, 200: { # T200 5: DispenseSettings( # 5uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 50: DispenseSettings( # 50uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), 200: DispenseSettings( # 200uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, # this is a fake number - deceleration=20000, # this is a fake number + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=5, ), }, 1000: { # T1000 10: DispenseSettings( # 10uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), 100: DispenseSettings( # 100uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), 1000: DispenseSettings( # 1000uL - flow_rate=80, - delay=0.5, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - acceleration=10000, - deceleration=20000, + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_dispense_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + leading_air_gap=20, ), }, }, @@ -325,132 +363,120 @@ 50: { # P50 50: { # T50 1: AspirateSettings( # 1uL - flow_rate=35, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=2, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=35, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 10: AspirateSettings( # 10uL - flow_rate=23.5, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=2, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=23.5, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 50: AspirateSettings( # 50uL - flow_rate=35, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=2, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=35, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), }, }, 1000: { # P1000 50: { # T50 5: AspirateSettings( # 5uL - flow_rate=318, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=318, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 10: AspirateSettings( # 10uL - flow_rate=478, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=478, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 50: AspirateSettings( # 50uL - flow_rate=478, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=478, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), }, 200: { # T200 5: AspirateSettings( # 5uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=5, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=5, ), 50: AspirateSettings( # 50uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=3.5, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=3.5, ), 200: AspirateSettings( # 200uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=2, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=2, ), }, 1000: { # T1000 10: AspirateSettings( # 10uL - flow_rate=160, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), 100: AspirateSettings( # 100uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), 1000: AspirateSettings( # 1000uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), }, }, @@ -459,132 +485,120 @@ 50: { # P50 50: { # T50 1: AspirateSettings( # 1uL - flow_rate=35, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=2, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=35, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 10: AspirateSettings( # 10uL - flow_rate=23.5, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=2, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=23.5, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 50: AspirateSettings( # 50uL - flow_rate=35, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=2, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p50_ul_sec_sec, + plunger_flow_rate=35, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), }, }, 1000: { # P1000 50: { # T50 5: AspirateSettings( # 5uL - flow_rate=318, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=318, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 10: AspirateSettings( # 10uL - flow_rate=478, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=478, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 50: AspirateSettings( # 50uL - flow_rate=478, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=478, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), }, 200: { # T200 5: AspirateSettings( # 5uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=5, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=5, ), 50: AspirateSettings( # 50uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=3.5, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=3.5, ), 200: AspirateSettings( # 200uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=2, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=2, ), }, 1000: { # T1000 10: AspirateSettings( # 10uL - flow_rate=160, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), 100: AspirateSettings( # 100uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), 1000: AspirateSettings( # 1000uL - flow_rate=716, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_p1000_ul_sec_sec, + plunger_flow_rate=716, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), }, }, @@ -593,98 +607,89 @@ 1000: { # P1000 50: { # T50 5: AspirateSettings( # 5uL - flow_rate=6.5, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=6.5, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 10: AspirateSettings( # 10uL - flow_rate=6.5, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=6.5, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), 50: AspirateSettings( # 50uL - flow_rate=6.5, - delay=1.0, - submerge=_default_submerge_mm_t50, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=0.1, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=6.5, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=0.1, ), }, 200: { # T200 5: AspirateSettings( # 5uL - flow_rate=80, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=2, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=2, ), 50: AspirateSettings( # 50uL - flow_rate=80, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=3.5, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=3.5, ), 200: AspirateSettings( # 200uL - flow_rate=80, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=5, - trailing_air_gap=2, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=80, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=2, ), }, 1000: { # T1000 10: AspirateSettings( # 10uL - flow_rate=160, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), 100: AspirateSettings( # 100uL - flow_rate=160, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), 1000: AspirateSettings( # 1000uL - flow_rate=160, - delay=1.0, - submerge=_default_submerge_mm, - retract=_default_retract_mm, - air_gap=AirGapSettings( - leading_air_gap=20, - trailing_air_gap=10, - ), + z_submerge_depth=_default_submerge_mm, + plunger_acceleration=_default_accel_96ch_ul_sec_sec, + plunger_flow_rate=160, # ul/sec + delay=_default_aspirate_delay_seconds, + z_retract_discontinuity=_default_retract_discontinuity, + z_retract_height=_default_retract_mm, + trailing_air_gap=10, ), }, }, diff --git a/hardware-testing/hardware_testing/gravimetric/liquid_class/definition.py b/hardware-testing/hardware_testing/gravimetric/liquid_class/definition.py index 20b420b0ba5..bf9eb0b5c0e 100644 --- a/hardware-testing/hardware_testing/gravimetric/liquid_class/definition.py +++ b/hardware-testing/hardware_testing/gravimetric/liquid_class/definition.py @@ -6,33 +6,26 @@ class LiquidSettings: """Liquid Settings for both aspirate and dispense.""" - flow_rate: float # ul/sec + z_submerge_depth: float # millimeters below meniscus + plunger_acceleration: float # ul/sec/sec + plunger_flow_rate: float # ul/sec delay: float # seconds - submerge: float # millimeters below meniscus - retract: float # millimeters above meniscus - - -@dataclass -class AirGapSettings: - """Air Gap Settings.""" - - leading_air_gap: float # microliters - trailing_air_gap: float # microliters + z_retract_discontinuity: float # mm/sec + z_retract_height: float # millimeters above meniscus @dataclass class AspirateSettings(LiquidSettings): """Aspirate Settings.""" - air_gap: AirGapSettings + trailing_air_gap: float # microliters @dataclass class DispenseSettings(LiquidSettings): """Dispense Settings.""" - acceleration: float # ul/sec^2 FIXME: get working within protocol - deceleration: float # ul/sec^2 FIXME: get working within protocol + leading_air_gap: float # microliters @dataclass @@ -53,27 +46,45 @@ def _interp(lower: float, upper: float) -> float: return LiquidClassSettings( aspirate=AspirateSettings( - flow_rate=_interp(a.aspirate.flow_rate, b.aspirate.flow_rate), + z_submerge_depth=_interp( + a.aspirate.z_submerge_depth, b.aspirate.z_submerge_depth + ), + plunger_acceleration=_interp( + a.aspirate.plunger_acceleration, b.aspirate.plunger_acceleration + ), + plunger_flow_rate=_interp( + a.aspirate.plunger_flow_rate, b.aspirate.plunger_flow_rate + ), delay=_interp(a.aspirate.delay, b.aspirate.delay), - submerge=_interp(a.aspirate.submerge, b.aspirate.submerge), - retract=_interp(a.aspirate.retract, b.aspirate.retract), - air_gap=AirGapSettings( - leading_air_gap=_interp( - a.aspirate.air_gap.leading_air_gap, - b.aspirate.air_gap.leading_air_gap, - ), - trailing_air_gap=_interp( - a.aspirate.air_gap.trailing_air_gap, - b.aspirate.air_gap.trailing_air_gap, - ), + z_retract_discontinuity=_interp( + a.aspirate.z_retract_discontinuity, b.aspirate.z_retract_discontinuity + ), + z_retract_height=_interp( + a.aspirate.z_retract_height, b.aspirate.z_retract_height + ), + trailing_air_gap=_interp( + a.aspirate.trailing_air_gap, b.aspirate.trailing_air_gap ), ), dispense=DispenseSettings( - flow_rate=_interp(a.dispense.flow_rate, b.dispense.flow_rate), + z_submerge_depth=_interp( + a.dispense.z_submerge_depth, b.dispense.z_submerge_depth + ), + plunger_acceleration=_interp( + a.dispense.plunger_acceleration, b.dispense.plunger_acceleration + ), + plunger_flow_rate=_interp( + a.dispense.plunger_flow_rate, b.dispense.plunger_flow_rate + ), delay=_interp(a.dispense.delay, b.dispense.delay), - submerge=_interp(a.dispense.submerge, b.dispense.submerge), - retract=_interp(a.dispense.retract, b.dispense.retract), - acceleration=_interp(a.dispense.acceleration, b.dispense.acceleration), - deceleration=_interp(a.dispense.deceleration, b.dispense.deceleration), + z_retract_discontinuity=_interp( + a.dispense.z_retract_discontinuity, b.dispense.z_retract_discontinuity + ), + z_retract_height=_interp( + a.dispense.z_retract_height, b.dispense.z_retract_height + ), + leading_air_gap=_interp( + a.dispense.leading_air_gap, b.dispense.leading_air_gap + ), ), ) diff --git a/hardware-testing/hardware_testing/gravimetric/liquid_class/pipetting.py b/hardware-testing/hardware_testing/gravimetric/liquid_class/pipetting.py index d85c1163674..8d2c2151433 100644 --- a/hardware-testing/hardware_testing/gravimetric/liquid_class/pipetting.py +++ b/hardware-testing/hardware_testing/gravimetric/liquid_class/pipetting.py @@ -1,10 +1,16 @@ """Pipette motions.""" +from math import pi from dataclasses import dataclass from typing import Optional, Callable, Tuple +from opentrons.config.defaults_ot3 import ( + DEFAULT_ACCELERATIONS, + DEFAULT_MAX_SPEED_DISCONTINUITY, +) from opentrons.protocol_api import InstrumentContext, ProtocolContext from opentrons.protocol_api.labware import Well +from hardware_testing.opentrons_api.types import OT3AxisKind from hardware_testing.gravimetric import config from hardware_testing.gravimetric.liquid_height.height import LiquidTracker from hardware_testing.opentrons_api.types import OT3Mount, Point @@ -64,11 +70,6 @@ class PipettingCallbacks: on_exiting: Callable -def _do_user_pause(ctx: ProtocolContext, inspect: bool, msg: str = "") -> None: - if not ctx.is_simulating() and inspect: - input(f"{msg}, ENTER to continue") - - def _check_aspirate_dispense_args( aspirate: Optional[float], dispense: Optional[float] ) -> None: @@ -79,7 +80,6 @@ def _check_aspirate_dispense_args( def _get_approach_submerge_retract_heights( - pipette: InstrumentContext, well: Well, liquid_tracker: LiquidTracker, liquid_class: LiquidClassSettings, @@ -99,11 +99,11 @@ def _get_approach_submerge_retract_heights( liquid_before = well.depth + (well.depth - liquid_before) liquid_after = well.depth + (well.depth - liquid_after) if aspirate: - liq_submerge = liquid_class.aspirate.submerge - liq_retract = liquid_class.aspirate.retract + liq_submerge = liquid_class.aspirate.z_submerge_depth + liq_retract = liquid_class.aspirate.z_retract_height else: - liq_submerge = liquid_class.dispense.submerge - liq_retract = liquid_class.dispense.retract + liq_submerge = liquid_class.dispense.z_submerge_depth + liq_retract = liquid_class.dispense.z_retract_height approach_mm, submerge_mm, retract_mm = _get_heights_in_well( liquid_before, liquid_after, liq_submerge, liq_retract ) @@ -125,21 +125,85 @@ def _submerge( def _retract( + ctx: ProtocolContext, pipette: InstrumentContext, well: Well, - height: float, channel_offset: Point, speed: float, + z_discontinuity: float, ) -> None: - pipette.move_to( - well.bottom(height).move(channel_offset), - force_direct=True, - speed=speed, - ) + # change discontinuity per the liquid-class settings + hw_api = ctx._core.get_hardware() + if pipette.channels == 96: + hw_api.config.motion_settings.max_speed_discontinuity.high_throughput[ + OT3AxisKind.Z + ] = z_discontinuity + else: + hw_api.config.motion_settings.max_speed_discontinuity.low_throughput[ + OT3AxisKind.Z + ] = z_discontinuity + # NOTE: re-setting the gantry-load will reset the move-manager's per-axis constraints + hw_api.set_gantry_load(hw_api.gantry_load) + # retract out of well pipette.move_to( well.top().move(channel_offset), force_direct=True, + speed=speed, ) + # reset discontinuity back to default + if pipette.channels == 96: + hw_api.config.motion_settings.max_speed_discontinuity.high_throughput[ + OT3AxisKind.Z + ] = DEFAULT_MAX_SPEED_DISCONTINUITY.high_throughput[OT3AxisKind.Z] + else: + hw_api.config.motion_settings.max_speed_discontinuity.low_throughput[ + OT3AxisKind.Z + ] = DEFAULT_MAX_SPEED_DISCONTINUITY.low_throughput[OT3AxisKind.Z] + # NOTE: re-setting the gantry-load will reset the move-manager's per-axis constraints + hw_api.set_gantry_load(hw_api.gantry_load) + + +def _change_plunger_acceleration( + ctx: ProtocolContext, pipette: InstrumentContext, ul_per_sec_per_sec: float +) -> None: + hw_api = ctx._core.get_hardware() + # NOTE: set plunger accelerations by converting ul/sec/sec to mm/sec/sec, + # making sure to use the nominal ul/mm to convert so that the + # mm/sec/sec we move is constant regardless of changes to the function + if "p50" in pipette.name: + shaft_diameter_mm = 1.0 + else: + shaft_diameter_mm = 4.5 + nominal_ul_per_mm = pi * pow(shaft_diameter_mm * 0.5, 2) + p_accel = ul_per_sec_per_sec / nominal_ul_per_mm + if pipette.channels == 96: + hw_api.config.motion_settings.acceleration.high_throughput[ + OT3AxisKind.P + ] = p_accel + else: + hw_api.config.motion_settings.acceleration.low_throughput[ + OT3AxisKind.P + ] = p_accel + # NOTE: re-setting the gantry-load will reset the move-manager's per-axis constraints + hw_api.set_gantry_load(hw_api.gantry_load) + + +def _reset_plunger_acceleration( + ctx: ProtocolContext, pipette: InstrumentContext +) -> None: + hw_api = ctx._core.get_hardware() + if pipette.channels == 96: + p_accel = DEFAULT_ACCELERATIONS.high_throughput[OT3AxisKind.P] + hw_api.config.motion_settings.acceleration.high_throughput[ + OT3AxisKind.P + ] = p_accel + else: + p_accel = DEFAULT_ACCELERATIONS.low_throughput[OT3AxisKind.P] + hw_api.config.motion_settings.acceleration.low_throughput[ + OT3AxisKind.P + ] = p_accel + # NOTE: re-setting the gantry-load will reset the move-manager's per-axis constraints + hw_api.set_gantry_load(hw_api.gantry_load) def _pipette_with_liquid_settings( @@ -165,10 +229,9 @@ def _pipette_with_liquid_settings( def _dispense_with_added_blow_out() -> None: # dispense all liquid, plus some air by calling `pipette.blow_out(location, volume)` # FIXME: this is a hack, until there's an equivalent `pipette.blow_out(location, volume)` - pipette.flow_rate.blow_out = liquid_class.dispense.flow_rate hw_api = ctx._core.get_hardware() hw_mount = OT3Mount.LEFT if pipette.mount == "left" else OT3Mount.RIGHT - hw_api.blow_out(hw_mount, liquid_class.aspirate.air_gap.leading_air_gap) + hw_api.blow_out(hw_mount, liquid_class.dispense.leading_air_gap) # ASPIRATE/DISPENSE SEQUENCE HAS THREE PHASES: # 1. APPROACH @@ -177,7 +240,6 @@ def _dispense_with_added_blow_out() -> None: # CALCULATE TIP HEIGHTS FOR EACH PHASE approach_mm, submerge_mm, retract_mm = _get_approach_submerge_retract_heights( - pipette, well, liquid_tracker, liquid_class, @@ -197,16 +259,7 @@ def _dispense_with_added_blow_out() -> None: # CREATE CALLBACKS FOR EACH PHASE def _aspirate_on_approach() -> None: - # set plunger speeds - pipette.flow_rate.aspirate = liquid_class.aspirate.flow_rate - pipette.flow_rate.dispense = liquid_class.dispense.flow_rate - pipette.flow_rate.blow_out = liquid_class.dispense.flow_rate - # Note: Here, we previously would aspirate some air, to account for the leading-air-gap. - # However, we can instead use the already-present air between the pipette's - # "bottom" and "blow-out" plunger positions. This would require the `pipette.blow_out` - # method to accept a microliter amount as an optional argument. - # Advantage: guarantee all aspirations begin at same position, helping low-volume accuracy. - # Disadvantage: limit our max leading-air-gap volume, potentially leaving droplets behind. + pass def _aspirate_on_submerge() -> None: # mix 5x times @@ -215,8 +268,9 @@ def _aspirate_on_submerge() -> None: for i in range(config.NUM_MIXES_BEFORE_ASPIRATE): pipette.aspirate(aspirate) pipette.dispense(aspirate) + _z_disc = liquid_class.aspirate.z_retract_discontinuity _retract( - pipette, well, approach_mm, channel_offset, retract_speed + ctx, pipette, well, channel_offset, retract_speed, _z_disc ) # retract to the approach height pipette.blow_out().aspirate(pipette.min_volume).dispense() _submerge(pipette, well, submerge_mm, channel_offset, submerge_speed) @@ -232,15 +286,11 @@ def _aspirate_on_submerge() -> None: def _aspirate_on_retract() -> None: # add trailing-air-gap - # NOTE: temporarily set aspirate flow-rate to be the faster dispense flow-rate - pipette.flow_rate.aspirate = liquid_class.dispense.flow_rate - pipette.aspirate(liquid_class.aspirate.air_gap.trailing_air_gap) - pipette.flow_rate.aspirate = liquid_class.aspirate.flow_rate + pipette.aspirate(liquid_class.aspirate.trailing_air_gap) def _dispense_on_approach() -> None: - _do_user_pause(ctx, inspect, "about to dispense") # remove trailing-air-gap - pipette.dispense(liquid_class.aspirate.air_gap.trailing_air_gap) + pipette.dispense(liquid_class.aspirate.trailing_air_gap) def _dispense_on_submerge() -> None: callbacks.on_dispensing() @@ -254,13 +304,11 @@ def _dispense_on_submerge() -> None: ) # delay ctx.delay(liquid_class.dispense.delay) - _do_user_pause(ctx, inspect, "about to retract") def _dispense_on_retract() -> None: - if added_blow_out: + if pipette.current_volume <= 0 and added_blow_out: # blow-out any remaining air in pipette (any reason why not?) callbacks.on_blowing_out() - _do_user_pause(ctx, inspect, "about to blow-out") # FIXME: using the HW-API to specify that we want to blow-out the full # available blow-out volume hw_api = ctx._core.get_hardware() @@ -272,12 +320,15 @@ def _dispense_on_retract() -> None: pipette.touch_tip(speed=config.TOUCH_TIP_SPEED) # NOTE: always do a trailing-air-gap, regardless of if tip is empty or not # to avoid droplets from forming and falling off the tip - # NOTE: temporarily set aspirate flow-rate to be the faster dispense flow-rate - pipette.flow_rate.aspirate = liquid_class.dispense.flow_rate - pipette.aspirate(liquid_class.aspirate.air_gap.trailing_air_gap) - pipette.flow_rate.aspirate = liquid_class.aspirate.flow_rate + pipette.aspirate(liquid_class.aspirate.trailing_air_gap) # PHASE 1: APPROACH + pipette.flow_rate.aspirate = liquid_class.aspirate.plunger_flow_rate + pipette.flow_rate.dispense = liquid_class.dispense.plunger_flow_rate + pipette.flow_rate.blow_out = liquid_class.dispense.plunger_flow_rate + _change_plunger_acceleration( + ctx, pipette, liquid_class.dispense.plunger_acceleration + ) pipette.move_to(well.bottom(approach_mm).move(channel_offset)) _aspirate_on_approach() if aspirate else _dispense_on_approach() @@ -288,12 +339,17 @@ def _dispense_on_retract() -> None: # PHASE 3: RETRACT callbacks.on_retracting() - _retract(pipette, well, retract_mm, channel_offset, retract_speed) + if aspirate: + _z_disc = liquid_class.aspirate.z_retract_discontinuity + else: + _z_disc = liquid_class.dispense.z_retract_discontinuity + _retract(ctx, pipette, well, channel_offset, retract_speed, _z_disc) _aspirate_on_retract() if aspirate else _dispense_on_retract() # EXIT callbacks.on_exiting() pipette.move_to(well.top().move(channel_offset), force_direct=True) + _reset_plunger_acceleration(ctx, pipette) def aspirate_with_liquid_class( diff --git a/hardware-testing/hardware_testing/gravimetric/overrides/api.patch b/hardware-testing/hardware_testing/gravimetric/overrides/api.patch index 061ace17eaf..77a109d240e 100644 --- a/hardware-testing/hardware_testing/gravimetric/overrides/api.patch +++ b/hardware-testing/hardware_testing/gravimetric/overrides/api.patch @@ -3,47 +3,6 @@ index 4035e961fa,1dfde3aa43..0000000000 deleted file mode 100644,100644 --- a/hardware-testing/hardware_testing/gravimetric/overrides/api.patch +++ /dev/null -diff --git a/api/src/opentrons/config/defaults_ot3.py b/api/src/opentrons/config/defaults_ot3.py -index 7d5560b54a..ecd2656f1e 100644 ---- a/api/src/opentrons/config/defaults_ot3.py -+++ b/api/src/opentrons/config/defaults_ot3.py -@@ -92,25 +92,25 @@ DEFAULT_MAX_SPEEDS: Final[ByGantryLoad[Dict[OT3AxisKind, float]]] = ByGantryLoad - OT3AxisKind.X: 400, - OT3AxisKind.Y: 325, - OT3AxisKind.Z: 100, - OT3AxisKind.P: 70, - OT3AxisKind.Z_G: 50, - }, - ) - - DEFAULT_ACCELERATIONS: Final[ByGantryLoad[Dict[OT3AxisKind, float]]] = ByGantryLoad( - high_throughput={ - OT3AxisKind.X: 800, - OT3AxisKind.Y: 500, - OT3AxisKind.Z: 150, -- OT3AxisKind.P: 30, -+ OT3AxisKind.P: 1000, # FIXME: move to liquid-class - OT3AxisKind.Z_G: 150, - OT3AxisKind.Q: 10, - }, - low_throughput={ - OT3AxisKind.X: 800, - OT3AxisKind.Y: 600, - OT3AxisKind.Z: 150, -- OT3AxisKind.P: 100, -+ OT3AxisKind.P: 1500, # FIXME: move to liquid-class - OT3AxisKind.Z_G: 150, - }, - ) -@@ -121,7 +121,7 @@ DEFAULT_MAX_SPEED_DISCONTINUITY: Final[ - high_throughput={ - OT3AxisKind.X: 10, - OT3AxisKind.Y: 10, -- OT3AxisKind.Z: 5, -+ OT3AxisKind.Z: 15, # FIXME: move to liquid-class - OT3AxisKind.P: 5, - OT3AxisKind.Z_G: 10, - OT3AxisKind.Q: 5, diff --git a/api/src/opentrons/hardware_control/instruments/ot3/pipette.py b/api/src/opentrons/hardware_control/instruments/ot3/pipette.py index 815dada3b9..30121fc4c8 100644 --- a/api/src/opentrons/hardware_control/instruments/ot3/pipette.py