def test_jacobian_1DN3(): force = ff.Linear() force_prime = force.derive() y = np.array([1.0, 0.7, 2.5])[:, np.newaxis] model = cbmos.CBModel(force, ef.solve_ivp, 1) A = model.jacobian(y, {}) # calculate manually y1 = y[0] y2 = y[1] y3 = y[2] A12 = (y2-y1)**2/abs(y2-y1)**2\ *(force_prime(abs(y2-y1)) - force(abs(y2-y1))/abs(y2-y1))\ + force(abs(y2-y1))/abs(y2-y1) A13 = (y3-y1)**2/abs(y3-y1)**2\ *(force_prime(abs(y3-y1)) - force(abs(y3-y1))/abs(y3-y1))\ + force(abs(y3-y1))/abs(y3-y1) A23 = (y3-y2)**2/abs(y3-y2)**2\ *(force_prime(abs(y3-y2)) - force(abs(y3-y2))/abs(y3-y2))\ + force(abs(y3-y2))/abs(y3-y2) A2 = np.squeeze( np.array([[-(A12 + A13), A12, A13], [A12, -(A12 + A23), A23], [A13, A23, -(A13 + A23)]])) assert (np.all(A == A2))
def test_jacobian_3DN3(): g = ff.Linear() g_prime = g.derive() y = np.array([[0., 0., 0.], [0.7, 0.1, -0.6], [0.3, -1., -2.0]]) model = cbmos.CBModel(g, ef.solve_ivp, 3) A = model.jacobian(y, {}) # calculate manually y1 = y[0, :][:, np.newaxis] y2 = y[1, :][:, np.newaxis] y3 = y[2, :][:, np.newaxis] r12 = y2 - y1 norm_12 = np.linalg.norm(r12) r13 = y3 - y1 norm_13 = np.linalg.norm(r13) r23 = y3 - y2 norm_23 = np.linalg.norm(r23) A12 = r12 @ r12.transpose() / norm_12**2 * (g_prime( norm_12) - g(norm_12) / norm_12) + g(norm_12) / norm_12 * np.eye(3) A13 = r13 @ r13.transpose() / norm_13**2 * (g_prime( norm_13) - g(norm_13) / norm_13) + g(norm_13) / norm_13 * np.eye(3) A23 = r23 @ r23.transpose() / norm_23**2 * (g_prime( norm_23) - g(norm_23) / norm_23) + g(norm_23) / norm_23 * np.eye(3) A2 = np.block([[-(A12 + A13), A12, A13], [A12, -(A12 + A23), A23], [A13, A23, -(A13 + A23)]]) assert (np.all(A == A2))
def test_no_division_skipped(): dim = 1 cbm_solver = cbmos.CBModel(ff.Linear(), scpi.solve_ivp, dim) cell_list = [ cl.Cell(0, [0], proliferating=True), cl.Cell(1, [1.0], 0.0, True) ] cell_list[0].division_time = 1.0 cell_list[1].division_time = 1.0 t_data = np.linspace(0, 30, 101) _, history = cbm_solver.simulate(cell_list, t_data, {}, {}, raw_t=False) eq = [ hq.heappop(cbm_solver._queue._events) for i in range(len(cbm_solver._queue._events)) ] assert eq == sorted(eq) assert len(eq) == len(history[-1]) - 1 for t, cells in zip(t_data, history): for c in cells: assert c.birthtime <= t assert c.division_time > t
def test_cell_list_copied(): dim = 1 cbm_solver_one = cbmos.CBModel(ff.Linear(), scpi.solve_ivp, dim) cbm_solver_two = cbmos.CBModel(ff.Linear(), scpi.solve_ivp, dim) cell_list = [ cl.Cell(0, [0], proliferating=True), cl.Cell(1, [0.3], proliferating=True) ] t_data = np.linspace(0, 1, 101) _, history_one = cbm_solver_one.simulate(cell_list, t_data, {}, {}) _, history_two = cbm_solver_two.simulate(cell_list, t_data, {}, {}) assert history_two[0][0].position == np.array([0]) assert history_two[0][1].position == np.array([0.3])
def test_event_at_t_data(): dim = 1 cbm_solver = cbmos.CBModel(ff.Linear(), scpi.solve_ivp, dim) cell_list = [ cl.Cell(0, [0], proliferating=True), cl.Cell(1, [1.0], 0.0, True) ] cell_list[0].division_time = 1.0 cell_list[1].division_time = 1.0 t_data = np.linspace(0, 10, 101) _, history = cbm_solver.simulate(cell_list, t_data, {}, {}, raw_t=False) assert len(history) == len(t_data)
def test_update_positions(): dim = 3 cbm_solver = cbmos.CBModel(ff.Linear(), ef.solve_ivp, dim) cell_list = [cl.Cell(i, [0, 0, i]) for i in range(5)] for i, cell in enumerate(cell_list): cell.division_time = cell.ID cbm_solver.cell_list = cell_list new_positions = [[0, i, i] for i in range(5)] cbm_solver._update_positions(new_positions) for i, cell in enumerate(cbm_solver.cell_list): print(cell.position) assert cell.position.tolist() == [0, i, i]
def test_calculate_positions(two_cells): for dim in [1, 2, 3]: cbm_solver = cbmos.CBModel(ff.Linear(), ef.solve_ivp, dim) T = np.linspace(0, 10, num=10) # Check cells end up at the resting length for s in [1., 2., 3.]: sol = cbm_solver._calculate_positions( T, two_cells.reshape(-1, 3)[:, :dim].reshape(-1), { 's': s, 'mu': 1.0 }, { 'dt': 0.1 }).y.reshape(-1, 2 * dim) assert np.abs(sol[-1][:dim] - sol[-1][dim:]).sum() - s < 0.01
def test_apply_division(): from cbmos.cbmodel._eventqueue import EventQueue dim = 3 cbm_solver = cbmos.CBModel(ff.Linear(), ef.solve_ivp, dim) cell_list = [cl.Cell(i, [0, 0, i], proliferating=True) for i in range(5)] for i, cell in enumerate(cell_list): cell.division_time = cell.ID cbm_solver.cell_list = cell_list cbm_solver.next_cell_index = 5 cbm_solver._queue = EventQueue([]) cbm_solver._apply_division(cell_list[0], 1) assert len(cbm_solver.cell_list) == 6 assert cbm_solver.cell_list[5].ID == 5 assert cbm_solver.next_cell_index == 6 assert cell_list[0].division_time != 0 assert np.isclose( np.linalg.norm(cell_list[0].position - cell_list[5].position), cbm_solver.separation)
def test_min_event_resolution(): dim = 1 cbm_solver = cbmos.CBModel(ff.Linear(), scpi.solve_ivp, dim) cell_list = [ cl.Cell(0, [0], proliferating=True), cl.Cell(1, [1.0], 0.0, True) ] cell_list[0].division_time = 0.25 cell_list[1].division_time = 0.25 t_data = [0, 0.4, 0.6, 1] _, history = cbm_solver.simulate( cell_list, t_data, {}, {}, raw_t=False, min_event_resolution=0.5, ) assert len(history[0]) == 2 assert len(history[1]) == 2 assert len(history[2]) == 4 assert len(history[3]) == 4