def test_distance():
    exp_organo = generate_ring(3, 1, 2)
    th_organo = generate_ring(3, 1, 2)
    exp_organo.vert_df.loc[0, 'x'] += 1
    distance = _distance(exp_organo, th_organo)
    assert np.all(
        np.equal(distance, np.concatenate(([1], np.zeros(exp_organo.Nv - 1)))))
def test_distance_regularized():
    exp_organo = generate_ring(3, 1, 2)
    th_organo = generate_ring(3, 1, 2)
    geom.update_all(exp_organo)
    geom.update_all(th_organo)
    specs = {
        'face': {
            'is_alive': 1,
            'prefered_area': 1.1 * th_organo.face_df.area,
            'area_elasticity': 1,
        },
        'edge': {
            'ux': 0.,
            'uy': 0.,
            'uz': 0.,
            'line_tension': 0.01,
            'is_active': 1
        },
        'vert': {
            'adhesion_strength': 0.,
            'x_ecm': 0.,
            'y_ecm': 0.,
            'is_active': 1
        },
        'settings': {
            'lumen_elasticity': 0.01,
            'lumen_prefered_vol': th_organo.settings['lumen_volume'],
            'lumen_volume': th_organo.settings['lumen_volume']
        }
    }
    exp_organo.update_specs(specs, reset=True)
    th_organo.update_specs(specs, reset=True)
    param_tension_only = {('edge', 'line_tension'): np.ones(12)}
    param_with_lumen = {
        ('edge', 'line_tension'): np.ones(12),
        ('lumen_prefered_vol', None): th_organo.settings['lumen_volume']
    }
    for basal_reg, apical_reg in ((0, 0), (0, 1), (1, 0), (1, 1)):
        for variables in (param_with_lumen, param_tension_only):
            to_regularize = {'dic': {'apical': basal_reg, 'basal': apical_reg}}
            reg_weight = 0.01
            energy_opt = {'options': {'gtol': 1e-1, 'ftol': 1e-1}}

            exp_organo.vert_df.loc[0, 'x'] += 1
            res = distance_regularized(exp_organo, th_organo, variables,
                                       Solver, geom, model, **energy_opt)
            assert isinstance(res, np.ndarray)
            assert res.all() >= 0
            assert res.any() > 0
def _create_org():
    organo = generate_ring(3, 1, 2)
    geom.update_all(organo)
    alpha = 1 + 1 / (20 * (organo.settings['R_out'] - organo.settings['R_in']))
    specs = {
        'face': {
            'is_alive': 1,
            'prefered_area': list(alpha * organo.face_df.area.values),
            'area_elasticity': 1.,
        },
        'edge': {
            'ux': 0.,
            'uy': 0.,
            'uz': 0.,
            'line_tension': 0.1,
            'is_active': 1
        },
        'vert': {
            'adhesion_strength': 0.,
            'x_ecm': 0.,
            'y_ecm': 0.,
            'is_active': 1
        },
        'settings': {
            'lumen_elasticity': 0.1,
            'lumen_prefered_vol': organo.settings['lumen_volume'],
            'lumen_volume': organo.settings['lumen_volume']
        }
    }

    organo.update_specs(specs, reset=True)
    geom.update_all(organo)
    return organo
def test_infer_pol():
    organo = generate_ring(3, 1, 2)
    pol_organo = organo.copy()
    pol_organo.vert_df.loc[pol_organo.basal_verts, ('x', 'y')] *= 1.1
    geom.update_all(pol_organo)
    for val in _infer_pol(pol_organo):
        assert round(val, 9) == 0.9
def test_tension_bounds():
    organo = generate_ring(3, 1, 2)
    organo.edge_df.loc[:, 'line_tension'] = np.ones(12)
    organo.edge_df.loc[(0, 1), 'line_tension'] = [-1, 2 * 1e3]
    penalties = _tension_bounds(organo)
    assert len(penalties) == 3 * organo.Nf
    assert penalties[0] == 1e3
    assert penalties[1] == 0
    assert np.argwhere(penalties != 0).squeeze() == np.array(0)
def test_right_side():
    organo = generate_ring(3, 1, 2)
    pol_organo = organo.copy()
    pol_organo.vert_df.loc[pol_organo.basal_verts, ('x', 'y')] *= 1.1
    geom.update_all(pol_organo)
    cst = _right_side(pol_organo)
    assert isinstance(cst, np.ndarray)
    assert np.array_equal(cst.shape, (15, ))
    assert np.array_equal(cst[:12], np.zeros(12))
    assert not np.isnan(cst[12:]).any()
