Skip to content
Snippets Groups Projects
test_dycpm.py 9.67 KiB
Newer Older
Roman Belousov's avatar
Roman Belousov committed
"""Test `dycpm` module"""
import dycpm
Roman Belousov's avatar
Roman Belousov committed
import dycpm.analysis
Roman Belousov's avatar
Roman Belousov committed
import pytest
import json
Roman Belousov's avatar
Roman Belousov committed
import numpy as np, networkx as nx
Roman Belousov's avatar
Roman Belousov committed

def test_cell():
    """Test `dycpm.Cell`"""
    side = 100
    volume = round(np.mean(dycpm.DIVISION_VOLUME_DISTRIBUTION) / 2)
    partition = round(np.cbrt(volume));
    margin = round(np.floor((side - partition) / 2));

    cell = dycpm.Cell(
        type_id=dycpm.EPI, parent_id=0, age=0, preferred_volume=volume,
        division_volume=dycpm.sample_division_volume(),
        voxel_ids=[round(
            margin + (n - 1) % partition**2 % partition
            + side * (margin + (n - 1) % partition**2 // partition)
            + side**2 * (margin + (n - 1) // partition**2)
        ) for n in range(volume)]
    )

    assert 475144 in cell.voxel_ids
    assert cell.type_id == dycpm.EPI
    assert cell.type_id != dycpm.PRE

    cell.type_id = dycpm.PRE
    assert cell.type_id == dycpm.PRE

def test_state(tmp_path):
    """Test JSON-format export and import of a state"""
    state = dycpm.State(
        side=10, action_probabilities=3 * [0.3],
        growth_rate=2 * [1.6], volume_elasticity=2 * [1],
Roman Belousov's avatar
Roman Belousov committed
        active_exponents = [0.1, -1.2, 2.3, -3.4, 0.5, -0.6, 7.7],
Roman Belousov's avatar
Roman Belousov committed
        surface_tension=5 * [10], cells={
            1: {
                'type_id': dycpm.EPI, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': 1,
                "voxel_ids": [1]
            }
        }
    )

    assert state.side == 10
Roman Belousov's avatar
Roman Belousov committed
    assert state.active_exponents == [0.1, -1.2, 2.3, -3.4, 0.5, -0.6, 7.7]
Roman Belousov's avatar
Roman Belousov committed

Roman Belousov's avatar
Roman Belousov committed
    path = f'{tmp_path}/test_state.json'
Roman Belousov's avatar
Roman Belousov committed
    state.to_json_file(path)
    assert isinstance(state.cells[1], dycpm.Cell)

    state = dycpm.State.from_json_file(path)
    assert state.side == 10

    assert state.surface_tension[0] == 10

    state.surface_tension = [20, 5, 10, 15, 10]
    assert state.surface_tension[0] == 20
    state.surface_tension[0] = 25
    assert state.surface_tension[0] == 25

    assert state.cells[1].type_id == dycpm.EPI
    assert state.cells[1].type_id != dycpm.PRE

    state.cells[1].type_id = dycpm.PRE
    assert state.cells[1].type_id != dycpm.EPI
    assert state.cells[1].type_id == dycpm.PRE

Roman Belousov's avatar
Roman Belousov committed
    assert state.active_exponents == [0.1, -1.2, 2.3, -3.4, 0.5, -0.6, 7.7]

Roman Belousov's avatar
Roman Belousov committed
def test_simulation():
    """Test simulation flow"""
    side = 100
    volume = round(np.mean(dycpm.DIVISION_VOLUME_DISTRIBUTION) / 2)
    partition = round(np.cbrt(volume));
    margin = round(np.floor((side - partition) / 2));

    state = dycpm.State(
        time=0, side=side, action_probabilities=3 * [0.3], death_probability=1e-4,
        growth_rate=2 * [1.6], volume_elasticity=2 * [1], surface_tension=5 * [10],
        division_distribution=dycpm.DIVISION_VOLUME_DISTRIBUTION,
        cells={
            1: {
                'type_id': 1, 'parent_id': 0, 'age': 0,
                'preferred_volume': volume,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [round(
                    margin + (n - 1) % partition**2 % partition
                    + side * (margin + (n - 1) % partition**2 // partition)
                    + side**2 * (margin + (n - 1) // partition**2)
                ) for n in range(volume)]
            }
        }
    )
Roman Belousov's avatar
Roman Belousov committed
    assert state.active_exponents == 8 * [0.0]
Roman Belousov's avatar
Roman Belousov committed
    assert 1 in state.cells

    kernel = dycpm.Kernel(state)
    assert kernel.cell_number == 1
    for _ in range(2): kernel.advance()
    state = kernel.state

    assert state.time == 2
    assert state.side == 100
Roman Belousov's avatar
Roman Belousov committed

def test_lattice():
    """Test `State.lattice()"""

    side = 100
    volume = round(np.mean(dycpm.DIVISION_VOLUME_DISTRIBUTION) / 2)
    partition = round(np.cbrt(volume));
    margin = round(np.floor((side - partition) / 2));

    state = dycpm.State(
        time=0, side=side, action_probabilities=3 * [0.3], death_probability=1e-4,
        growth_rate=2 * [1.6], volume_elasticity=2 * [1], surface_tension=5 * [10],
        division_distribution=dycpm.DIVISION_VOLUME_DISTRIBUTION,
        cells={
            1: {
                'type_id': 1, 'parent_id': 0, 'age': 0,
                'preferred_volume': volume,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [round(
                    margin + (n - 1) % partition**2 % partition
                    + side * (margin + (n - 1) % partition**2 // partition)
                    + side**2 * (margin + (n - 1) // partition**2)
                ) for n in range(volume)]
            }
        }
    )

    lattice = state.lattice()
    assert lattice.shape == (side, ) * 3
    assert lattice[49, 49, 49] == 1
    assert lattice[0, 0, 0] == 0
    assert np.count_nonzero(lattice.ravel() == 1) == volume

def test_analysis_neighborIndex():
    """ Test `dycpm.analysis.neighbor_index()`"""
    state = dycpm.State(
        time=0, side=10, action_probabilities=3 * [0.3], death_probability=1e-4,
        growth_rate=2 * [1.6], volume_elasticity=2 * [1], surface_tension=5 * [10],
        division_distribution=dycpm.DIVISION_VOLUME_DISTRIBUTION,
        cells={
            1: {
                'type_id': 1, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 4 * 10 + 4]
            },
            2: {
                'type_id': 1, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 4 * 10 + 5]
            },
            3: {
                'type_id': 2, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 5 * 10 + 4]
            }
        }
    )
    assert dycpm.analysis.neighbor_index(state, [1], [2]) == 0.5
    assert dycpm.analysis.neighbor_index(state, [1], [0, 2]) == 2 / 3
    assert dycpm.analysis.neighbor_index(state, [2], [1]) == 1
    assert dycpm.analysis.neighbor_index(state, [2], [0, 1]) == 1


    """ Test `dycpm.analysis`"""
    state = dycpm.State(
        time=0, side=10, action_probabilities=3 * [0.3], death_probability=1e-4,
        growth_rate=2 * [1.6], volume_elasticity=2 * [1], surface_tension=5 * [10],
        division_distribution=dycpm.DIVISION_VOLUME_DISTRIBUTION,
        cells={
            1: {
                'type_id': 1, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 4 * 10 + 4]
            },
            2: {
                'type_id': 1, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 4 * 10 + 5]
            },
            3: {
                'type_id': 2, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 5 * 10 + 4]
            },
            4: {
                'type_id': 2, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [0 * 10**2 + 0 * 10 + 0]            
            },
            5: {
                'type_id': 2, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [1 * 10**2 + 0 * 10 + 0]            
            }
        }
    )
    assert dycpm.analysis.neighbor_index(state, [1], [2]) == 0.5
    assert dycpm.analysis.neighbor_index(state, [1], [0, 2]) == 2 / 3
    assert dycpm.analysis.neighbor_index(state, [2], [1]) == 1 / 3
    assert dycpm.analysis.neighbor_index(state, [2], [0, 1]) == 2 / 3
