Ejemplo n.º 1
0
def split_areas(u, tck, z, xs, ps, a):
    """
    Find the areas of the parent and nascent daughter cells.

    args:
        u (ndarray): 1D array giving paramaterization of the spline
        z (ndarray): coordinates of division plane on midline
        tck (list): spline representation of border
        xs (ndarray): coordinates along the border
        ps (ndarray): coordinates of cell poles
        a (float): area of the entire cell

    returns:
        ao (float): area of the parent cell
        an (float): area of the daughter cell

    """

    # Split the border into two contours, one for each new cell
    uo, un = splitborder(u, xs, z)

    # Identify the contours with the old and new cells
    xso = np.asarray(zip(*splev(uo, tck)))
    xsn = np.asarray(zip(*splev(un, tck)))

    # Verify the identifications
    po, pn = ps
    do = np.min([norm(po - v) for v in xso])
    dn = np.min([norm(pn - v) for v in xso])
    if dn < do:
        xso, xsn = xsn, xso

    # Make new periodic splines for each cell
    tcko = makebspline(xso, 0., True)[0]
    tckn = makebspline(xsn, 0., True)[0]

    # Return the area of each cell
    ao = splineprops(u, tcko, ('Area', ))['Area']
    an = splineprops(u, tckn, ('Area', ))['Area']

    # Scale the results to be commensurate with the full area
    f = a / (ao + an)
    return f * ao, f * an
def split_areas(u, tck, z, xs, ps, a):
    """
    Find the areas of the parent and nascent daughter cells.

    args:
        u (ndarray): 1D array giving paramaterization of the spline
        z (ndarray): coordinates of division plane on midline
        tck (list): spline representation of border
        xs (ndarray): coordinates along the border
        ps (ndarray): coordinates of cell poles
        a (float): area of the entire cell

    returns:
        ao (float): area of the parent cell
        an (float): area of the daughter cell

    """

    # Split the border into two contours, one for each new cell
    uo, un = splitborder(u, xs, z)

    # Identify the contours with the old and new cells
    xso = np.asarray(zip(*splev(uo, tck)))
    xsn = np.asarray(zip(*splev(un, tck)))

    # Verify the identifications
    po, pn = ps
    do = np.min([norm(po - v) for v in xso])
    dn = np.min([norm(pn - v) for v in xso])
    if dn < do:
        xso, xsn = xsn, xso

    # Make new periodic splines for each cell
    tcko = makebspline(xso, 0.0, True)[0]
    tckn = makebspline(xsn, 0.0, True)[0]

    # Return the area of each cell
    ao = splineprops(u, tcko, ("Area",))["Area"]
    an = splineprops(u, tckn, ("Area",))["Area"]

    # Scale the results to be commensurate with the full area
    f = a / (ao + an)
    return f * ao, f * an