def test_t_per_cell_coefs():
    organo = generate_ring(3, 1, 2)
    t_per_cell = _t_per_cell_coefs(organo, _get_sim_param(3, 1, 2),
                                   _infer_pol(organo))
    assert isinstance(t_per_cell, np.ndarray)
    assert np.array_equal(t_per_cell.shape, (3, 13))
    assert np.array_equal(t_per_cell[:, :3], np.eye(3))
    assert np.array_equal(t_per_cell[:, 3:6], np.eye(3))
    assert np.array_equal(
        t_per_cell[:, 6:9],
        np.roll(np.eye(3) + np.roll(np.eye(3), 1, axis=0), 1, axis=1))
    assert np.array_equal(t_per_cell[:, 9:], np.zeros((3, 4)))
예제 #8
0
def mesh_from_data(centers, inner_contour, outer_contour):
    """Creates an annular organoid from image data
    """

    Nf = centers.shape[0]
    print(tmp_eptm.datasets[elem][columns], values)

    # Organize centers clockwize
    origin = centers.mean(axis=1)
    shifted_centers = centers - origin[np.newaxis, :]
    thetas = np.arctan2(shifted_centers[:, 1], shifted_centers[:, 0])
    centers = centers.take(np.argsort(thetas))
    inner_vs, outer_vs = get_bissecting_vertices(centers, inner_contour,
                                                 outer_contour)

    R_in = np.linalg.norm(inner_vs - inner_vs.mean(axis=1), axis=0).mean()
    R_out = np.linalg.norm(outer_vs - outer_vs.mean(axis=1), axis=0).mean()

    organo = generate_ring(Nf, R_in, R_out)
    organo.vert_df.loc[organo.apical_verts, organo.coords] = inner_vs[::-1]
    organo.vert_df.loc[organo.basal_verts, organo.coords] = outer_vs[::-1]

    AnnularGeometry.update_all(organo)
    specs = {
        'face': {
            'is_alive': 1,
            'prefered_area': organo.face_df.area.mean(),
            'area_elasticity': 1,
        },
        'edge': {
            'ux': 0.,
            'uy': 0.,
            'fx': 0.,
            'fy': 0.,
            'sx': 0.,  # source and target coordinates
            'sy': 0.,
            'tx': 0.,
            'ty': 0.,
            'line_tension': 1e-3,
            'is_active': 1
        },
        'vert': {
            'is_active': 1
        },
        'settings': {
            'lumen_elasticity': 10,
            'lumen_prefered_vol': organo.settings['lumen_volume'],
            'lumen_volume': organo.settings['lumen_volume']
        }
    }
    organo.update_specs(specs, reset=True)
    return organo
def test_prepare_tensions():
    organo = generate_ring(3, 1, 2)
    organo.edge_df.loc[:, 'line_tension'] = np.ones(12)
    tension_array = organo.edge_df.loc[:, 'line_tension'][:3 * organo.Nf]
    tension_array[0] += 1
    tension_array[3 * organo.Nf - 1] += 1
    tensions = prepare_tensions(organo, tension_array)
    assert len(tensions) == 4 * organo.Nf
    assert np.all(
        np.equal(tensions[:3 * organo.Nf], tension_array[:3 * organo.Nf]))
    assert np.all(
        np.equal(np.roll(tensions[3 * organo.Nf:], 1),
                 tension_array[2 * organo.Nf:]))
