示例#1
0
文件: fungus.py 项目: knappa/nlisim
    def initialize_spores(self, tissue: np.ndarray, init_num: int):
        """Initialize spores on epithelium cells."""
        grid = self.grid
        if init_num > 0:
            points = np.zeros((init_num, 3))
            indices = np.argwhere(tissue == TissueTypes.EPITHELIUM.value)
            if len(indices) > 0:
                rg.shuffle(indices)
                for i in range(init_num):
                    # putting in some protection for the occasional time that we place the cell on
                    # the boundary of the voxel-space
                    if indices[i][2] == grid.xv.shape[0] - 1:
                        x = grid.xv[indices[i][2]]
                    else:
                        x = rg.uniform(grid.xv[indices[i][2]],
                                       grid.xv[indices[i][2] + 1])

                    if indices[i][1] == grid.yv.shape[0] - 1:
                        y = grid.yv[indices[i][1]]
                    else:
                        y = rg.uniform(grid.yv[indices[i][1]],
                                       grid.yv[indices[i][1] + 1])

                    if indices[i][0] == grid.zv.shape[0] - 1:
                        z = grid.zv[indices[i][0]]
                    else:
                        z = rg.uniform(grid.zv[indices[i][0]],
                                       grid.zv[indices[i][0] + 1])

                    point = Point(x=x, y=y, z=z)
                    points[i] = point

                self.spawn_spores(points)
    def initialize(self, state: State):
        pneumocyte: PneumocyteState = state.pneumocyte
        voxel_volume: float = state.voxel_volume
        time_step_size: float = self.time_step
        lung_tissue: np.ndarray = state.lung_tissue

        pneumocyte.max_conidia = self.config.getint(
            'max_conidia')  # units: conidia
        pneumocyte.time_to_rest = self.config.getint(
            'time_to_rest')  # units: hours
        pneumocyte.time_to_change_state = self.config.getint(
            'time_to_change_state')  # units: hours
        pneumocyte.p_tnf_qtty = self.config.getfloat(
            'p_tnf_qtty')  # units: atto-mol * cell^-1 * h^-1
        pneumocyte.pr_p_int_param = self.config.getfloat('pr_p_int_param')

        # computed values
        pneumocyte.iter_to_rest = int(
            pneumocyte.time_to_rest *
            (60 /
             self.time_step))  # units: hours * (min/hour) / (min/step) = step
        pneumocyte.iter_to_change_state = int(
            pneumocyte.time_to_change_state *
            (60 /
             self.time_step))  # units: hours * (min/hour) / (min/step) = step
        pneumocyte.pr_p_int = -math.expm1(
            -time_step_size / 60 /
            (voxel_volume * pneumocyte.pr_p_int_param))  # units: probability

        # initialize cells, placing one per epithelial voxel
        dz_field: np.ndarray = state.grid.delta(axis=0)
        dy_field: np.ndarray = state.grid.delta(axis=1)
        dx_field: np.ndarray = state.grid.delta(axis=2)
        epithelial_voxels = list(
            zip(*np.where(lung_tissue == TissueType.EPITHELIUM)))
        rg.shuffle(epithelial_voxels)
        for vox_z, vox_y, vox_x in epithelial_voxels[:self.config.
                                                     getint('count')]:
            # the x,y,z coordinates are in the centers of the grids
            z = state.grid.z[vox_z]
            y = state.grid.y[vox_y]
            x = state.grid.x[vox_x]
            dz = dz_field[vox_z, vox_y, vox_x]
            dy = dy_field[vox_z, vox_y, vox_x]
            dx = dx_field[vox_z, vox_y, vox_x]
            pneumocyte.cells.append(
                PneumocyteCellData.create_cell(point=Point(
                    x=x + rg.uniform(-dx / 2, dx / 2),
                    y=y + rg.uniform(-dy / 2, dy / 2),
                    z=z + rg.uniform(-dz / 2, dz / 2),
                )))

        return state