Ejemplo n.º 3
0
def get_width_profile_new(s, num_points=500):
    """
    Get the width profile and associated variables with a recalculated midline.

    args:
        s (Series): data read in from file for a single frame

    returns:
        d (dict): calculated values

    """

    # Evaluate the midline at discrete points starting at the old pole
    u = np.linspace(0., 1., num_points)

    d = {
        'Radius': np.nan,
        'RadiusStalked': np.nan,
        'RadiusSwarmer': np.nan,
        'Widths': np.empty(0),
        'WidthMin': np.nan,
        'WidthStalkedMax': np.nan,
        'WidthSwarmerMax': np.nan,
        'WidthStalkedMin': np.nan,
        'WidthSwarmerMin': np.nan,
        'Area': np.nan,
        'AreaStalked': np.nan,
        'AreaSwarmer': np.nan,
        'Length': np.nan,
        'LengthStalked': np.nan,
        'LengthSwarmer': np.nan,
        'LengthStalkedMin': np.nan,
        'LengthSwarmerMin': np.nan,
        'MidSpline': []
    }
    try:
        # Get coordinates and first derivative of contour
        tck = s['EdgeSpline']
        es = np.asarray(zip(*splev(u, tck)))
        des = np.asarray(zip(*splev(u, tck, der=1)))

        # Find a crude approximation of the cell poles
        ps = (s['StalkedPole'], s['SwarmerPole'])

        # Approximate the midline by taking the Voronoi diagram
        vs = find_midline(es)

        # Prune the Voronoi diagram to remove branch points
        cs0 = prune_midline(es, des, vs)

        # Reorient the midline from stalked to swarmer pole
        cs1 = orient_midline(es, cs0, ps)

        # Find approximate width along the medial axis
        ws1 = get_width(es, cs1[:-1], np.diff(cs1, axis=0))

        # Find the radius of curvature of the entire cell
        cre0 = fit_circle(cs1)

        # Get the minimum cell width
        j1_min, w1_min = find_min_width(ws1)
        if np.any(j1_min):
            # Split contours according to minimum cell width
            wso1, wsn1 = ws1[:j1_min], ws1[j1_min:]

            # Find the maximum widths of either side
            jo1_max, wo1_max = find_max_width(wso1)
            jn1_max, wn1_max = find_max_width(wsn1)

            # Only keep exterior points within 98% of maximum width
            ko1_max = np.flatnonzero(wso1[jo1_max:] > wo1_max * 0.75)
            ko1 = np.hstack((range(jo1_max), jo1_max + ko1_max))
            kn1_max = np.flatnonzero(wsn1[:jn1_max] > wn1_max * 0.75)
            kn1 = np.hstack((kn1_max, range(jn1_max, len(wsn1))))

            # Fit circles to either cell
            cre1 = fit_circle(cs1[ko1])
            cre2 = fit_circle(cs1[j1_min + kn1])
        else:
            cre1, cre2, = cre0, cre0

        # Extend the midline in a way that maintains curvature
        cs2 = extend_midline(es, cs1, (cre1[:2], cre2[:2]), ps)

        # Spline the new midline
        tck4 = makebspline(cs2, smoothing=0.1)[0]
        d['MidSpline'] = tck4
        cs4 = np.asarray(zip(*splev(u, tck4)))
        dcs4 = np.asarray(zip(*splev(u, tck4, der=1)))

        # Get the correct cell poles
        po, pn = cs4[0], cs4[-1]

        # Get the index of the stalked pole
        jo = np.argmin(np.sum((es - po)**2, axis=1))

        # Overall cell area and length
        a = splineprops(u, tck, 'Area')['Area']
        d['Area'] = a
        l = splineprops(u, tck4, 'Length')['Length']
        d['Length'] = l

        # Fit best-fit circle to entire cell
        cre0 = fit_circle(cs4)
        d['Radius'] = cre0[1]

        # Get the cell width and minimum and maximum cell widths
        ws4 = get_width(es, cs4, dcs4)
        d['Widths'] = ws4
        j4_min, w_min = find_min_width(ws4)
        d['WidthMin'] = w_min
        if np.any(j4_min):
            # Split contours according to minimum cell width
            wso4, wsn4 = ws4[:j4_min], ws4[j4_min:]

            # Find the maximum widths of either side
            jo4_max, wo_max = find_max_width(wso4)
            jn4_max, wn_max = find_max_width(wsn4)

            # Find the minimum widths of either side
            jo4_min, wo_min = find_min_width(wso4)
            jn4_min, wn_min = find_min_width(wsn4)

            if not np.any(jo4_min): jo4_min = np.nan
            if not np.any(jn4_min): jn4_min = np.nan

            # Get points on contour at division plane
            es_min = get_divn_plane(es, cs4[j4_min], dcs4[j4_min])

            # Split the cell areas and lengths
            ao, an = split_areas(u, tck, es_min, es, (po, pn), a)
            lo, ln = split_lengths(u, tck4, j4_min, es, (po, pn), l)

            # Find the lengths to either secondary minimum
            ro_min = float(jo4_min) / float(len(wso4))
            rn_min = 1. - float(jn4_min) / float(len(wsn4))

            lo_min = lo * ro_min
            ln_min = ln * rn_min

            # Find best-fit circle to each cell half
            cre1 = fit_circle(cs4[:j4_min])
            cre2 = fit_circle(cs4[j4_min:])
        else:
            wo_max, wn_max = np.nan, np.nan
            wo_min, wn_min = np.nan, np.nan
            ao, an = np.nan, np.nan
            lo, ln = np.nan, np.nan
            cre1 = (np.nan, np.nan)
            cre2 = (np.nan, np.nan)
            lo_min, ln_min = np.nan, np.nan

        d['RadiusStalked'] = cre1[1]
        d['RadiusSwarmer'] = cre2[1]
        d['WidthStalkedMax'] = wo_max
        d['WidthSwarmerMax'] = wn_max
        d['WidthStalkedMin'] = wo_min
        d['WidthSwarmerMin'] = wn_min
        d['AreaStalked'] = ao
        d['AreaSwarmer'] = an
        d['LengthStalked'] = lo
        d['LengthSwarmer'] = ln
        d['LengthStalkedMin'] = lo_min
        d['LengthSwarmerMin'] = ln_min
    except Exception:
        pass
    return d