예제 #10
0
def create_organo(nb_cells, r_in, r_out, seed=None, rot=None, geom=geom):
    organo = generate_ring(nb_cells, r_in, r_out)
    Nf = organo.Nf
    geom.update_all(organo)
    alpha = 1 + 1 / (20 * (organo.settings['R_out'] - organo.settings['R_in']))
    specs = {
        'face': {
            'is_alive': 1,
            'prefered_area': organo.face_df.area,
            'area_elasticity': 1.,
        },
        'edge': {
            'ux': 0.,
            'uy': 0.,
            'uz': 0.,
            'line_tension': 0.1,
            'is_active': 1
        },
        'vert': {
            'adhesion_strength': 0.01,
            'x_ecm': 0.,
            'y_ecm': 0.,
            'is_active': 1
        },
        'settings': {
            'lumen_elasticity': 1.,
            'lumen_prefered_vol': organo.settings['lumen_volume'],
            'lumen_volume': organo.settings['lumen_volume']
        }
    }
    organo.update_specs(specs, reset=True)
    normalize_scale(organo, geom, refer='edges')
    geom.update_all(organo)
    if seed is not None:
        symetric_tensions = set_init_point(organo.settings['R_in'],
                                           organo.settings['R_out'], organo.Nf,
                                           alpha)
        sin_mul = 1 + (np.sin(
            np.linspace(0, 2 * np.pi, organo.Nf, endpoint=False)))**2
        organo.face_df.prefered_area *= np.random.normal(1.0, 0.05, organo.Nf)
        organo.edge_df.line_tension = prepare_tensions(organo,
                                                       symetric_tensions)
        organo.edge_df.loc[:Nf - 1,
                           'line_tension'] *= sin_mul * np.random.normal(
                               1.0, 0.05, organo.Nf)
        geom.update_all(organo)
    if rot is not None:
        organo.vert_df.loc[:, 'x'] = (organo.vert_df.x.copy() * np.cos(rot) -
                                      organo.vert_df.y.copy() * np.sin(rot))
        print(
            'rotated x',
            organo.vert_df.x.copy() * np.cos(rot) -
            organo.vert_df.y.copy() * np.sin(rot))
        organo.vert_df.loc[:, 'y'] = (organo.vert_df.x.copy() * np.sin(rot) +
                                      organo.vert_df.y.copy() * np.cos(rot))
        print(
            'rotated y',
            organo.vert_df.x.copy() * np.sin(rot) +
            organo.vert_df.y.copy() * np.cos(rot))
        geom.update_all(organo)
    organo.vert_df[['x_ecm', 'y_ecm']] = organo.vert_df[['x', 'y']]
    organo.vert_df.loc[organo.basal_verts, 'adhesion_strength'] = 0.01
    new_tensions = organo.edge_df.line_tension
    organo.edge_df.loc[:, 'line_tension'] = new_tensions
    return organo
예제 #11
0
def generate_ring_from_image(
    brightfield_path,
    dapi_path,
    scp_model_path=None,
    threshold=28,
    blur=9,
    rol_window_inside=100,
    rol_window_outside=20,
):
    """Create an organo mesh of class AnnularSheet from a brightfield image
    and a CellProfiler DAPI analysis csv file

    Parameters
    ----------
    brightfield_path : string
      path to the brightfield image
    dapi_path : string
      path to the DAPI image
    scp_model_path : string
      path to the stardist model
    threshold: int >=0
      threshold to apply to the brightfield image
    blur: int >=0
      gaussian blur to apply to the brightfield image
    rol_window_inside: int > 0.
      Length of the window of the rolling mean on apical contour.
    rol_window_outside: int > 0.
      Length of the window of the rolling mean on basal contour.
    Return
    ----------
    organo : object of class AnnularSheet
      the organo mesh extracted from the data
    """

    membrane_dic = extract_membranes(brightfield_path, threshold, blur)
    clockwise_centers = _star_convex_polynoms(dapi_path, membrane_dic,
                                              scp_model_path)

    inside_df = pd.DataFrame(membrane_dic["inside"], index=None)
    outside_df = pd.DataFrame(membrane_dic["outside"], index=None)
    inners = inside_df.rolling(rol_window_inside, min_periods=1).mean().values
    outers = outside_df.rolling(rol_window_outside,
                                min_periods=1).mean().values

    nb_cells = len(clockwise_centers)

    org_center = membrane_dic["center_inside"] - np.full(
        2, membrane_dic["img_shape"][0] / 2.0)

    inner_vs, outer_vs = get_bissecting_vertices(clockwise_centers, inners,
                                                 outers, org_center)

    organo = generate_ring(nb_cells, membrane_dic["rIn"], membrane_dic["rOut"])

    organo.vert_df.loc[organo.apical_verts, organo.coords] = (
        inner_vs[::-1] - np.full(inner_vs.shape, org_center)) * 0.323
    organo.vert_df.loc[organo.basal_verts, organo.coords] = (
        outer_vs[::-1] - np.full(outer_vs.shape, org_center)) * 0.323
    inners = (inners - np.full(inners.shape, org_center)) * 0.323
    outers = (outers - np.full(outers.shape, org_center)) * 0.323
    clockwise_centers = np.array(clockwise_centers)
    clockwise_centers -= np.full(outer_vs.shape, org_center)
    clockwise_centers *= 0.323
    organo.settings["R_in"] *= 0.323
    organo.settings["R_out"] *= 0.323

    return organo, inners, outers, clockwise_centers