示例#3
0
    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.macrophage import MacrophageCellData, MacrophageState
        from nlisim.modules.phagocyte import PhagocyteState, PhagocyteStatus

        il10: IL10State = state.il10
        macrophage: MacrophageState = state.macrophage
        molecules: MoleculesState = state.molecules
        voxel_volume: float = state.voxel_volume
        grid: RectangularGrid = state.grid

        # active Macrophages secrete il10 and non-dead macrophages can become inactivated by il10
        for macrophage_cell_index in macrophage.cells.alive():
            macrophage_cell: MacrophageCellData = macrophage.cells[
                macrophage_cell_index]
            macrophage_cell_voxel: Voxel = grid.get_voxel(
                macrophage_cell['point'])

            if (macrophage_cell['status'] == PhagocyteStatus.ACTIVE and
                    macrophage_cell['state'] == PhagocyteState.INTERACTING):
                il10.grid[tuple(macrophage_cell_voxel
                                )] += il10.macrophage_secretion_rate_unit_t

            if macrophage_cell['status'] not in {
                    PhagocyteStatus.DEAD,
                    PhagocyteStatus.APOPTOTIC,
                    PhagocyteStatus.NECROTIC,
            } and (activation_function(
                    x=il10.grid[tuple(macrophage_cell_voxel)],
                    k_d=il10.k_d,
                    h=self.time_step / 60,  # units: (min/step) / (min/hour)
                    volume=voxel_volume,
                    b=1,
            ) > rg.uniform()):
                # inactive cells stay inactive, others become inactivating
                if macrophage_cell['status'] != PhagocyteStatus.INACTIVE:
                    macrophage_cell['status'] = PhagocyteStatus.INACTIVATING
                macrophage_cell['status_iteration'] = 0

        # Degrade IL10
        il10.grid *= il10.half_life_multiplier
        il10.grid *= turnover_rate(
            x=np.ones(shape=il10.grid.shape, dtype=np.float64),
            x_system=0.0,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

        # Diffusion of IL10
        il10.grid[:] = apply_diffusion(
            variable=il10.grid,
            laplacian=molecules.laplacian,
            diffusivity=molecules.diffusion_constant,
            dt=self.time_step,
        )

        return state
示例#4
0
    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.neutrophil import NeutrophilCellData, NeutrophilState
        from nlisim.modules.phagocyte import PhagocyteStatus

        il8: IL8State = state.il8
        molecules: MoleculesState = state.molecules
        neutrophil: NeutrophilState = state.neutrophil
        voxel_volume: float = state.voxel_volume
        grid: RectangularGrid = state.grid

        # IL8 activates neutrophils
        for neutrophil_cell_index in neutrophil.cells.alive():
            neutrophil_cell: NeutrophilCellData = neutrophil.cells[
                neutrophil_cell_index]
            if neutrophil_cell['status'] in {
                    PhagocyteStatus.RESTING or PhagocyteStatus.ACTIVE
            }:
                neutrophil_cell_voxel: Voxel = grid.get_voxel(
                    neutrophil_cell['point'])
                if (activation_function(
                        x=il8.grid[tuple(neutrophil_cell_voxel)],
                        k_d=il8.k_d,
                        h=self.time_step /
                        60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=1,
                ) > rg.uniform()):
                    neutrophil_cell['status'] = PhagocyteStatus.ACTIVE
                    neutrophil_cell['status_iteration'] = 0

        # Degrade IL8
        il8.grid *= il8.half_life_multiplier
        il8.grid *= turnover_rate(
            x=np.ones(shape=il8.grid.shape, dtype=np.float64),
            x_system=0.0,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

        # Diffusion of IL8
        il8.grid[:] = apply_diffusion(
            variable=il8.grid,
            laplacian=molecules.laplacian,
            diffusivity=molecules.diffusion_constant,
            dt=self.time_step,
        )

        return state
    def update_status(self, state: State,
                      neutrophil_cell: NeutrophilCellData) -> None:
        """
        Update the status of the cell, progressing between states after a certain number of ticks.

        Parameters
        ----------
        state : State
            global simulation state
        neutrophil_cell : NeutrophilCellData

        Returns
        -------
        nothing
        """
        neutrophil: NeutrophilState = state.neutrophil

        if neutrophil_cell['status'] in {
                PhagocyteStatus.NECROTIC, PhagocyteStatus.APOPTOTIC
        }:
            self.release_phagosome(state, neutrophil_cell)
            # releases iron & dies later

        elif rg.uniform() < neutrophil.apoptosis_probability:
            neutrophil_cell['status'] = PhagocyteStatus.APOPTOTIC

        elif neutrophil_cell['status'] == PhagocyteStatus.ACTIVE:
            if neutrophil_cell[
                    'status_iteration'] >= neutrophil.iter_to_change_state:
                neutrophil_cell['status_iteration'] = 0
                neutrophil_cell['tnfa'] = False
                neutrophil_cell['status'] = PhagocyteStatus.RESTING
                neutrophil_cell['state'] = PhagocyteState.FREE
            else:
                neutrophil_cell['status_iteration'] += 1

        elif neutrophil_cell['status'] == PhagocyteStatus.ACTIVATING:
            if neutrophil_cell[
                    'status_iteration'] >= neutrophil.iter_to_change_state:
                neutrophil_cell['status_iteration'] = 0
                neutrophil_cell['status'] = PhagocyteStatus.ACTIVE
            else:
                neutrophil_cell['status_iteration'] += 1
    def advance(self, state: State, previous_time: float):
        """Advance the state by a single time step."""
        macrophage: MacrophageState = state.macrophage

        for macrophage_cell_index in macrophage.cells.alive():
            macrophage_cell = macrophage.cells[macrophage_cell_index]

            num_cells_in_phagosome = np.sum(macrophage_cell['phagosome'] >= 0)

            self.update_status(state, macrophage_cell, num_cells_in_phagosome)

            if (num_cells_in_phagosome == 0
                    and rg.uniform() < macrophage.prob_death_per_timestep
                    and len(macrophage.cells.alive()) > macrophage.min_ma):
                macrophage_cell['status'] = PhagocyteStatus.DEAD
                macrophage_cell['dead'] = True

            if not macrophage_cell['fpn']:
                if macrophage_cell[
                        'fpn_iteration'] >= macrophage.iter_to_change_state:
                    macrophage_cell['fpn_iteration'] = 0
                    macrophage_cell['fpn'] = True
                else:
                    macrophage_cell['fpn_iteration'] += 1

            # Movement
            if macrophage_cell['status'] == PhagocyteStatus.ACTIVE:
                max_move_step = (macrophage.ma_move_rate_act * self.time_step
                                 )  # (µm/min) * (min/step) = µm * step
            else:
                max_move_step = (macrophage.ma_move_rate_rest * self.time_step
                                 )  # (µm/min) * (min/step) = µm * step
            move_step: int = rg.poisson(max_move_step)
            # move the cell 1 µm, move_step number of times
            for _ in range(move_step):
                self.single_step_move(state, macrophage_cell,
                                      macrophage_cell_index, macrophage.cells)

        # Recruitment
        self.recruit_macrophages(state)

        return state
示例#7
0
def choose_voxel_by_prob(voxels: Tuple[Voxel, ...], default_value: Voxel,
                         weights: np.ndarray) -> Voxel:
    """
    Choose a voxels using a non-normalized probability distribution.

    If weights are all zero, the default value is chosen.

    Parameters
    ----------
    voxels
        an tuple of voxels
    default_value
        default return value for when weights are uniformly zero
    weights
        an array of non-negative (unchecked) unnormalized probabilities/weights for the voxels

    Returns
    -------
    a Voxel, from voxels, chosen by the probability distribution, or the default
    """
    normalization_constant = np.sum(weights)
    if normalization_constant <= 0:
        # e.g. if all neighbors are air
        return default_value

    # prepend a zero to detect `failure by zero' in the argmax below
    normalized_weights = np.concatenate(
        (np.array([0.0]), weights / normalization_constant))

    # sample from distribution given by normalized weights
    random_voxel_idx: int = int(
        np.argmax(np.cumsum(normalized_weights) - rg.uniform() > 0.0) - 1)
    if random_voxel_idx < 0:
        # the only way the 0th could be chosen is by argmax failing
        return default_value
    else:
        return voxels[random_voxel_idx]
示例#8
0
    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.macrophage import MacrophageCellData, MacrophageState
        from nlisim.modules.neutrophil import NeutrophilCellData, NeutrophilState
        from nlisim.modules.phagocyte import PhagocyteStatus
        from nlisim.modules.pneumocyte import PneumocyteCellData, PneumocyteState

        mip2: MIP2State = state.mip2
        molecules: MoleculesState = state.molecules
        neutrophil: NeutrophilState = state.neutrophil
        pneumocyte: PneumocyteState = state.pneumocyte
        macrophage: MacrophageState = state.macrophage
        grid: RectangularGrid = state.grid
        voxel_volume = state.voxel_volume

        # interact with neutrophils
        neutrophil_activation: np.ndarray = activation_function(
            x=mip2.grid,
            k_d=mip2.k_d,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            volume=voxel_volume,
            b=1,
        )
        for neutrophil_cell_index in neutrophil.cells.alive():
            neutrophil_cell: NeutrophilCellData = neutrophil.cells[neutrophil_cell_index]
            neutrophil_cell_voxel: Voxel = grid.get_voxel(neutrophil_cell['point'])

            if (
                neutrophil_cell['status'] == PhagocyteStatus.RESTING
                and neutrophil_activation[tuple(neutrophil_cell_voxel)] > rg.uniform()
            ):
                neutrophil_cell['status'] = PhagocyteStatus.ACTIVATING
                neutrophil_cell['status_iteration'] = 0
            elif neutrophil_cell['tnfa']:
                mip2.grid[tuple(neutrophil_cell_voxel)] += mip2.neutrophil_secretion_rate_unit_t
                if neutrophil_activation[tuple(neutrophil_cell_voxel)] > rg.uniform():
                    neutrophil_cell['status_iteration'] = 0

        # interact with pneumocytes
        for pneumocyte_cell_index in pneumocyte.cells.alive():
            pneumocyte_cell: PneumocyteCellData = pneumocyte.cells[pneumocyte_cell_index]

            if pneumocyte_cell['tnfa']:
                pneumocyte_cell_voxel: Voxel = grid.get_voxel(pneumocyte_cell['point'])
                mip2.grid[tuple(pneumocyte_cell_voxel)] += mip2.pneumocyte_secretion_rate_unit_t

        # interact with macrophages
        for macrophage_cell_index in macrophage.cells.alive():
            macrophage_cell: MacrophageCellData = macrophage.cells[macrophage_cell_index]

            if macrophage_cell['tnfa']:
                macrophage_cell_voxel: Voxel = grid.get_voxel(macrophage_cell['point'])
                mip2.grid[tuple(macrophage_cell_voxel)] += mip2.macrophage_secretion_rate_unit_t

        # Degrade MIP2
        mip2.grid *= mip2.half_life_multiplier
        mip2.grid *= turnover_rate(
            x=np.array(1.0, dtype=np.float64),
            x_system=0.0,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

        # Diffusion of MIP2
        mip2.grid[:] = apply_diffusion(
            variable=mip2.grid,
            laplacian=molecules.laplacian,
            diffusivity=molecules.diffusion_constant,
            dt=self.time_step,
        )

        return state
    def recruit_macrophages(self, state: State) -> None:
        """
        Recruit macrophages based on MIP1b activation

        Parameters
        ----------
        state : State
            global simulation state

        Returns
        -------
        nothing
        """
        from nlisim.modules.mip1b import MIP1BState
        from nlisim.util import TissueType, activation_function

        macrophage: MacrophageState = state.macrophage
        mip1b: MIP1BState = state.mip1b
        voxel_volume: float = state.voxel_volume
        space_volume: float = state.space_volume
        lung_tissue = state.lung_tissue

        # 1. compute number of macrophages to recruit
        num_live_macrophages = len(macrophage.cells.alive())
        avg = (macrophage.recruitment_rate * np.sum(mip1b.grid) *
               (1 - num_live_macrophages / macrophage.max_ma) /
               (mip1b.k_d * space_volume))
        number_to_recruit = max(
            np.random.poisson(avg) if avg > 0 else 0,
            macrophage.min_ma - num_live_macrophages)
        # 2. get voxels for new macrophages, based on activation
        if number_to_recruit > 0:
            activation_voxels = zip(*np.where(
                np.logical_and(
                    activation_function(
                        x=mip1b.grid,
                        k_d=mip1b.k_d,
                        h=self.time_step / 60,
                        volume=voxel_volume,
                        b=macrophage.rec_bias,
                    ) < rg.uniform(size=mip1b.grid.shape),
                    lung_tissue != TissueType.AIR,
                )))
            dz_field: np.ndarray = state.grid.delta(axis=0)
            dy_field: np.ndarray = state.grid.delta(axis=1)
            dx_field: np.ndarray = state.grid.delta(axis=2)
            for coordinates in rg.choice(tuple(activation_voxels),
                                         size=number_to_recruit,
                                         replace=True):
                vox_z, vox_y, vox_x = coordinates
                # the x,y,z coordinates are in the centers of the grids
                z = state.grid.z[vox_z]
                y = state.grid.y[vox_y]
                x = state.grid.x[vox_x]
                dz = dz_field[vox_z, vox_y, vox_x]
                dy = dy_field[vox_z, vox_y, vox_x]
                dx = dx_field[vox_z, vox_y, vox_x]
                self.create_macrophage(
                    state=state,
                    x=x + rg.uniform(-dx / 2, dx / 2),
                    y=y + rg.uniform(-dy / 2, dy / 2),
                    z=z + rg.uniform(-dz / 2, dz / 2),
                )
    def initialize(self, state: State):
        from nlisim.util import TissueType

        macrophage: MacrophageState = state.macrophage
        lung_tissue = state.lung_tissue
        time_step_size: float = self.time_step

        macrophage.max_conidia = self.config.getint(
            'max_conidia')  # (from phagocyte model) units: count
        macrophage.time_to_rest = self.config.getint(
            'time_to_rest')  # units: min
        macrophage.time_to_change_state = self.config.getint(
            'time_to_change_state')  # units: hours
        macrophage.ma_internal_iron = self.config.getfloat(
            'ma_internal_iron')  # units: atto-mols

        macrophage.max_ma = self.config.getint('max_ma')  # units: count
        macrophage.min_ma = self.config.getint('min_ma')  # units: count
        macrophage.init_num_macrophages = self.config.getint(
            'init_num_macrophages')  # units: count

        macrophage.recruitment_rate = self.config.getfloat('recruitment_rate')
        macrophage.rec_bias = self.config.getfloat('rec_bias')
        macrophage.drift_bias = self.config.getfloat('drift_bias')

        macrophage.ma_move_rate_act = self.config.getfloat(
            'ma_move_rate_act')  # µm/min
        macrophage.ma_move_rate_rest = self.config.getfloat(
            'ma_move_rate_rest')  # µm/min

        macrophage.half_life = self.config.getfloat(
            'ma_half_life')  # units: hours

        # UNUSED:
        # macrophage.kd_ma_iron = self.config.getfloat('kd_ma_iron')
        # macrophage.ma_vol = self.config.getfloat('ma_vol')

        # computed values
        macrophage.iter_to_rest = int(
            macrophage.time_to_rest /
            self.time_step)  # units: min / (min/step) = steps
        macrophage.iter_to_change_state = int(
            macrophage.time_to_change_state *
            (60 /
             time_step_size))  # units: hours * (min/hour) / (min/step) = step

        macrophage.prob_death_per_timestep = -math.log(0.5) / (
            macrophage.half_life * (60 / time_step_size)
        )  # units: 1/(  hours * (min/hour) / (min/step)  ) = 1/step

        # initialize cells, placing them randomly
        locations = list(zip(*np.where(lung_tissue != TissueType.AIR)))
        dz_field: np.ndarray = state.grid.delta(axis=0)
        dy_field: np.ndarray = state.grid.delta(axis=1)
        dx_field: np.ndarray = state.grid.delta(axis=2)
        for vox_z, vox_y, vox_x in random.choices(
                locations, k=macrophage.init_num_macrophages):
            # the x,y,z coordinates are in the centers of the grids
            z = state.grid.z[vox_z]
            y = state.grid.y[vox_y]
            x = state.grid.x[vox_x]
            dz = dz_field[vox_z, vox_y, vox_x]
            dy = dy_field[vox_z, vox_y, vox_x]
            dx = dx_field[vox_z, vox_y, vox_x]
            self.create_macrophage(
                state=state,
                x=x + rg.uniform(-dx / 2, dx / 2),
                y=y + rg.uniform(-dy / 2, dy / 2),
                z=z + rg.uniform(-dz / 2, dz / 2),
                iron_pool=macrophage.ma_internal_iron,
            )

        return state
    def advance(self, state: State, previous_time: float):
        """Advance the state by a single time step."""
        from nlisim.modules.afumigatus import (
            Afumigatus,
            AfumigatusCellData,
            AfumigatusCellStatus,
            AfumigatusState,
        )
        from nlisim.modules.iron import IronState
        from nlisim.modules.macrophage import MacrophageCellData, MacrophageState

        neutrophil: NeutrophilState = state.neutrophil
        macrophage: MacrophageState = state.macrophage
        afumigatus: AfumigatusState = state.afumigatus
        iron: IronState = state.iron
        grid: RectangularGrid = state.grid
        voxel_volume: float = state.voxel_volume
        space_volume: float = state.space_volume

        for neutrophil_cell_index in neutrophil.cells.alive():
            neutrophil_cell = neutrophil.cells[neutrophil_cell_index]
            neutrophil_cell_voxel: Voxel = grid.get_voxel(
                neutrophil_cell['point'])

            self.update_status(state, neutrophil_cell)

            # ---------- interactions

            # dead and dying cells release iron
            if neutrophil_cell['status'] in {
                    PhagocyteStatus.NECROTIC,
                    PhagocyteStatus.APOPTOTIC,
                    PhagocyteStatus.DEAD,
            }:
                iron.grid[tuple(
                    neutrophil_cell_voxel)] += neutrophil_cell['iron_pool']
                neutrophil_cell['iron_pool'] = 0
                neutrophil_cell['dead'] = True

            # interact with fungus
            if neutrophil_cell[
                    'state'] == PhagocyteState.FREE and neutrophil_cell[
                        'status'] not in {
                            PhagocyteStatus.APOPTOTIC,
                            PhagocyteStatus.NECROTIC,
                            PhagocyteStatus.DEAD,
                        }:
                # get fungal cells in this voxel
                local_aspergillus = afumigatus.cells.get_cells_in_voxel(
                    neutrophil_cell_voxel)
                for aspergillus_cell_index in local_aspergillus:
                    aspergillus_cell: AfumigatusCellData = afumigatus.cells[
                        aspergillus_cell_index]
                    if aspergillus_cell['dead']:
                        continue

                    if aspergillus_cell['status'] in {
                            AfumigatusCellStatus.HYPHAE,
                            AfumigatusCellStatus.GERM_TUBE,
                    }:
                        # possibly kill the fungal cell, extracellularly
                        if rg.uniform() < neutrophil.pr_n_hyphae:
                            interact_with_aspergillus(
                                phagocyte_cell=neutrophil_cell,
                                phagocyte_cell_index=neutrophil_cell_index,
                                phagocyte_cells=neutrophil.cells,
                                aspergillus_cell=aspergillus_cell,
                                aspergillus_cell_index=aspergillus_cell_index,
                                phagocyte=neutrophil,
                            )
                            Afumigatus.kill_fungal_cell(
                                afumigatus=afumigatus,
                                afumigatus_cell=aspergillus_cell,
                                afumigatus_cell_index=aspergillus_cell_index,
                                iron=iron,
                                grid=grid,
                            )
                        else:
                            neutrophil_cell[
                                'state'] = PhagocyteState.INTERACTING

                    elif aspergillus_cell[
                            'status'] == AfumigatusCellStatus.SWELLING_CONIDIA:
                        if rg.uniform() < neutrophil.pr_n_phagocyte:
                            interact_with_aspergillus(
                                phagocyte_cell=neutrophil_cell,
                                phagocyte_cell_index=neutrophil_cell_index,
                                phagocyte_cells=neutrophil.cells,
                                aspergillus_cell=aspergillus_cell,
                                aspergillus_cell_index=aspergillus_cell_index,
                                phagocyte=neutrophil,
                            )

            # interact with macrophages:
            # if we are apoptotic, give our iron and phagosome to a nearby
            # present macrophage (if empty)
            if neutrophil_cell['status'] == PhagocyteStatus.APOPTOTIC:
                local_macrophages = macrophage.cells.get_cells_in_voxel(
                    neutrophil_cell_voxel)
                for macrophage_index in local_macrophages:
                    macrophage_cell: MacrophageCellData = macrophage.cells[
                        macrophage_index]
                    macrophage_num_cells_in_phagosome = np.sum(
                        macrophage_cell['phagosome'] >= 0)
                    # TODO: Henrique, why only if empty?
                    if macrophage_num_cells_in_phagosome == 0:
                        macrophage_cell['phagosome'] = neutrophil_cell[
                            'phagosome']
                        macrophage_cell['iron_pool'] += neutrophil_cell[
                            'iron_pool']
                        neutrophil_cell['iron_pool'] = 0.0
                        neutrophil_cell['status'] = PhagocyteStatus.DEAD
                        macrophage_cell['status'] = PhagocyteStatus.INACTIVE

            # Movement
            if neutrophil_cell['status'] == PhagocyteStatus.ACTIVE:
                max_move_step = neutrophil.n_move_rate_act * self.time_step
            else:
                max_move_step = neutrophil.n_move_rate_rest * self.time_step
            move_step: int = rg.poisson(max_move_step)
            # move the cell 1 µm, move_step number of times
            for _ in range(move_step):
                self.single_step_move(state, neutrophil_cell,
                                      neutrophil_cell_index, neutrophil.cells)
            # TODO: understand the meaning of the parameter here: moving randomly n steps is
            #  different than moving n steps in a random direction. Which is it?

        # Recruitment
        self.recruit_neutrophils(state, space_volume, voxel_volume)

        return state
    def advance(self, state: State, previous_time: float):
        """Advance the state by a single time step."""
        from nlisim.modules.afumigatus import (
            AfumigatusCellData,
            AfumigatusCellStatus,
            AfumigatusState,
        )

        # from nlisim.modules.il6 import IL6State
        # from nlisim.modules.il8 import IL8State
        from nlisim.modules.tnfa import TNFaState

        pneumocyte: PneumocyteState = state.pneumocyte
        afumigatus: AfumigatusState = state.afumigatus
        # il6: IL6State = getattr(state, 'il6', None)
        # il8: IL8State = getattr(state, 'il8', None)
        tnfa: TNFaState = state.tnfa
        grid: RectangularGrid = state.grid
        voxel_volume: float = state.voxel_volume

        for pneumocyte_cell_index in pneumocyte.cells.alive():
            pneumocyte_cell = pneumocyte.cells[pneumocyte_cell_index]
            pneumocyte_cell_voxel: Voxel = grid.get_voxel(
                pneumocyte_cell['point'])

            # self update
            if pneumocyte_cell['status'] == PhagocyteStatus.ACTIVE:
                if pneumocyte_cell[
                        'status_iteration'] >= pneumocyte.iter_to_rest:
                    pneumocyte_cell['status_iteration'] = 0
                    pneumocyte_cell['status'] = PhagocyteStatus.RESTING
                    pneumocyte_cell['tnfa'] = False
                else:
                    pneumocyte_cell['status_iteration'] += 1

            elif pneumocyte_cell['status'] == PhagocyteStatus.ACTIVATING:
                if pneumocyte_cell[
                        'status_iteration'] >= pneumocyte.iter_to_change_state:
                    pneumocyte_cell['status_iteration'] = 0
                    pneumocyte_cell['status'] = PhagocyteStatus.ACTIVE
                else:
                    pneumocyte_cell['status_iteration'] += 1

            # ----------- interactions

            # interact with fungus
            if pneumocyte_cell['status'] not in {
                    PhagocyteStatus.APOPTOTIC,
                    PhagocyteStatus.NECROTIC,
                    PhagocyteStatus.DEAD,
            }:
                local_aspergillus = afumigatus.cells.get_cells_in_voxel(
                    pneumocyte_cell_voxel)
                for aspergillus_index in local_aspergillus:
                    aspergillus_cell: AfumigatusCellData = afumigatus.cells[
                        aspergillus_index]

                    # skip resting conidia
                    if aspergillus_cell[
                            'status'] == AfumigatusCellStatus.RESTING_CONIDIA:
                        continue

                    if pneumocyte_cell['status'] != PhagocyteStatus.ACTIVE:
                        if rg.uniform() < pneumocyte.pr_p_int:
                            pneumocyte_cell[
                                'status'] = PhagocyteStatus.ACTIVATING
                    else:
                        # TODO: I don't get this, looks like it zeros out the iteration
                        #  when activating
                        pneumocyte_cell['status_iteration'] = 0

            # # secrete IL6
            # if il6 is not None and pneumocyte_cell['status'] == PhagocyteStatus.ACTIVE:
            #     il6.grid[tuple(pneumocyte_cell_voxel)] += pneumocyte.p_il6_qtty
            #
            # # secrete IL8
            # if il8 is not None and pneumocyte_cell['tnfa']:
            #     il8.grid[tuple(pneumocyte_cell_voxel)] += pneumocyte.p_il8_qtty

            # interact with TNFa
            if pneumocyte_cell['status'] == PhagocyteStatus.ACTIVE:
                if (activation_function(
                        x=tnfa.grid[tuple(pneumocyte_cell_voxel)],
                        k_d=tnfa.k_d,
                        h=self.time_step /
                        60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=1,
                ) < rg.uniform()):
                    pneumocyte_cell['status_iteration'] = 0
                    pneumocyte_cell['tnfa'] = True

                # secrete TNFa
                tnfa.grid[tuple(
                    pneumocyte_cell_voxel)] += pneumocyte.p_tnf_qtty

        return state
示例#13
0
    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.macrophage import MacrophageCellData, MacrophageState
        from nlisim.modules.phagocyte import PhagocyteStatus

        tgfb: TGFBState = state.tgfb
        molecules: MoleculesState = state.molecules
        macrophage: MacrophageState = state.macrophage
        voxel_volume: float = state.voxel_volume
        grid: RectangularGrid = state.grid

        for macrophage_cell_index in macrophage.cells.alive():
            macrophage_cell: MacrophageCellData = macrophage.cells[
                macrophage_cell_index]
            macrophage_cell_voxel: Voxel = grid.get_voxel(
                macrophage_cell['point'])

            if macrophage_cell['status'] == PhagocyteStatus.INACTIVE:
                tgfb.grid[tuple(macrophage_cell_voxel
                                )] += tgfb.macrophage_secretion_rate_unit_t
                if (activation_function(
                        x=tgfb.grid[tuple(macrophage_cell_voxel)],
                        k_d=tgfb.k_d,
                        h=self.time_step /
                        60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=1,
                ) > rg.uniform()):
                    macrophage_cell['status_iteration'] = 0

            elif macrophage_cell['status'] not in {
                    PhagocyteStatus.APOPTOTIC,
                    PhagocyteStatus.NECROTIC,
                    PhagocyteStatus.DEAD,
            }:
                if (activation_function(
                        x=tgfb.grid[tuple(macrophage_cell_voxel)],
                        k_d=tgfb.k_d,
                        h=self.time_step /
                        60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=1,
                ) > rg.uniform()):
                    macrophage_cell['status'] = PhagocyteStatus.INACTIVATING
                    macrophage_cell[
                        'status_iteration'] = 0  # Previously, was no reset of the status iteration

        # Degrade TGFB
        tgfb.grid *= tgfb.half_life_multiplier
        tgfb.grid *= turnover_rate(
            x=np.array(1.0, dtype=np.float64),
            x_system=0.0,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

        # Diffusion of TGFB
        tgfb.grid[:] = apply_diffusion(
            variable=tgfb.grid,
            laplacian=molecules.laplacian,
            diffusivity=molecules.diffusion_constant,
            dt=self.time_step,
        )

        return state
    def initialize(self, state: State):
        neutrophil: NeutrophilState = state.neutrophil
        voxel_volume = state.voxel_volume
        lung_tissue = state.lung_tissue

        neutrophil.init_num_neutrophils = self.config.getint(
            'init_num_neutrophils')  # units: count

        neutrophil.time_to_change_state = self.config.getfloat(
            'time_to_change_state')  # units: hours
        neutrophil.max_conidia = self.config.getint(
            'max_conidia')  # (from phagocyte model) units: count

        neutrophil.recruitment_rate = self.config.getfloat('recruitment_rate')
        neutrophil.rec_bias = self.config.getfloat('rec_bias')
        neutrophil.max_neutrophils = self.config.getfloat(
            'max_neutrophils')  # units: count
        neutrophil.n_frac = self.config.getfloat('n_frac')

        neutrophil.drift_bias = self.config.getfloat('drift_bias')
        neutrophil.n_move_rate_act = self.config.getfloat('n_move_rate_act')
        neutrophil.n_move_rate_rest = self.config.getfloat('n_move_rate_rest')

        neutrophil.pr_n_hyphae_param = self.config.getfloat(
            'pr_n_hyphae_param')
        neutrophil.pr_n_phagocyte_param = self.config.getfloat(
            'pr_n_phagocyte_param')

        neutrophil.half_life = self.config.getfloat(
            'half_life')  # units: hours

        # computed values
        neutrophil.apoptosis_probability = -math.log(0.5) / (
            neutrophil.half_life *
            (60 / self.time_step)  # units: hours*(min/hour)/(min/step)=steps
        )  # units: probability
        neutrophil.iter_to_change_state = int(
            neutrophil.time_to_change_state * 60 /
            self.time_step)  # units: hours * (min/hour) / (min/step) = steps
        neutrophil.pr_n_hyphae = -math.expm1(-self.time_step / 60 / (
            voxel_volume * neutrophil.pr_n_hyphae_param))  # units: probability
        neutrophil.pr_n_phagocyte = -math.expm1(
            -self.time_step / 60 /
            (voxel_volume *
             neutrophil.pr_n_phagocyte_param))  # units: probability

        # place initial neutrophils
        locations = list(zip(*np.where(lung_tissue != TissueType.AIR)))
        dz_field: np.ndarray = state.grid.delta(axis=0)
        dy_field: np.ndarray = state.grid.delta(axis=1)
        dx_field: np.ndarray = state.grid.delta(axis=2)
        for vox_z, vox_y, vox_x in random.choices(
                locations, k=neutrophil.init_num_neutrophils):
            # the x,y,z coordinates are in the centers of the grids
            z = state.grid.z[vox_z]
            y = state.grid.y[vox_y]
            x = state.grid.x[vox_x]
            dz = dz_field[vox_z, vox_y, vox_x]
            dy = dy_field[vox_z, vox_y, vox_x]
            dx = dx_field[vox_z, vox_y, vox_x]

            self.create_neutrophil(
                state=state,
                x=x + rg.uniform(-dx / 2, dx / 2),
                y=y + rg.uniform(-dy / 2, dy / 2),
                z=z + rg.uniform(-dz / 2, dz / 2),
            )

        return state
    def recruit_neutrophils(self, state: State, space_volume: float,
                            voxel_volume: float) -> None:
        """
        Recruit neutrophils based on MIP2 activation

        Parameters
        ----------
        state : State
            global simulation state
        space_volume : float
        voxel_volume : float

        Returns
        -------
        nothing
        """
        from nlisim.modules.mip2 import MIP2State
        from nlisim.util import TissueType, activation_function

        neutrophil: NeutrophilState = state.neutrophil
        mip2: MIP2State = state.mip2
        lung_tissue = state.lung_tissue

        # 1. compute number of neutrophils to recruit
        num_live_neutrophils = len(neutrophil.cells.alive())
        avg = (neutrophil.recruitment_rate * neutrophil.n_frac *
               np.sum(mip2.grid) *
               (1 - num_live_neutrophils / neutrophil.max_neutrophils) /
               (mip2.k_d * space_volume))
        number_to_recruit = np.random.poisson(avg) if avg > 0 else 0
        if number_to_recruit <= 0:
            return
        # 2. get voxels for new macrophages, based on activation
        activation_voxels = tuple(
            zip(*np.where(
                np.logical_and(
                    activation_function(
                        x=mip2.grid,
                        k_d=mip2.k_d,
                        h=self.time_step /
                        60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=neutrophil.rec_bias,
                    ) < rg.uniform(size=mip2.grid.shape),
                    lung_tissue != TissueType.AIR,
                ))))

        dz_field: np.ndarray = state.grid.delta(axis=0)
        dy_field: np.ndarray = state.grid.delta(axis=1)
        dx_field: np.ndarray = state.grid.delta(axis=2)
        for coordinates in rg.choice(activation_voxels,
                                     size=number_to_recruit,
                                     replace=True):
            vox_z, vox_y, vox_x = coordinates
            # the x,y,z coordinates are in the centers of the grids
            z = state.grid.z[vox_z]
            y = state.grid.y[vox_y]
            x = state.grid.x[vox_x]
            dz = dz_field[vox_z, vox_y, vox_x]
            dy = dy_field[vox_z, vox_y, vox_x]
            dx = dx_field[vox_z, vox_y, vox_x]
            self.create_neutrophil(
                state=state,
                x=x + rg.uniform(-dx / 2, dx / 2),
                y=y + rg.uniform(-dy / 2, dy / 2),
                z=z + rg.uniform(-dz / 2, dz / 2),
            )
示例#16
0
    def initialize(self, state: State):
        afumigatus: AfumigatusState = state.afumigatus
        voxel_volume = state.voxel_volume  # units: L
        lung_tissue = state.lung_tissue

        afumigatus.pr_ma_hyphae_param = self.config.getfloat('pr_ma_hyphae_param')
        afumigatus.pr_ma_phag_param = self.config.getfloat('pr_ma_phag_param')
        afumigatus.phag_affinity_t = self.config.getfloat('phag_affinity_t')

        afumigatus.pr_branch = self.config.getfloat('pr_branch')  # units: probability
        afumigatus.steps_to_bn_eval = self.config.getint('steps_to_bn_eval')  # units: steps

        afumigatus.conidia_vol = self.config.getfloat('conidia_vol')  # units: L
        afumigatus.hyphae_volume = self.config.getfloat('hyphae_volume')  # units: L
        afumigatus.hyphal_length = self.config.getfloat('hyphal_length')  # units: µm

        afumigatus.kd_lip = self.config.getfloat('kd_lip')  # units: aM

        afumigatus.time_to_swelling = self.config.getfloat('time_to_swelling')  # units: hours
        afumigatus.time_to_germinate = self.config.getfloat('time_to_germinate')  # units: hours
        afumigatus.time_to_grow = self.config.getfloat('time_to_grow')  # units: hours
        afumigatus.aspergillus_change_half_life = self.config.getfloat(
            'aspergillus_change_half_life'
        )  # units: hours

        # computed values
        afumigatus.init_iron = afumigatus.kd_lip * afumigatus.conidia_vol  # units: aM*L = atto-mols

        afumigatus.rel_phag_affinity_unit_t = self.time_step / afumigatus.phag_affinity_t

        afumigatus.pr_ma_hyphae = -math.expm1(
            -afumigatus.rel_phag_affinity_unit_t / (afumigatus.pr_ma_hyphae_param * voxel_volume)
        )  # exponent units:  ?/(?*L) = TODO
        afumigatus.pr_ma_phag = -math.expm1(
            -afumigatus.rel_phag_affinity_unit_t / (voxel_volume * afumigatus.pr_ma_phag_param)
        )  # exponent units:  ?/(?*L) = TODO

        afumigatus.iter_to_swelling = max(
            0, int(afumigatus.time_to_swelling * (60 / self.time_step) - 2)
        )  # units: hours * (min/hour) / (min/step) = steps TODO: -2?
        afumigatus.iter_to_germinate = max(
            0, int(afumigatus.time_to_germinate * (60 / self.time_step) - 2)
        )  # units: hours * (min/hour) / (min/step) = steps TODO: -2?
        afumigatus.iter_to_grow = max(
            0, int(afumigatus.time_to_grow * 60 / self.time_step) - 1
        )  # units: hours * (min/hour) / (min/step) = steps
        afumigatus.pr_aspergillus_change = -math.log(0.5) / (
            afumigatus.aspergillus_change_half_life * (60 / self.time_step)
        )

        # place cells for initial infection
        locations = list(zip(*np.where(lung_tissue == TissueType.EPITHELIUM)))
        dz_field: np.ndarray = state.grid.delta(axis=0)
        dy_field: np.ndarray = state.grid.delta(axis=1)
        dx_field: np.ndarray = state.grid.delta(axis=2)
        for vox_z, vox_y, vox_x in random.choices(
            locations, k=self.config.getint('init_infection_num')
        ):
            # the x,y,z coordinates are in the centers of the grids
            z = state.grid.z[vox_z]
            y = state.grid.y[vox_y]
            x = state.grid.x[vox_x]
            dz = dz_field[vox_z, vox_y, vox_x]
            dy = dy_field[vox_z, vox_y, vox_x]
            dx = dx_field[vox_z, vox_y, vox_x]
            afumigatus.cells.append(
                AfumigatusCellData.create_cell(
                    point=Point(
                        x=x + rg.uniform(-dx / 2, dx / 2),
                        y=y + rg.uniform(-dy / 2, dy / 2),
                        z=z + rg.uniform(-dz / 2, dz / 2),
                    ),
                    iron_pool=afumigatus.init_iron,
                )
            )

        return state
示例#17
0
    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.macrophage import MacrophageCellData, MacrophageState
        from nlisim.modules.neutrophil import NeutrophilCellData, NeutrophilState
        from nlisim.modules.phagocyte import PhagocyteStatus

        tnfa: TNFaState = state.tnfa
        molecules: MoleculesState = state.molecules
        macrophage: MacrophageState = state.macrophage
        neutrophil: NeutrophilState = state.neutrophil
        voxel_volume: float = state.voxel_volume
        grid: RectangularGrid = state.grid

        for macrophage_cell_index in macrophage.cells.alive():
            macrophage_cell: MacrophageCellData = macrophage.cells[macrophage_cell_index]
            macrophage_cell_voxel: Voxel = grid.get_voxel(macrophage_cell['point'])

            if macrophage_cell['status'] == PhagocyteStatus.ACTIVE:
                tnfa.grid[tuple(macrophage_cell_voxel)] += tnfa.macrophage_secretion_rate_unit_t

            if macrophage_cell['status'] in {PhagocyteStatus.RESTING, PhagocyteStatus.ACTIVE}:
                if (
                    activation_function(
                        x=tnfa.grid[tuple(macrophage_cell_voxel)],
                        k_d=tnfa.k_d,
                        h=self.time_step / 60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=1,
                    )
                    > rg.uniform()
                ):
                    if macrophage_cell['status'] == PhagocyteStatus.RESTING:
                        macrophage_cell['status'] = PhagocyteStatus.ACTIVATING
                    else:
                        macrophage_cell['status'] = PhagocyteStatus.ACTIVE
                    # Note: multiple activations will reset the 'clock'
                    macrophage_cell['status_iteration'] = 0
                    macrophage_cell['tnfa'] = True

        for neutrophil_cell_index in neutrophil.cells.alive():
            neutrophil_cell: NeutrophilCellData = neutrophil.cells[neutrophil_cell_index]
            neutrophil_cell_voxel: Voxel = grid.get_voxel(neutrophil_cell['point'])

            if neutrophil_cell['status'] == PhagocyteStatus.ACTIVE:
                tnfa.grid[tuple(neutrophil_cell_voxel)] += tnfa.neutrophil_secretion_rate_unit_t

            if neutrophil_cell['status'] in {PhagocyteStatus.RESTING, PhagocyteStatus.ACTIVE}:
                if (
                    activation_function(
                        x=tnfa.grid[tuple(neutrophil_cell_voxel)],
                        k_d=tnfa.k_d,
                        h=self.time_step / 60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=1,
                    )
                    > rg.uniform()
                ):
                    if neutrophil_cell['status'] == PhagocyteStatus.RESTING:
                        neutrophil_cell['status'] = PhagocyteStatus.ACTIVATING
                    else:
                        neutrophil_cell['status'] = PhagocyteStatus.ACTIVE
                    # Note: multiple activations will reset the 'clock'
                    neutrophil_cell['status_iteration'] = 0
                    neutrophil_cell['tnfa'] = True

        # Degrade TNFa
        tnfa.grid *= tnfa.half_life_multiplier
        tnfa.grid *= turnover_rate(
            x=np.array(1.0, dtype=np.float64),
            x_system=0.0,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

        # Diffusion of TNFa
        tnfa.grid[:] = apply_diffusion(
            variable=tnfa.grid,
            laplacian=molecules.laplacian,
            diffusivity=molecules.diffusion_constant,
            dt=self.time_step,
        )

        return state