def get_width_profile_new(s, num_points=500):
    """
    Get the width profile and associated variables with a recalculated midline.

    args:
        s (Series): data read in from file for a single frame

    returns:
        d (dict): calculated values

    """

    # Evaluate the midline at discrete points starting at the old pole
    u = np.linspace(0.0, 1.0, num_points)

    d = {
        "Radius": np.nan,
        "RadiusStalked": np.nan,
        "RadiusSwarmer": np.nan,
        "Widths": np.empty(0),
        "WidthMin": np.nan,
        "WidthStalkedMax": np.nan,
        "WidthSwarmerMax": np.nan,
        "WidthStalkedMin": np.nan,
        "WidthSwarmerMin": np.nan,
        "Area": np.nan,
        "AreaStalked": np.nan,
        "AreaSwarmer": np.nan,
        "Length": np.nan,
        "LengthStalked": np.nan,
        "LengthSwarmer": np.nan,
        "LengthStalkedMin": np.nan,
        "LengthSwarmerMin": np.nan,
        "MidSpline": [],
    }
    try:
        # Get coordinates and first derivative of contour
        tck = s["EdgeSpline"]
        es = np.asarray(zip(*splev(u, tck)))
        des = np.asarray(zip(*splev(u, tck, der=1)))

        # Find a crude approximation of the cell poles
        ps = (s["StalkedPole"], s["SwarmerPole"])

        # Approximate the midline by taking the Voronoi diagram
        vs = find_midline(es)

        # Prune the Voronoi diagram to remove branch points
        cs0 = prune_midline(es, des, vs)

        # Reorient the midline from stalked to swarmer pole
        cs1 = orient_midline(es, cs0, ps)

        # Find approximate width along the medial axis
        ws1 = get_width(es, cs1[:-1], np.diff(cs1, axis=0))

        # Find the radius of curvature of the entire cell
        cre0 = fit_circle(cs1)

        # Get the minimum cell width
        j1_min, w1_min = find_min_width(ws1)
        if np.any(j1_min):
            # Split contours according to minimum cell width
            wso1, wsn1 = ws1[:j1_min], ws1[j1_min:]

            # Find the maximum widths of either side
            jo1_max, wo1_max = find_max_width(wso1)
            jn1_max, wn1_max = find_max_width(wsn1)

            # Only keep exterior points within 98% of maximum width
            ko1_max = np.flatnonzero(wso1[jo1_max:] > wo1_max * 0.75)
            ko1 = np.hstack((range(jo1_max), jo1_max + ko1_max))
            kn1_max = np.flatnonzero(wsn1[:jn1_max] > wn1_max * 0.75)
            kn1 = np.hstack((kn1_max, range(jn1_max, len(wsn1))))

            # Fit circles to either cell
            cre1 = fit_circle(cs1[ko1])
            cre2 = fit_circle(cs1[j1_min + kn1])
        else:
            cre1, cre2, = cre0, cre0

        # Extend the midline in a way that maintains curvature
        cs2 = extend_midline(es, cs1, (cre1[:2], cre2[:2]), ps)

        # Spline the new midline
        tck4 = makebspline(cs2, smoothing=0.1)[0]
        d["MidSpline"] = tck4
        cs4 = np.asarray(zip(*splev(u, tck4)))
        dcs4 = np.asarray(zip(*splev(u, tck4, der=1)))

        # Get the correct cell poles
        po, pn = cs4[0], cs4[-1]

        # Get the index of the stalked pole
        jo = np.argmin(np.sum((es - po) ** 2, axis=1))

        # Overall cell area and length
        a = splineprops(u, tck, "Area")["Area"]
        d["Area"] = a
        l = splineprops(u, tck4, "Length")["Length"]
        d["Length"] = l

        # Fit best-fit circle to entire cell
        cre0 = fit_circle(cs4)
        d["Radius"] = cre0[1]

        # Get the cell width and minimum and maximum cell widths
        ws4 = get_width(es, cs4, dcs4)
        d["Widths"] = ws4
        j4_min, w_min = find_min_width(ws4)
        d["WidthMin"] = w_min
        if np.any(j4_min):
            # Split contours according to minimum cell width
            wso4, wsn4 = ws4[:j4_min], ws4[j4_min:]

            # Find the maximum widths of either side
            jo4_max, wo_max = find_max_width(wso4)
            jn4_max, wn_max = find_max_width(wsn4)

            # Find the minimum widths of either side
            jo4_min, wo_min = find_min_width(wso4)
            jn4_min, wn_min = find_min_width(wsn4)

            if not np.any(jo4_min):
                jo4_min = np.nan
            if not np.any(jn4_min):
                jn4_min = np.nan

            # Get points on contour at division plane
            es_min = get_divn_plane(es, cs4[j4_min], dcs4[j4_min])

            # Split the cell areas and lengths
            ao, an = split_areas(u, tck, es_min, es, (po, pn), a)
            lo, ln = split_lengths(u, tck4, j4_min, es, (po, pn), l)

            # Find the lengths to either secondary minimum
            ro_min = float(jo4_min) / float(len(wso4))
            rn_min = 1.0 - float(jn4_min) / float(len(wsn4))

            lo_min = lo * ro_min
            ln_min = ln * rn_min

            # Find best-fit circle to each cell half
            cre1 = fit_circle(cs4[:j4_min])
            cre2 = fit_circle(cs4[j4_min:])
        else:
            wo_max, wn_max = np.nan, np.nan
            wo_min, wn_min = np.nan, np.nan
            ao, an = np.nan, np.nan
            lo, ln = np.nan, np.nan
            cre1 = (np.nan, np.nan)
            cre2 = (np.nan, np.nan)
            lo_min, ln_min = np.nan, np.nan

        d["RadiusStalked"] = cre1[1]
        d["RadiusSwarmer"] = cre2[1]
        d["WidthStalkedMax"] = wo_max
        d["WidthSwarmerMax"] = wn_max
        d["WidthStalkedMin"] = wo_min
        d["WidthSwarmerMin"] = wn_min
        d["AreaStalked"] = ao
        d["AreaSwarmer"] = an
        d["LengthStalked"] = lo
        d["LengthSwarmer"] = ln
        d["LengthStalkedMin"] = lo_min
        d["LengthSwarmerMin"] = ln_min
    except Exception:
        pass
    return d