Module nlisim.modules.phagocyte
Expand source code
from abc import abstractmethod
from enum import IntEnum, unique
from typing import TYPE_CHECKING, Tuple
from attr import attrs
import numpy as np
from nlisim.cell import CellData, CellFields, CellList
from nlisim.coordinates import Point, Voxel
from nlisim.grid import RectangularGrid
from nlisim.module import ModuleModel, ModuleState
from nlisim.state import State
if TYPE_CHECKING: # prevent circular imports for type checking
from nlisim.modules.afumigatus import AfumigatusCellData
MAX_CONIDIA = (
30 # note: this the max that we can set the max to. i.e. not an actual model parameter
)
class PhagocyteCellData(CellData):
PHAGOCYTE_FIELDS: CellFields = [
('phagosome', np.int64, MAX_CONIDIA),
]
dtype = np.dtype(CellData.FIELDS + PHAGOCYTE_FIELDS, align=True) # type: ignore
@classmethod
def create_cell_tuple(
cls,
**kwargs,
) -> Tuple:
initializer = {
'phagosome': kwargs.get('phagosome', -1 * np.ones(MAX_CONIDIA, dtype=np.int64)),
}
# ensure that these come in the correct order
return CellData.create_cell_tuple(**kwargs) + tuple(
[initializer[key] for key, *_ in PhagocyteCellData.PHAGOCYTE_FIELDS]
)
@attrs(kw_only=True)
class PhagocyteModuleState(ModuleState):
max_conidia: int # units: count
class PhagocyteModel(ModuleModel):
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])
@abstractmethod
def single_step_probabilistic_drift(
self, state: State, cell: PhagocyteCellData, voxel: Voxel
) -> Point:
...
@staticmethod
def release_phagosome(state: State, phagocyte_cell: PhagocyteCellData) -> None:
"""
Release afumigatus cells in the phagosome
Parameters
----------
state : State
global simulation state
phagocyte_cell : PhagocyteCellData
Returns
-------
Nothing
"""
from nlisim.modules.afumigatus import AfumigatusCellState, AfumigatusState
afumigatus: AfumigatusState = state.afumigatus
for fungal_cell_index in phagocyte_cell['phagosome']:
if fungal_cell_index == -1:
continue
afumigatus.cells[fungal_cell_index]['state'] = AfumigatusCellState.RELEASING
phagocyte_cell['phagosome'][:] = -1
# TODO: better name
@unique
class PhagocyteState(IntEnum):
FREE = 0
INTERACTING = 1
# TODO: name
@unique
class PhagocyteStatus(IntEnum):
INACTIVE = 0
INACTIVATING = 1
RESTING = 2
ACTIVATING = 3
ACTIVE = 4
APOPTOTIC = 5
NECROTIC = 6
DEAD = 7
ANERGIC = 8
INTERACTING = 9
# noinspection PyUnresolvedReferences
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
Functions
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)
-
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
Expand source code
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
Classes
class PhagocyteCellData (arg: Union[int, Iterable[ForwardRef('CellData')]], initialize: bool = False, **kwargs)
-
A low-level data contain for an array cells.
This class is a subtype of numpy.recarray containing the lowest level representation of a list of "cells" in a simulation. The underlying data format of this type are identical to a simple array of C structures with the fields given in the static "dtype" variable.
The base class contains only a single coordinate representing the location of the center of the cell. Most implementations will want to override this class to append more fields. Subclasses must also override the base implementation of
create_cell
to construct a single record containing the additional fields.For example, the following derived class adds an addition floating point value associated with each cell.
class DerivedCell(CellData): FIELDS = CellData.FIELDS + [ ('iron_content', 'f8') ] dtype = np.dtype(CellData.FIELDS, align=True) @classmethod def create_cell_tuple(cls, iron_content=0, **kwargs) -> Tuple: return CellData.create_cell_tuple(**kwargs) + (iron_content,)
Expand source code
class PhagocyteCellData(CellData): PHAGOCYTE_FIELDS: CellFields = [ ('phagosome', np.int64, MAX_CONIDIA), ] dtype = np.dtype(CellData.FIELDS + PHAGOCYTE_FIELDS, align=True) # type: ignore @classmethod def create_cell_tuple( cls, **kwargs, ) -> Tuple: initializer = { 'phagosome': kwargs.get('phagosome', -1 * np.ones(MAX_CONIDIA, dtype=np.int64)), } # ensure that these come in the correct order return CellData.create_cell_tuple(**kwargs) + tuple( [initializer[key] for key, *_ in PhagocyteCellData.PHAGOCYTE_FIELDS] )
Ancestors
- CellData
- numpy.ndarray
Subclasses
Class variables
var PHAGOCYTE_FIELDS : List[Union[Tuple[str, numpy.dtype], Tuple[str, Type[Any]], Tuple[str, Type[Any], int], Tuple[str, str], Tuple[str, str, int]]]
Inherited members
class PhagocyteModel (config: SimulationConfig)
-
Expand source code
class PhagocyteModel(ModuleModel): 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]) @abstractmethod def single_step_probabilistic_drift( self, state: State, cell: PhagocyteCellData, voxel: Voxel ) -> Point: ... @staticmethod def release_phagosome(state: State, phagocyte_cell: PhagocyteCellData) -> None: """ Release afumigatus cells in the phagosome Parameters ---------- state : State global simulation state phagocyte_cell : PhagocyteCellData Returns ------- Nothing """ from nlisim.modules.afumigatus import AfumigatusCellState, AfumigatusState afumigatus: AfumigatusState = state.afumigatus for fungal_cell_index in phagocyte_cell['phagosome']: if fungal_cell_index == -1: continue afumigatus.cells[fungal_cell_index]['state'] = AfumigatusCellState.RELEASING phagocyte_cell['phagosome'][:] = -1
Ancestors
Subclasses
Static methods
def release_phagosome(state: State, phagocyte_cell: PhagocyteCellData) ‑> None
-
Release afumigatus cells in the phagosome
Parameters
state
:State
- global simulation state
phagocyte_cell
:PhagocyteCellData
Returns
Nothing
Expand source code
@staticmethod def release_phagosome(state: State, phagocyte_cell: PhagocyteCellData) -> None: """ Release afumigatus cells in the phagosome Parameters ---------- state : State global simulation state phagocyte_cell : PhagocyteCellData Returns ------- Nothing """ from nlisim.modules.afumigatus import AfumigatusCellState, AfumigatusState afumigatus: AfumigatusState = state.afumigatus for fungal_cell_index in phagocyte_cell['phagosome']: if fungal_cell_index == -1: continue afumigatus.cells[fungal_cell_index]['state'] = AfumigatusCellState.RELEASING phagocyte_cell['phagosome'][:] = -1
Methods
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
Expand source code
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 single_step_probabilistic_drift(self, state: State, cell: PhagocyteCellData, voxel: Voxel) ‑> Point
-
Expand source code
@abstractmethod def single_step_probabilistic_drift( self, state: State, cell: PhagocyteCellData, voxel: Voxel ) -> Point: ...
Inherited members
class PhagocyteModuleState (*, global_state: State)
-
Base type intended to store the state for simulation modules.
This class contains serialization support for basic types (float, int, str, bool) and numpy arrays of those types. Modules containing more complicated state must override the serialization mechanism with custom behavior.
Method generated by attrs for class PhagocyteModuleState.
Expand source code
class PhagocyteModuleState(ModuleState): max_conidia: int # units: count
Ancestors
Subclasses
Class variables
var max_conidia : int
Inherited members
class PhagocyteState (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
An enumeration.
Expand source code
class PhagocyteState(IntEnum): FREE = 0 INTERACTING = 1
Ancestors
- enum.IntEnum
- builtins.int
- enum.Enum
Class variables
var FREE
var INTERACTING
class PhagocyteStatus (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
An enumeration.
Expand source code
class PhagocyteStatus(IntEnum): INACTIVE = 0 INACTIVATING = 1 RESTING = 2 ACTIVATING = 3 ACTIVE = 4 APOPTOTIC = 5 NECROTIC = 6 DEAD = 7 ANERGIC = 8 INTERACTING = 9
Ancestors
- enum.IntEnum
- builtins.int
- enum.Enum
Class variables
var ACTIVATING
var ACTIVE
var ANERGIC
var APOPTOTIC
var DEAD
var INACTIVATING
var INACTIVE
var INTERACTING
var NECROTIC
var RESTING