Source code for src.agent.default_geo_neighbor_helpers

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from src.agent.cell import Cell
    from src.sim.simulation.sim import GrowingSim


[docs] class NeighborHelpers: """ Helper functions to determine the direction of a neighbor cell relative to a cell when initializing model to default geometry. """ ROOTCAP_CELL_IDs = [ 60, 90, 120, 136, 166, 210, 296, 75, 105, 135, 151, 181, 225, 311, ]
[docs] @staticmethod def get_neighbor_dir_neighbor_shares_one_v_default_geo(cell: "Cell", neighbor: "Cell") -> str: """ Determine the direction of a neighbor cell sharing one vertex in default geometry. Parameters ---------- cell : Cell The reference cell. neighbor : Cell The neighboring cell being considered. Returns ------- str The direction of the neighbor relative to the cell ('a', 'b', 'l', 'm'), or an empty string if no direction is applicable. Notes ----- The direction is determined by comparing cell IDs. These directions will only be correct if model is initialized to default geometry. """ neighbor_direct = "" if cell.get_c_id() == 10 and neighbor.get_c_id() == 20: neighbor_direct = "a" elif cell.get_c_id() == 20 and neighbor.get_c_id() == 10: neighbor_direct = "b" elif cell.get_c_id() == 11 and neighbor.get_c_id() == 25: neighbor_direct = "a" elif cell.get_c_id() == 25 and neighbor.get_c_id() == 11: neighbor_direct = "b" elif cell.get_c_id() == 16 and neighbor.get_c_id() == 36: neighbor_direct = "a" elif cell.get_c_id() == 36 and neighbor.get_c_id() == 16: neighbor_direct = "b" elif cell.get_c_id() == 19 and neighbor.get_c_id() == 37: neighbor_direct = "a" elif cell.get_c_id() == 37 and neighbor.get_c_id() == 19: neighbor_direct = "b" elif cell.get_c_id() == 20 and neighbor.get_c_id() == 26: neighbor_direct = "b" elif cell.get_c_id() == 26 and neighbor.get_c_id() == 20: neighbor_direct = "l" elif cell.get_c_id() == 20 and neighbor.get_c_id() == 36: neighbor_direct = "a" elif cell.get_c_id() == 36 and neighbor.get_c_id() == 20: neighbor_direct = "b" elif cell.get_c_id() == 25 and neighbor.get_c_id() == 27: neighbor_direct = "b" elif cell.get_c_id() == 27 and neighbor.get_c_id() == 25: neighbor_direct = "l" elif cell.get_c_id() == 25 and neighbor.get_c_id() == 37: neighbor_direct = "a" elif cell.get_c_id() == 37 and neighbor.get_c_id() == 25: neighbor_direct = "b" elif cell.get_c_id() == 38 and neighbor.get_c_id() == 39: neighbor_direct = "m" elif cell.get_c_id() == 39 and neighbor.get_c_id() == 38: neighbor_direct = "l" elif cell.get_c_id() == 39 and neighbor.get_c_id() == 46: neighbor_direct = "l" elif cell.get_c_id() == 46 and neighbor.get_c_id() == 39: neighbor_direct = "m" elif cell.get_c_id() == 42 and neighbor.get_c_id() == 43: neighbor_direct = "l" elif cell.get_c_id() == 43 and neighbor.get_c_id() == 42: neighbor_direct = "m" elif cell.get_c_id() == 42 and neighbor.get_c_id() == 47: neighbor_direct = "l" elif cell.get_c_id() == 47 and neighbor.get_c_id() == 42: neighbor_direct = "m" elif cell.get_c_id() == 44 and neighbor.get_c_id() == 50: neighbor_direct = "m" elif cell.get_c_id() == 50 and neighbor.get_c_id() == 44: neighbor_direct = "l" elif cell.get_c_id() == 45 and neighbor.get_c_id() == 51: neighbor_direct = "m" elif cell.get_c_id() == 51 and neighbor.get_c_id() == 45: neighbor_direct = "l" elif cell.get_c_id() == 50 and neighbor.get_c_id() == 52: neighbor_direct = "l" elif cell.get_c_id() == 52 and neighbor.get_c_id() == 50: neighbor_direct = "m" elif cell.get_c_id() == 51 and neighbor.get_c_id() == 59: neighbor_direct = "l" elif cell.get_c_id() == 59 and neighbor.get_c_id() == 51: neighbor_direct = "m" elif cell.get_c_id() == 54 and neighbor.get_c_id() == 65: neighbor_direct = "a" elif cell.get_c_id() == 65 and neighbor.get_c_id() == 54: neighbor_direct = "b" elif cell.get_c_id() == 54 and neighbor.get_c_id() == 66: neighbor_direct = "a" elif cell.get_c_id() == 66 and neighbor.get_c_id() == 54: neighbor_direct = "b" elif cell.get_c_id() == 57 and neighbor.get_c_id() == 69: neighbor_direct = "a" elif cell.get_c_id() == 69 and neighbor.get_c_id() == 57: neighbor_direct = "b" elif cell.get_c_id() == 57 and neighbor.get_c_id() == 70: neighbor_direct = "a" elif cell.get_c_id() == 70 and neighbor.get_c_id() == 57: neighbor_direct = "b" # This catches assignment of neighbor of root cap cells rootcap_cell_ids = NeighborHelpers.ROOTCAP_CELL_IDs if cell.get_c_id() in rootcap_cell_ids: neighbor_direct = "m" if neighbor.get_c_id() in rootcap_cell_ids: neighbor_direct = "l" return neighbor_direct
[docs] @staticmethod def check_if_neighbors_with_new_root_cap_cell(cell: "Cell", sim: "GrowingSim") -> None: """ Checks if the neighbor is the next root cap cell. Args: cell (Cell): The current cell. neighbor (Cell): The neighboring cell. Returns: str: The direction of the neighbor ('a', 'b', 'l', 'm') or None if no direction is found. """ all_lrc_cells = [ cell for cell in sim.get_cell_list() if cell.get_c_id() in NeighborHelpers.ROOTCAP_CELL_IDs ] non_current_neighbor_lrc_cells = [ lrc_cell for lrc_cell in all_lrc_cells if lrc_cell not in cell.get_l_neighbors() ] for lrc_cell in non_current_neighbor_lrc_cells: if NeighborHelpers.cell_and_lrc_cell_are_neighbors(cell, lrc_cell): cell.add_l_neighbor(lrc_cell) lrc_cell.add_m_neighbor(cell)
[docs] @staticmethod def get_neighbor_dir_neighbor_shares_no_vs_default_geo(cell: "Cell", neighbor: "Cell") -> str: """ Determine the direction of a neighbor cell without shared vertices in default geometry. Parameters ---------- cell : Cell The reference cell. neighbor : Cell The neighboring cell being considered. Returns ------- str The direction of the neighbor relative to the cell ('a', 'b', 'l', 'm'), or an appropriate message if no standard direction is found. Notes ----- This method accounts for special cases where neighboring cells do not share a common vertex. These assignments will only be true if model is initialized to default geometry. """ neighbor_direct = "" if cell.get_c_id() == 17 and neighbor.get_c_id() == 20: neighbor_direct = "l" elif cell.get_c_id() == 20 and neighbor.get_c_id() == 17: neighbor_direct = "b" elif cell.get_c_id() == 18 and neighbor.get_c_id() == 25: neighbor_direct = "l" elif cell.get_c_id() == 25 and neighbor.get_c_id() == 18: neighbor_direct = "b" # This catches assignment of neighbor of root cap cells rootcap_cell_ids = NeighborHelpers.ROOTCAP_CELL_IDs if cell.get_c_id() in rootcap_cell_ids: neighbor_miny = neighbor.get_quad_perimeter().get_min_y() if ( cell.get_quad_perimeter().get_min_y() <= neighbor_miny < cell.get_quad_perimeter().get_max_y() ): neighbor_direct = "m" else: neighbor_direct = "cell no longer root cap cell neighbor" if neighbor.get_c_id() in rootcap_cell_ids: cell_miny = cell.get_quad_perimeter().get_min_y() if ( neighbor.get_quad_perimeter().get_min_y() <= cell_miny < neighbor.get_quad_perimeter().get_max_y() ): neighbor_direct = "l" else: neighbor_direct = "cell no longer root cap cell neighbor" NeighborHelpers.check_if_neighbors_with_new_root_cap_cell(cell, cell.get_sim()) return neighbor_direct
[docs] @staticmethod # This relies on the assumption that only cells that were previously neighbors with root cap cells will ever be neighbors with root cap cells def fix_lrc_neighbors_after_growth(sim: "GrowingSim") -> None: non_root_tip_cells = [ cell for cell in sim.get_cell_list() if cell.get_cell_type() != "roottip" ] for non_root_tip_cell in non_root_tip_cells: for l_neighbor in non_root_tip_cell.get_l_neighbors(): if l_neighbor.get_c_id() in NeighborHelpers.ROOTCAP_CELL_IDs: NeighborHelpers.check_if_neighbors_with_new_root_cap_cell( non_root_tip_cell, sim ) NeighborHelpers.check_if_no_longer_neighbors_with_root_cap_cell( non_root_tip_cell, l_neighbor )
[docs] @staticmethod def check_if_no_longer_neighbors_with_root_cap_cell(cell: "Cell", lrc_neighbor: "Cell") -> None: if not NeighborHelpers.cell_and_lrc_cell_are_neighbors(cell, lrc_neighbor): cell.remove_l_neighbor(lrc_neighbor) lrc_neighbor.remove_m_neighbor(cell)
[docs] @staticmethod def cell_and_lrc_cell_are_neighbors(cell: "Cell", lrc_cell: "Cell") -> bool: cell_left_l_or_m = cell.get_quad_perimeter().get_left_lateral_or_medial( cell.get_sim().get_root_midpointx() ) lrc_cell_left_l_or_m = lrc_cell.get_quad_perimeter().get_left_lateral_or_medial( lrc_cell.get_sim().get_root_midpointx() ) # If cells are on opposite sides of the root if cell_left_l_or_m != lrc_cell_left_l_or_m: return False # Cells must share a membrane (x-coordinates of adjacent membrane don't match) if cell_left_l_or_m == "lateral": assert ( cell.get_quad_perimeter().get_min_x() == lrc_cell.get_quad_perimeter().get_max_x() ) else: assert ( cell.get_quad_perimeter().get_max_x() == lrc_cell.get_quad_perimeter().get_min_x() ) cell_miny = cell.get_quad_perimeter().get_min_y() cell_maxy = cell.get_quad_perimeter().get_max_y() lrc_cell_miny = lrc_cell.get_quad_perimeter().get_min_y() lrc_cell_maxy = lrc_cell.get_quad_perimeter().get_max_y() if ( lrc_cell_miny <= cell_miny <= lrc_cell_maxy or lrc_cell_miny <= cell_maxy <= lrc_cell_maxy or (cell_miny <= lrc_cell_miny <= cell_maxy and cell_miny <= lrc_cell_maxy <= cell_maxy) ): return True else: return False