def remove_supernatant(vol, src, dest, side, pip=p300, mode=None): if mode == 'elution': p300.flow_rate.aspirate = 10 else: p300.flow_rate.aspirate = 30 p300.flow_rate.dispense = 30 while vol > 200: p300.aspirate( 200, src.bottom().move(types.Point(x=side, y=0, z=0.5))) p300.dispense(200, dest) p300.aspirate(10, dest) vol -= 200 p300.aspirate(vol, src.bottom().move(types.Point(x=side, y=0, z=0.5))) p300.dispense(vol, dest) if mode == 'elution': p300.blow_out() if dest == trash: p300.blow_out() p300.flow_rate.aspirate = 50
def resuspend_pellet(well, pip, mvol, reps=10): """ 'resuspend_pellet' will forcefully dispense liquid over the pellet after the magdeck engage in order to more thoroughly resuspend the pellet. param well: The current well that the resuspension will occur in. param pip: The pipet that is currently attached/ being used. param mvol: The volume that is transferred before the mixing steps. param reps: The number of mix repetitions that should occur. Note~ During each mix rep, there are 2 cycles of aspirating from center, dispensing at the top and 2 cycles of aspirating from center, dispensing at the bottom (5 mixes total) """ rightLeft = int(str(well).split(' ')[0][1:]) % 2 """ 'rightLeft' will determine which value to use in the list of 'top' and 'bottom' (below), based on the column of the 'well' used. In the case that an Even column is used, the first value of 'top' and 'bottom' will be used, otherwise, the second value of each will be used. """ center = well.bottom().move(types.Point(x=0,y=0,z=0.1)) top = [ well.bottom().move(types.Point(x=-3.8,y=3.8,z=0.1)), well.bottom().move(types.Point(x=3.8,y=3.8,z=0.1)) ] bottom = [ well.bottom().move(types.Point(x=-3.8,y=-3.8,z=0.1)), well.bottom().move(types.Point(x=3.8,y=-3.8,z=0.1)) ] pip.flow_rate.dispense = 500 pip.flow_rate.aspirate = 150 mix_vol = 0.9 * mvol pip.move_to(center) for _ in range(reps): for _ in range(2): pip.aspirate(mix_vol, center) pip.dispense(mix_vol, top[rightLeft]) for _ in range(2): pip.aspirate(mix_vol, center) pip.dispense(mix_vol, bottom[rightLeft])
def super_removal(vol, d_plate, tips): m300.flow_rate.aspirate = 30 for idx, (src, dest, tip) in enumerate(zip(magwells, d_plate, tips)): side = -1 if idx % 2 == 0 else 1 m300.pick_up_tip(tip) m300.aspirate(vol, src.bottom().move(types.Point(x=side, y=0, z=0.5))) m300.air_gap(20) m300.dispense(vol + 20, dest) m300.drop_tip() m300.flow_rate.aspirate = 100
def supernatant_removal(vol, src, dest, side, trash_mode=False): m300.flow_rate.aspirate = 20 while vol >= max_tip_volume: m300.aspirate(max_tip_volume, src.bottom().move(types.Point(x=side, y=0, z=0.5))) m300.dispense(max_tip_volume, dest) if trash_mode: for _ in range(2): m300.blow_out() vol -= max_tip_volume if vol < max_tip_volume: m300.aspirate(vol, src.bottom().move(types.Point(x=side, y=0, z=0.5))) m300.dispense(vol, dest) if trash_mode: for _ in range(2): m300.blow_out() m300.flow_rate.aspirate = 50 reset_flow_rates()
def remove_residual_supernatant(pip, vol): p1000.flow_rate.aspirate = 75 p1000.flow_rate.dispense = 75 for well in mag_plate_wells[:samples]: pick_up(pip) pip.aspirate( vol, well.bottom().move( types.Point(x=getWellSide(well, mag_plate), y=0, z=0.5))) pip.dispense(vol, trash) pip.drop_tip() reset_flow_rates()
async def test_mount_offset_applied(hardware_api): await hardware_api.home() abs_position = types.Point(30, 20, 10) mount = types.Mount.LEFT target_position = {Axis.X: 64, Axis.Y: 20, Axis.Z: 10, Axis.A: 218, Axis.B: 19, Axis.C: 19} await hardware_api.move_to(mount, abs_position) assert hardware_api._current_position == target_position
async def test_move_extras_passed_through(hardware_api, monkeypatch): mock_be_move = mock.Mock() monkeypatch.setattr(hardware_api._backend, 'move', mock_be_move) await hardware_api.home() await hardware_api.move_to(types.Mount.RIGHT, types.Point(0, 0, 0)) assert mock_be_move.call_args_list[0][1]['speed'] is None assert mock_be_move.call_args_list[0][1]['axis_max_speeds'] == {} mock_be_move.reset_mock() await hardware_api.move_to(types.Mount.RIGHT, types.Point(1, 1, 1), speed=30, max_speeds={Axis.X: 10}) assert mock_be_move.call_args_list[0][1]['speed'] == 30 assert mock_be_move.call_args_list[0][1]['axis_max_speeds'] == {'X': 10} mock_be_move.reset_mock() await hardware_api.move_rel(types.Mount.LEFT, types.Point(1, 1, 1), speed=40, max_speeds={Axis.Y: 20}) assert mock_be_move.call_args_list[0][1]['speed'] == 40 assert mock_be_move.call_args_list[0][1]['axis_max_speeds'] == {'Y': 20}
async def move(request: web.Request, session) -> web.Response: req = await request.json() moveloc = MoveLocation(**req) if hasattr(moveloc.location, 'offset'): # using getattr to avoid error raised by Union of deck position and # tiprack position having different attributes. offset = getattr(moveloc.location, 'offset') location = { "locationId": moveloc.location.locationId, "offset": types.Point(*offset) } else: position = getattr(moveloc.location, 'position') location = { "locationId": moveloc.location.locationId, "position": types.Point(*position) } await session.trigger_transition(CalibrationCheckTrigger.confirm_step, pipette_id=moveloc.pipetteId, request_location=location) return web.json_response(status=200)
def repeat_dispense(dist_vol, source, dest, max_asp=tip_max, disposal=0): # chunk size math.floor((max_asp - disposal) / dist_vol) for multi disp for chunk in create_chunks(dest.columns()[:num_cols], 1): if disposal > 0: p20m.aspirate(disposal, source) p20m.aspirate(dist_vol * len(chunk), source) for column in chunk: p20m.dispense(dist_vol, column[0].bottom(clearance_dispense)) # blowout changed to dispense of disposal volume to avoid bubbles p20m.dispense( disposal, source.move(types.Point(x=0, y=0, z=blowout_vertical_offset)))
async def test_retract(hardware_api, toggle_new_calibration): await hardware_api.home() await hardware_api.move_to(types.Mount.RIGHT, types.Point(0, 10, 20)) await hardware_api.retract(types.Mount.RIGHT, 10) assert hardware_api._current_position == { Axis.X: 0, Axis.Y: 10, Axis.Z: 218, Axis.A: 218, Axis.B: 19, Axis.C: 19 }
def slow_transfer(vol, reagent, columnID, reagentName, mixVol=washMixing, repeats=mixRepeats, mixReagent=False, altura=generalHeight, magnetTime=True, incubationTime = incubationWash, moveSide=0, extraVol=0, pipette=p300): """ Similar to remove_supernatant, but the other way around. It transfers from point A to point B in <tipVol> ul trips and pours liquid from the top, to avoid contaminating the tip while transfering all the necessary volume. It also includes incubation and magnet """ protocol.comment("\n\nADDING STEP: Transfering %s ul of %s to samples" % (vol, reagentName)) for index, ID in enumerate(columnID): src=reagent to=deepPlate[ID] currentip = availableTips.pop() retrieve_tip(p300, currentip) if (mixReagent==True) and (index==0 or index==2 or index==5): #If the reagent is to be mixed, and we are in column 1, 3 or 6, mix it. We mix three times to make sure we dont have differences protocol.comment("Mixing %s" % reagentName) well_mix(vol=beadsMixing, loc=beads, reps=beadsMixRepeats, height=beadsHeight, moveSide=0) #We only do this with magnetic beads, that's why we use those variable names p300.blow_out(beads.top()) tvol = vol while tvol > tipVolume: p300.dispense(20, src.top() ) p300.transfer(tipVolume, src.bottom().move(types.Point(x=0, y=0, z=bottomHeight)), to.top(topOffset), new_tip="never", air_gap=extraVol) protocol.delay(seconds=2) p300.blow_out() tvol -= tipVolume p300.dispense(20, src.top() ) p300.transfer(tvol,src.bottom().move(types.Point(x=0, y=0, z=bottomHeight)), to.center(), new_tip="never", air_gap=extraVol) protocol.delay(seconds=2) well_mix(vol=mixVol, loc=to, reps=repeats, moveSide=moveSide, height=altura) remove_tip(pipette, currentip) #Incubation if magnetTime==True: protocol.comment("Engaging magnet") magneto.engage(height=magnetHeight) protocol.comment("Incubating for %s minutes" % incubationTime) clock(time=incubationTime)
def run(protocol): # load labware [tip1, tip2, tip3, tip4, tip5] = [ protocol.load_labware( 'opentrons_96_filtertiprack_200ul', s) for s in [ '1', '4', '7', '10', '9']] tips = [tip1, tip2, tip3, tip4] usedtips = [ well for row in [ tip5, tip1, tip2, tip3] for well in row.rows()[0]] tuberacks = [protocol.load_labware( 'biobank_96_tuberack_1ml', str(s)) for s in range(2, 12, 3)] deepplate = protocol.load_labware('nest_96_wellplate_2ml_deep', '3') p300 = protocol.load_instrument('p300_multi_gen2', 'left', tip_racks=tips) tubewells = [well for plate in tuberacks for well in plate.rows()[0]][:NUM_COLS] #p300.default_speed = 400 #400 is default #p300.flow_rate.aspirate = 50 #300 is default #Controls Gantry-Speed ('A' Right, 'Z' Left) rsvr_hts = [18, 18] x = 0 for idx, (src, utip) in enumerate(zip(tubewells, usedtips)): p300.pick_up_tip() for i in range(1): protocol.max_speeds['Z'] = 50 #125 default p300.aspirate(100, src.bottom(rsvr_hts[x % 2])) protocol.delay(seconds=2) p300.move_to(src.top().move(types.Point(x=0, y=0, z=-4))) p300.move_to(src.top().move(types.Point(x=3.75, y=0, z=-4))) p300.move_to(src.top().move(types.Point(x=0, y=0, z=-4))) p300.move_to(src.top().move(types.Point(x=0, y=0, z=-4))) p300.move_to(src.top().move(types.Point(x=-3.75, y=0, z=-4))) p300.move_to(src.top().move(types.Point(x=0, y=0, z=-4))) protocol.delay(seconds=2) protocol.max_speeds['Z'] = 125 #125 default p300.dispense(200, deepplate.rows()[0][idx % 12].bottom(2)) p300.blow_out(deepplate.rows()[0][idx % 12].bottom(2)) p300.move_to(deepplate.rows()[0][idx % 12].top().move(types.Point(x=0, y=0, z=-4))) p300.move_to(deepplate.rows()[0][idx % 12].top().move(types.Point(x=3.6, y=0, z=-4))) p300.move_to(deepplate.rows()[0][idx % 12].top().move(types.Point(x=0, y=0, z=-4))) x += 1 p300.drop_tip(utip)
def show_or_exit(key): message.set_text("") global movement_distance if key in movement_distances.keys(): set_movement_distance(movement_distances[key]) if key in ('h', 'H'): protocol.home() if key in ('q', 'Q'): raise urwid.ExitMainLoop if key in ('s', 'S'): save_offset() if key in ('k', 'K') and movement_distance != "slot": set_movement_distance(min(movement_distance, 50)) move_in_direction(types.Point(0, 0, 1)) if key in ('m', 'M') and movement_distance != "slot": set_movement_distance(min(movement_distance, 50)) move_in_direction(types.Point(0, 0, -1)) if key == "up": move_in_direction(types.Point(0, 1, 0)) if key == "down": move_in_direction(types.Point(0, -1, 0)) if key == "left": move_in_direction(types.Point(-1, 0, 0)) if key == "right": move_in_direction(types.Point(1, 0, 0))
def well_mix(vol, loc, repsdown=mixdownReps, repsmovement=mixMovementReps, yOffset=0.75, height=generalHeight, moveSide=0, bottomHeight=bottomMixHeight): """ Aspirates <vol> from bottom of well and dispenses it from <height> <reps> times loc1 is a position at 0.3mm over the bottom of the well loc2 is a position in the same x and y posiiton than loc1, but at <height>mm over the bottom of the well The idea here is to take liquid to the very bottom and pour it from a higher point, to mix things """ p300.flow_rate.aspirate = 1000 p300.flow_rate.dispense = 1000 for _ in range(repsdown): p300.aspirate( vol, loc.bottom().move( types.Point(x=0 + moveSide, y=yOffset, z=bottomHeight))) p300.dispense( vol, loc.bottom().move( types.Point(x=0 + moveSide, y=yOffset, z=bottomHeight))) yOffset = -yOffset for _ in range(repsmovement): p300.aspirate( vol, loc.bottom().move( types.Point(x=0 + moveSide, y=yOffset, z=bottomHeight))) yOffset = -yOffset p300.dispense( vol, loc.bottom().move( types.Point(x=0 + moveSide, y=yOffset, z=height))) p300.dispense(20, loc.top(topOffset)) p300.flow_rate.aspirate = 50 p300.flow_rate.dispense = 150
async def test_move_currents(smoothie, monkeypatch, loop): smoothie.simulating = False hardware_api = await hc.API.build_hardware_controller(loop=loop) mock_active_axes = mock.Mock() monkeypatch.setattr(hardware_api._backend._smoothie_driver, 'activate_axes', mock_active_axes) mount = PipettePair.PRIMARY_RIGHT await hardware_api.home() mock_active_axes.reset_mock() await hardware_api.move_to(mount, types.Point(0, 0, 0)) expected_call_list = [mock.call('XYAZ')] assert mock_active_axes.call_args_list == expected_call_list
def run(protocol: protocol_api.ProtocolContext): """Function to change the gantry speed of the robot.""" #loading labware (from opentrons labware library) plate = protocol.load_labware('biorad_96_wellplate_200ul_pcr', 1, '96plate') tiprack_1 = protocol.load_labware('opentrons_96_tiprack_300ul', 2, '300tips') #load pipette p300 = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[tiprack_1]) #transfer 100ul from plate well A1 to plate well B1 p300.transfer(100, plate['A1'], plate['B1']) #move to 50 mm above front left of slot 5, very quickly p300.move_to(protocol.deck.position_for('5').move(types.Point(z=50))) #slow down pipette p300.default_speed = 100 #move to 50 mm above front left of slot 9, much more slowly p300.move_to(protocol.deck.position_for('9').move(types.Point(z=50)))
async def test_load_labware_to_preparing_second_pipette( check_calibration_session): sess = await in_preparing_second_pipette(check_calibration_session) tip_pt = sess._moves.preparingSecondPipette.position curr_pos = await sess.hardware.gantry_position( sess._get_pipette_by_rank(session.PipetteRank.second).mount) assert curr_pos == tip_pt - types.Point(0, 0, 10) assert check_calibration_session.current_state.name == \ session.CalibrationCheckState.preparingSecondPipette await check_calibration_session.trigger_transition( session.CalibrationCheckTrigger.jog, OK_DIFF_VECTOR) assert check_calibration_session.current_state.name == \ session.CalibrationCheckState.preparingSecondPipette
def __init__(self, load_name='ot2_standard'): super().__init__() row_offset = 90.5 col_offset = 132.5 for idx in range(1, 13): self.data[idx] = None self._positions = { idx + 1: types.Point((idx % 3) * col_offset, idx // 3 * row_offset, 0) for idx in range(12) } self._highest_z = 0.0 self._definition = load_deck(load_name, 2) self._load_fixtures()
def remove_supernatant(vol, src, side): m300.flow_rate.aspirate = 20 m300.aspirate(10, src.top()) while vol > tipMax: m300.aspirate(tipMax, src.bottom().move(types.Point(x=side, y=0, z=0.5))) # wait for a moment to allow outer drips to fall above liquid m300.move_to(src.top(-6)) protocol.delay(seconds=1) # flick to the side m300.move_to(src.top(-6).move(types.Point(x=2, y=0, z=0))) m300.move_to(src.top(-6).move(types.Point(x=0, y=0, z=0))) m300.dispense(tipMax + 10, waste) m300.aspirate(10, waste) vol -= tipMax m300.aspirate(10, src.top()) m300.aspirate((vol + 10), src.bottom().move(types.Point(x=side, y=0, z=0.5))) m300.move_to(src.top(-6)) protocol.delay(seconds=1) m300.dispense((vol + 20), waste) m300.flow_rate.aspirate = 50
async def test_comparing_first_pipette_point_two_to_jogging_point_three( check_calibration_session): sess = await in_jogging_first_pipette_to_point_three( check_calibration_session) tip_pt = sess._moves.joggingFirstPipetteToPointThree.position curr_pos = await sess.hardware.gantry_position( sess._get_pipette_by_rank(session.PipetteRank.first).mount) assert curr_pos == tip_pt + types.Point(0, 0, 5.3) assert check_calibration_session.current_state.name == \ session.CalibrationCheckState.joggingFirstPipetteToPointThree await check_calibration_session.trigger_transition( session.CalibrationCheckTrigger.jog, OK_DIFF_VECTOR) assert check_calibration_session.current_state.name == \ session.CalibrationCheckState.joggingFirstPipetteToPointThree
def __init__(self): super().__init__() row_offset = 90.5 col_offset = 132.5 for idx in range(1, 13): self.data[idx] = None self._positions = { idx + 1: types.Point((idx % 3) * col_offset, idx // 3 * row_offset, 0) for idx in range(12) } self._highest_z = 0.0 # TODO: support deck loadName as a param self._definition = load('ot2_standard', 2)
def probe(self, move_after) -> str: hw = self.hardware mount = self._current_mount probe_center = hw.locate_tip_probe_center(mount) _, _, cz = position(mount, hw, CriticalPoint.TIP) # work around to prevent pipette tip crashing into tip box # when moving from tip box -> other point on the deck pt = types.Point(x=move_after[0], y=move_after[1], z=cz) hw.move_to(mount, pt) log.debug("Setting probe center to {}".format(probe_center)) hw.update_config(tip_probe=hw.config.tip_probe._replace( center=probe_center)) return 'Tip probe'
async def test_save_xy(async_server, dc_session): hardware = dc_session.adapter version = async_server['api_version'] if version == 1: mount = 'left' hardware.reset() pip = instruments.P10_Single(mount=mount) else: mount = types.Mount.LEFT hardware.reset() hardware.cache_instruments({ mount: 'p10_single_v1', types.Mount.RIGHT: None }) pip = hardware.attached_instruments[mount] dc_session.pipettes = {mount: pip} dc_session.current_mount = mount dc_session.tip_length = 25 if version == 1: dc_session.pipettes.get(mount)._add_tip(dc_session.tip_length) hardware.home() else: dc_session.pipettes.get(mount)['has_tip'] = True dc_session.pipettes.get(mount)['tip_length'] = dc_session.tip_length hardware.add_tip(types.Mount.LEFT, dc_session.tip_length) hardware.home() x = 100 y = 101 if version == 1: dc_session.pipettes.get(mount).move_to((hardware.deck, (x, y, 102))) else: # relative move or not? hardware.move_to(types.Mount.LEFT, types.Point(x=x, y=y, z=102)) point = '1' data = {'point': point} await endpoints.save_xy(data) actual = dc_session.points[point] if version == 1: expected = (robot._driver.position['X'] + hardware.config.mount_offset[0], robot._driver.position['Y']) else: coordinates = hardware.gantry_position(types.Mount.LEFT) expected = (coordinates.x, coordinates.y) assert actual == expected
def run(protocol): [piptype, pipmnt, num_plates] = get_values( # noqa: F821 'piptype', 'pipmnt', 'num_plates') # load labware and pipettes pip_name, tip_name = piptype.split() tips = protocol.load_labware(tip_name, '10') pip = protocol.load_instrument(pip_name, pipmnt, tip_racks=[tips]) res = protocol.load_labware('nest_12_reservoir_15ml', '11') mm1 = [res['A1']] * 5 + [res['A2']] * 4 num_plates += 1 plates = [ protocol.load_labware('nest_96_wellplate_100ul_pcr_full_skirt', s) for s in range(1, num_plates) ] # max_vol = 15 if pip_name == 'p20_multi_gen2' else 180 # distribute 10ul of QE pip.pick_up_tip() for plate, mm, r in zip(plates, mm1, range(1, 10)): wells = plate.rows()[0] disp_vol = 12 protocol.comment(f'Distributing 10ul to plate {r}...') for well in wells: pip.aspirate(10, mm) protocol.max_speeds['X'] = 25 pip.move_to(mm.top().move(types.Point(x=3.5, y=0, z=-4))) pip.move_to(mm.top().move(types.Point(x=-3.5, y=0, z=-2))) protocol.max_speeds['X'] = None pip.dispense(disp_vol, well) pip.blow_out(well) pip.aspirate(2, well.top()) pip.drop_tip() protocol.comment('Protocol complete.')
def __init__(self): super().__init__() row_offset = 90.5 col_offset = 132.5 for idx in range(1, 13): self.data[idx] = None self._positions = { idx + 1: types.Point((idx % 3) * col_offset, idx // 3 * row_offset, 0) for idx in range(12) } self._highest_z = 0.0 # TODO: support deck loadName as a param def_path = 'deck/definitions/2/ot2_standard.json' self._definition = json.loads(load_shared_data(def_path))
def remove_sup(pip, vol_sup): pip.pick_up_or_refill() # offset to left to avoid beads (odd col numbers) if index % 2 != 1: f = -1 # offset to right to avoid beads (even col numbers) else: f = 1 pip.aspirate(vol_sup, column[0].bottom(4), rate=0.3) pip.aspirate(vol_sup, column[0].bottom(1).move( types.Point(x=f * x_offset_bead_pellet, y=0, z=0)), rate=0.3) column[0].current_volume = 0 column[0].height = column[0].min_height
async def test_deck_cal_applied(monkeypatch, loop): new_gantry_cal = [[1, 0, 0, 10], [0, 1, 0, 20], [0, 0, 1, 30], [0, 0, 0, 1]] called_with = None def mock_move(position, speed=None, home_flagged_axes=True): nonlocal called_with called_with = position hardware_api = hc.API.build_hardware_simulator(loop=loop) monkeypatch.setattr(hardware_api._backend, 'move', mock_move) old_config = await hardware_api.config hardware_api._config = old_config._replace( gantry_calibration=new_gantry_cal) await hardware_api.home() await hardware_api.move_to(types.Mount.RIGHT, types.Point(0, 0, 0)) assert called_with['X'] == 10 assert called_with['Y'] == 20 assert called_with['A'] == 30 # Check that mount offset is also applied await hardware_api.move_to(types.Mount.LEFT, types.Point(0, 0, 0)) assert called_with['X'] == 44 assert called_with['Y'] == 20 assert called_with['Z'] == 30
def eth_wash(src, tips, waste, keeptips): p300.pick_up_tip(tips200[tips]) p300.flow_rate.aspirate = 50 p300.flow_rate.dispense = 30 for _ in range(3): p300.transfer(200, src, magsamps.top().move(types.Point(x=-1, y=0, z=-3)), new_tip='never') p300.blow_out(magsamps.top(-3)) # p300.touch_tip() # p300.return_tip() # p300.pick_up_tip(tips200[tips]) p300.flow_rate.aspirate = 30 p300.flow_rate.dispense = 150 for _ in range(3): p300.transfer(210, magsamps.bottom().move(types.Point(x=-1, y=0, z=0.5)), waste, new_tip='never') if not keeptips: p300.drop_tip()
async def test_save_z(async_server, dc_session, monkeypatch): hardware = dc_session.adapter model = 'p10_single_v1' # Z values were bleeding in from other tests, mock robot configs # to encapsulate this test fake_config = robot_configs.load() monkeypatch.setattr(hardware, 'config', fake_config) if async_server['api_version'] == 1: mount = 'left' hardware.reset() pip = instruments.P10_Single(mount=mount) else: mount = types.Mount.LEFT hardware.reset() hardware.cache_instruments({ mount: 'p10_single_v1', types.Mount.RIGHT: None }) pip = hardware.attached_instruments[mount] dc_session.pipettes = {mount: pip} dc_session.current_mount = mount dc_session.current_model = model dc_session.tip_length = 25 if async_server['api_version'] == 1: dc_session.pipettes.get(mount)._add_tip(dc_session.tip_length) else: dc_session.pipettes.get(mount)['has_tip'] = True dc_session.pipettes.get(mount)['tip_length'] = dc_session.tip_length z_target = 80.0 if async_server['api_version'] == 1: hardware.home() dc_session.pipettes.get(mount).move_to( (hardware.deck, (0, 0, z_target))) else: hardware.home() # Unsure whether to use move_to or move_rel hardware.move_to(types.Mount.LEFT, types.Point(x=0, y=0, z=z_target)) await endpoints.save_z({}) new_z = dc_session.z_value expected_z = z_target assert new_z == expected_z
async def test_drop_tip(dummy_instruments, loop, is_robot, toggle_new_calibration): hw_api = await hc.API.build_hardware_simulator( attached_instruments=dummy_instruments, loop=loop) mount = PipettePair.PRIMARY_RIGHT await hw_api.home() await hw_api.cache_instruments() tip_position = types.Point(12.13, 9, 150) await hw_api.move_to(mount, tip_position) tip_length = 25.0 await hw_api.pick_up_tip(mount, tip_length) await hw_api.drop_tip(mount) assert not hw_api._attached_instruments[mount.primary].has_tip assert hw_api._attached_instruments[mount.primary].current_volume == 0 assert not hw_api._attached_instruments[mount.secondary].has_tip assert hw_api._attached_instruments[mount.secondary].current_volume == 0