Roman Belousov's avatar
Roman Belousov committed

def test_analysis_cellGraph():
    """ Test `dycpm.analysis.cellGraph()`"""
    state = dycpm.State(
        time=0, side=10, action_probabilities=3 * [0.3], death_probability=1e-4,
        growth_rate=2 * [1.6], volume_elasticity=2 * [1], surface_tension=5 * [10],
        division_distribution=dycpm.DIVISION_VOLUME_DISTRIBUTION,
        cells={
            1: {
                'type_id': 1, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 4 * 10 + 4]
            },
            2: {
                'type_id': 1, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 4 * 10 + 5]
            },
            3: {
                'type_id': 2, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [4 * 10**2 + 5 * 10 + 4]
            },
            4: {
                'type_id': 2, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [0 * 10**2 + 0 * 10 + 0]            
            },
            5: {
                'type_id': 2, 'parent_id': 0, 'age': 0,
                'preferred_volume': 1,
                'division_volume': dycpm.sample_division_volume(),
                "voxel_ids": [1 * 10**2 + 0 * 10 + 0]            
            }
        }
    )

    epi = dycpm.analysis.CellGraph(state, dycpm.EPI)
    pre = dycpm.analysis.CellGraph(state, dycpm.PRE)
    assert len(epi.nodes) == 2
    assert len(pre.nodes) == 3
    assert nx.number_connected_components(epi) == 1
    assert nx.number_connected_components(pre) == 2