async def save_z(data) -> CommandResult: """ Save the current Z height value for the calibration data :param data: unused """ if not session_wrapper.session: raise NoSessionInProgress() if not session_wrapper.session.tip_length: message = "Tip length must be set before calibrating" status = False else: session_wrapper.session.z_value = position( session_wrapper.session.current_mount, session_wrapper.session.adapter, session_wrapper.session.cp)[-1] session_wrapper.session.current_transform[2][3] =\ session_wrapper.session.z_value session_wrapper.session.adapter.update_config( gantry_calibration=list( list(i) for i in session_wrapper.session.current_transform ) ) message = "Saved z: {}".format(session_wrapper.session.z_value) status = True return CommandResult(success=status, message=message)
async def save_xy(data) -> CommandResult: """ Save the current XY values for the calibration data :param data: a dict with schema: { 'point': a string ID ['1', '2', or '3'] of the calibration point to save } """ if not session_wrapper.session: raise NoSessionInProgress() valid_points = list(session_wrapper.session.points.keys()) point = data.get('point') if point not in valid_points: message = 'point must be one of {}'.format(valid_points) status = False elif not session_wrapper.session.current_mount: message = "Mount must be set before calibrating" status = False else: x, y, _ = position( session_wrapper.session.current_mount, session_wrapper.session.adapter, session_wrapper.session.cp) session_wrapper.session.points[point] = (x, y) message = "Saved point {} value: {}".format( point, session_wrapper.session.points[point]) status = True return CommandResult(success=status, message=message)
async def save_xy(data): """ Save the current XY values for the calibration data :param data: Information obtained from a POST request. The content type is application/json. The correct packet form should be as follows: { 'token': UUID token from current session start 'command': 'save xy' 'point': a string ID ['1', '2', or '3'] of the calibration point to save } """ valid_points = list(session_wrapper.session.points.keys()) point = data.get('point') if point not in valid_points: message = 'point must be one of {}'.format(valid_points) status = 400 elif not session_wrapper.session.current_mount: message = "Mount must be set before calibrating" status = 400 else: if not feature_flags.use_protocol_api_v2(): mount = 'Z' if session_wrapper.session.current_mount == 'left'\ else 'A' x, y, _ = position(mount, session_wrapper.session.adapter) if session_wrapper.session.pipettes[ session_wrapper.session.current_mount].channels != 1: # See note in `move` y = y - pipette_config.Y_OFFSET_MULTI if session_wrapper.session.current_mount == 'left': dx, dy, _ = session_wrapper.session.adapter.config.mount_offset x = x + dx y = y + dy else: x, y, _ = position( session_wrapper.session.current_mount, session_wrapper.session.adapter, session_wrapper.session.cp) session_wrapper.session.points[point] = (x, y) message = "Saved point {} value: {}".format( point, session_wrapper.session.points[point]) status = 200 return web.json_response({'message': message}, status=status)
async def save_xy(data) -> CommandResult: """ Save the current XY values for the calibration data :param data: a dict with schema: { 'point': a string ID ['1', '2', or '3'] of the calibration point to save } """ if not session_wrapper.session: raise NoSessionInProgress() valid_points = list(session_wrapper.session.points.keys()) point = data.get('point') if point not in valid_points: message = 'point must be one of {}'.format(valid_points) status = False elif not session_wrapper.session.current_mount: message = "Mount must be set before calibrating" status = False else: if not feature_flags.use_protocol_api_v2(): mount = 'Z' if session_wrapper.session.current_mount == 'left'\ else 'A' x, y, _ = position(mount, session_wrapper.session.adapter) if session_wrapper.session.pipettes[ session_wrapper.session.current_mount].channels != 1: # See note in `move` y = y - pipette_config.Y_OFFSET_MULTI if session_wrapper.session.current_mount == 'left': dx, dy, _ = session_wrapper.session.adapter.config.mount_offset x = x + dx y = y + dy else: x, y, _ = position(session_wrapper.session.current_mount, session_wrapper.session.adapter, session_wrapper.session.cp) session_wrapper.session.points[point] = (x, y) message = "Saved point {} value: {}".format( point, session_wrapper.session.points[point]) status = True return CommandResult(success=status, message=message)
async def save_z(data): """ Save the current Z height value for the calibration data :param data: Information obtained from a POST request. The content type is application/json. The correct packet form should be as follows: { 'token': UUID token from current session start 'command': 'save z' } """ if not session_wrapper.session.tip_length: message = "Tip length must be set before calibrating" status = 400 else: if not feature_flags.use_protocol_api_v2(): mount = 'Z' if session_wrapper.session.current_mount == 'left' \ else 'A' actual_z = position( mount, session_wrapper.session.adapter)[-1] length_offset = pipette_config.load( session_wrapper.session.current_model, session_wrapper.session.pipette_id).model_offset[-1] session_wrapper.session.z_value =\ actual_z - session_wrapper.session.tip_length + length_offset else: session_wrapper.session.z_value = position( session_wrapper.session.current_mount, session_wrapper.session.adapter, session_wrapper.session.cp)[-1] session_wrapper.session.current_transform[2][3] =\ session_wrapper.session.z_value session_wrapper.session.adapter.update_config( gantry_calibration=list( list(i) for i in session_wrapper.session.current_transform ) ) message = "Saved z: {}".format(session_wrapper.session.z_value) status = 200 return web.json_response({'message': message}, status=status)
async def test_set_and_jog_integration( async_client, async_server, monkeypatch): """ Test that the jog function works. Note that in order for the jog function to work, the following must be done: 1. Create a session manager Then jog requests will work as expected. """ test_model = 'p300_multi_v1' hardware = async_server['com.opentrons.hardware'] # Why does this need to be awaited for a synch adapter await hardware.cache_instruments( {types.Mount.LEFT: None, types.Mount.RIGHT: test_model}) dummy_token = 'Test Token' def uuid_mock(): return dummy_token monkeypatch.setattr(endpoints, '_get_uuid', uuid_mock) token_res = await async_client.post('/calibration/deck/start') assert token_res.status == 201, token_res token_text = await token_res.json() token = token_text['token'] axis = 'z' direction = 1 step = 3 # left pipette z carriage motor is smoothie axis "Z", right is "A" sess = dc.endpoints.session sess.adapter.home() prior_x, prior_y, prior_z = dc.position( sess.current_mount, sess.adapter, sess.cp) resp = await async_client.post( '/calibration/deck', json={ 'token': token, 'command': 'jog', 'axis': axis, 'direction': direction, 'step': step }) body = await resp.json() msg = body.get('message') assert '{}'.format((prior_x, prior_y, prior_z + step)) in msg
async def save_z(data) -> CommandResult: """ Save the current Z height value for the calibration data :param data: unused """ if not session_wrapper.session: raise NoSessionInProgress() if not session_wrapper.session.tip_length: message = "Tip length must be set before calibrating" status = False else: if not feature_flags.use_protocol_api_v2(): mount = 'Z' if session_wrapper.session.current_mount == 'left' \ else 'A' actual_z = position(mount, session_wrapper.session.adapter)[-1] length_offset = pipette_config.load( session_wrapper.session.current_model, session_wrapper.session.pipette_id).model_offset[-1] session_wrapper.session.z_value =\ actual_z - session_wrapper.session.tip_length + length_offset else: session_wrapper.session.z_value = position( session_wrapper.session.current_mount, session_wrapper.session.adapter, session_wrapper.session.cp)[-1] session_wrapper.session.current_transform[2][3] =\ session_wrapper.session.z_value session_wrapper.session.adapter.update_config(gantry_calibration=list( list(i) for i in session_wrapper.session.current_transform)) message = "Saved z: {}".format(session_wrapper.session.z_value) status = True return CommandResult(success=status, message=message)
async def test_set_and_jog_integration(async_client, monkeypatch): """ Test that the jog function works. Note that in order for the jog function to work, the following must be done: 1. Create a session manager Then jog requests will work as expected. """ test_model = 'p300_multi_v1' def dummy_read_model(mount): return test_model monkeypatch.setattr(robot._driver, 'read_pipette_model', dummy_read_model) robot.reset() dummy_token = 'Test Token' def uuid_mock(): return dummy_token monkeypatch.setattr(endpoints, '_get_uuid', uuid_mock) token_res = await async_client.post('/calibration/deck/start') token_text = await token_res.json() token = token_text['token'] axis = 'z' direction = 1 step = 3 # left pipette z carriage motor is smoothie axis "Z", right is "A" sess = dc.endpoints.session smoothie_axis = 'Z' if sess.current_mount == 'left' else 'A' robot.reset() prior_x, prior_y, prior_z = dc.position(smoothie_axis) resp = await async_client.post('/calibration/deck', json={ 'token': token, 'command': 'jog', 'axis': axis, 'direction': direction, 'step': step }) body = await resp.json() msg = body.get('message') assert '{}'.format((prior_x, prior_y, prior_z + step)) in msg
async def save_z(data): """ Save the current Z height value for the calibration data :param data: Information obtained from a POST request. The content type is application/json. The correct packet form should be as follows: { 'token': UUID token from current session start 'command': 'save z' } """ if not session.tip_length: message = "Tip length must be set before calibrating" status = 400 else: actual_z = position(session.current_mount)[-1] length_offset = pipette_config.load( session.current_model).model_offset[-1] session.z_value = actual_z - session.tip_length + length_offset message = "Saved z: {}".format(session.z_value) status = 200 return web.json_response({'message': message}, status=status)
async def move(data) -> CommandResult: """ Allow the user to move the selected pipette to a specific point :param data: a dict with schema: { 'point': The name of the point to move to. Must be one of ["1", "2", "3", "safeZ", "attachTip"] } :return: The position you are moving to """ if not session_wrapper.session: raise NoSessionInProgress() point_name = data.get('point') point = safe_points().get(str(point_name)) if point and len(point) == 3: if not feature_flags.use_protocol_api_v2(): pipette = session_wrapper.session.pipettes[ session_wrapper.session.current_mount] channels = pipette.channels # For multichannel pipettes in the V1 session, we use the tip closest # to the front of the robot rather than the back (this is the tip that # would go into well H1 of a plate when pipetting from the first row of # a 96 well plate, for instance). Since moves are issued for the A1 tip # we have to adjust the target point by 2 * Y_OFFSET_MULTI (where the # offset value is the distance from the axial center of the pipette to # the A1 tip). By sending the A1 tip to to the adjusted target, the H1 # tip should go to the desired point. Y_OFFSET_MULT must then be backed # out of xy positions saved in the `save_xy` handler # (not 2 * Y_OFFSET_MULTI, because the axial center of the pipette # will only be off by 1* Y_OFFSET_MULTI). if not channels == 1: x = point[0] y = point[1] + pipette_config.Y_OFFSET_MULTI * 2 z = point[2] point = (x, y, z) # hack: z=150mm is not a safe point for a gen2 pipette with a tip # attached, since their home location is z=+172mm and both 300ul # and 1000ul tips are more than 22mm long. This isn't an issue for # apiv2 because it can select the NOZZLE critical point. if pipette.tip_attached and point_name == 'attachTip': point = (point[0], point[1], point[2] - pipette._tip_length) pipette.move_to((session_wrapper.session.adapter.deck, point), strategy='arc') else: if not point_name == 'attachTip': intermediate_pos = position( session_wrapper.session.current_mount, session_wrapper.session.adapter, session_wrapper.session.cp) session_wrapper.session.adapter.move_to( session_wrapper.session.current_mount, Point(x=intermediate_pos[0], y=intermediate_pos[1], z=session_wrapper.session.tip_length), critical_point=session_wrapper.session.cp) session_wrapper.session.adapter.move_to( session_wrapper.session.current_mount, Point(x=point[0], y=point[1], z=session_wrapper.session.tip_length), critical_point=session_wrapper.session.cp) session_wrapper.session.adapter.move_to( session_wrapper.session.current_mount, Point(x=point[0], y=point[1], z=point[2]), critical_point=session_wrapper.session.cp) else: if session_wrapper.session.cp == CriticalPoint.TIP: session_wrapper.session.cp = CriticalPoint.NOZZLE session_wrapper.session.adapter.move_to( session_wrapper.session.current_mount, Point(x=point[0], y=point[1], z=point[2]), critical_point=session_wrapper.session.cp) message = 'Moved to {}'.format(point) status = True else: message = '"point" must be one of "1", "2", "3", "safeZ", "attachTip"' status = False return CommandResult(success=status, message=message)