def single_step_move(self, state: State, cell: PhagocyteCellData, cell_index: int, cell_list: CellList) -> None: """ Move the phagocyte one 1 µm, probabilistically. depending on single_step_probabilistic_drift Parameters ---------- state : State the global simulation state cell : PhagocyteCellData the cell to move cell_index : int index of cell in cell_list cell_list : CellList the CellList for the cell-type (macrophage/neutrophil/etc) of cell Returns ------- nothing """ grid: RectangularGrid = state.grid # At this moment, there is no inter-voxel geometry. cell_voxel: Voxel = grid.get_voxel(cell['point']) new_point: Point = self.single_step_probabilistic_drift( state, cell, cell_voxel) cell['point'] = new_point cell_list.update_voxel_index([cell_index])
def test_filter_out_dead(grid: RectangularGrid): cells = CellList(grid=grid) cells.extend([CellData.create_cell(dead=bool(i % 2)) for i in range(10)]) assert_array_equal(cells.alive(), [0, 2, 4, 6, 8]) assert_array_equal(cells.alive([1, 2, 3, 6]), [2, 6]) mask = np.arange(10) < 5 assert_array_equal(cells.alive(mask), [0, 2, 4])
def test_move_cell(grid: RectangularGrid): point = Point(x=4.5, y=4.5, z=4.5) raw_cells = [CellData.create_cell(point=point) for _ in range(5)] raw_cells[1]['point'] = Point(x=-1, y=4.5, z=4.5) raw_cells[4]['point'] = Point(x=4.5, y=4.5, z=-1) cells = CellList(grid=grid) cells.extend(raw_cells) cells[0]['point'] = Point(x=50, y=50, z=50) # updating an incorrect index will not update the cell at index 0 cells.update_voxel_index([1, 3]) assert_array_equal(cells.get_neighboring_cells(cells[2]), [0, 2, 3]) assert cells._reverse_voxel_index[0] == grid.get_voxel(point) # this should correctly update the voxel index cells.update_voxel_index([0]) assert_array_equal(cells.get_neighboring_cells(cells[0]), [0]) assert cells._reverse_voxel_index[0] == grid.get_voxel(cells[0]['point'])
def test_get_neighboring_cells(grid: RectangularGrid): point = Point(x=4.5, y=4.5, z=4.5) raw_cells = [CellData.create_cell(point=point) for _ in range(5)] raw_cells[1]['point'] = Point(x=-1, y=4.5, z=4.5) raw_cells[4]['point'] = Point(x=4.5, y=4.5, z=-1) cells = CellList(grid=grid) cells.extend(raw_cells) assert_array_equal(cells.get_neighboring_cells(cells[0]), [0, 2, 3]) assert_array_equal(cells.get_cells_in_voxel(Voxel(x=0, y=0, z=0)), [0, 2, 3])
def convert_cells_to_vtk(cells: CellList) -> vtkPolyData: cell_data: CellData = cells.cell_data live_cells = cells.alive() cell_data = cell_data[live_cells] fields = dict(cell_data.dtype.fields) # type: ignore fields.pop('point') points = vtkPoints() poly = vtkPolyData() poly.SetPoints(points) if not len(cell_data): return poly # vtk uses coordinate ordering x, y, z while we use z, y, x. points.SetData(numpy_to_vtk(np.flip(cell_data['point'], axis=1))) point_data = poly.GetPointData() for field, (dtype, *_) in fields.items(): data = cell_data[field] # numpy_to_vtk doesn't handle bool for some reason if dtype == np.dtype('bool'): data = data.astype(np.dtype('uint8')) # noinspection PyBroadException try: scalar = numpy_to_vtk(data) except Exception: print(f'Unhandled data type in field {field}') continue scalar.SetName(field) point_data.AddArray(scalar) return poly
def test_out_of_memory_error(grid: RectangularGrid, cell: CellData): cell_list = CellList(grid=grid, max_cells=1) cell_list.append(cell) with raises(Exception): cell_list.append(cell)
def test_serialize(cell_list: CellList, hdf5_group: Group): cell_list_group = cell_list.save(hdf5_group, 'test', {}) assert cell_list_group['cell_data'].shape == (len(cell_list), ) assert cell_list_group['cell_data'].dtype == cell_list.cell_data.dtype
def cell_list(grid: RectangularGrid, point: Point): cells = CellList.create_from_seed(grid=grid, point=point) yield cells
def interact_with_aspergillus( *, phagocyte_cell: PhagocyteCellData, phagocyte_cell_index: int, phagocyte_cells: CellList, aspergillus_cell: 'AfumigatusCellData', aspergillus_cell_index: int, phagocyte: PhagocyteModuleState, phagocytize: bool = False, ) -> None: """ Possibly have a phagocyte phagocytize a fungal cell. Parameters ---------- phagocyte_cell : PhagocyteCellData phagocyte_cell_index: int aspergillus_cell : AfumigatusCellData aspergillus_cell_index : int phagocyte : PhagocyteState phagocytize : bool """ from nlisim.modules.afumigatus import AfumigatusCellState, AfumigatusCellStatus # We cannot internalize an already internalized fungal cell if aspergillus_cell['state'] != AfumigatusCellState.FREE: return # internalize conidia if phagocytize or aspergillus_cell['status'] in { AfumigatusCellStatus.RESTING_CONIDIA, AfumigatusCellStatus.SWELLING_CONIDIA, AfumigatusCellStatus.STERILE_CONIDIA, }: if phagocyte_cell['status'] not in { PhagocyteStatus.NECROTIC, PhagocyteStatus.APOPTOTIC, PhagocyteStatus.DEAD, }: # check to see if we have room before we add in another cell to the phagosome num_cells_in_phagosome = np.sum(phagocyte_cell['phagosome'] >= 0) if num_cells_in_phagosome < phagocyte.max_conidia: aspergillus_cell['state'] = AfumigatusCellState.INTERNALIZING # place the fungal cell in the phagosome, # sorting makes sure that an 'empty' i.e. -1 slot is first phagocyte_cell['phagosome'].sort() phagocyte_cell['phagosome'][0] = aspergillus_cell_index # move the phagocyte to the location of the aspergillus phagocyte_cell['point'] = aspergillus_cell['point'] phagocyte_cells.update_voxel_index([phagocyte_cell_index]) # All phagocytes are activated by their interaction, except with resting conidia if aspergillus_cell['status'] == AfumigatusCellStatus.RESTING_CONIDIA: return phagocyte_cell['state'] = PhagocyteStatus.INTERACTING if phagocyte_cell['status'] != PhagocyteStatus.ACTIVE: # non-active phagocytes begin the activation stage if phagocyte_cell['status'] != PhagocyteStatus.ACTIVATING: # reset the counter, first time only phagocyte_cell['status_iteration'] = 0 phagocyte_cell['status'] = PhagocyteStatus.ACTIVATING else: # active phagocytes are kept active by resetting their iteration counter phagocyte_cell['status_iteration'] = 0