Determine refractive index and radius using Canny edge detection

    Compute the refractive index of a spherical phase object by
    detection of an edge in the phase image, a subsequent circle
    fit to the edge, and finally a weighted average over the phase
    image assuming a parabolic phase profile.

    Parameters
    ----------
    qpi: QPImage
        Quantitative phase image information
    r0: float
        Approximate radius of the sphere [m]
    edgekw: dict
        Additional keyword arguments for :func:`contour_canny`
    ret_center: bool
        Return the center coordinate of the sphere

    Returns
    -------
    n: float
        Computed refractive index
    r: float
        Computed radius [m]
    center: tuple of floats
        Center position of the sphere [px], only returned
        if `ret_center` is `True`

def analyze(qpi, r0, edgekw={}, ret_center=False, ret_edge=False):
    """Determine refractive index and radius using Canny edge detection

    Compute the refractive index of a spherical phase object by
    detection of an edge in the phase image, a subsequent circle
    fit to the edge, and finally a weighted average over the phase
    image assuming a parabolic phase profile.

    Parameters
    ----------
    qpi: QPImage
        Quantitative phase image information
    r0: float
        Approximate radius of the sphere [m]
    edgekw: dict
        Additional keyword arguments for :func:`contour_canny`
    ret_center: bool
        Return the center coordinate of the sphere

    Returns
    -------
    n: float
        Computed refractive index
    r: float
        Computed radius [m]
    center: tuple of floats
        Center position of the sphere [px], only returned
        if `ret_center` is `True`
    """
    nmed = qpi["medium index"]
    px_m = qpi["pixel size"]
    wl_m = qpi["wavelength"]
    px_wl = px_m / wl_m

    phase = qpi.pha
    # determine edge
    edge = contour_canny(image=phase,
                         radius=r0 / px_m,
                         verbose=False,
                         **edgekw,
                         )
    # fit circle to edge
    center, r = circle_fit(edge)
    # compute average phase density
    avg_phase = average_sphere(phase, center, r)
    # convert phase average to refractive index
    n = nmed + avg_phase / (2 * np.pi * px_wl)
    # convert radius from pixels to meters
    ret = [n, r * px_m]
    if ret_center:
        ret.append(center)
    if ret_edge:
        ret.append(edge)
    return ret