def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.iron import IronState
        from nlisim.modules.tafc import TAFCState

        estb: EstBState = state.estb
        iron: IronState = state.iron
        tafc: TAFCState = state.tafc
        molecules: MoleculesState = state.molecules
        voxel_volume = state.voxel_volume

        # contribute our iron buffer to the iron pool
        iron.grid += estb.iron_buffer
        estb.iron_buffer[:] = 0.0

        # interact with TAFC
        v1 = michaelian_kinetics(
            substrate=tafc.grid["TAFC"],
            enzyme=estb.grid,
            k_m=estb.k_m,
            k_cat=estb.k_cat,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            voxel_volume=voxel_volume,
        )
        v2 = michaelian_kinetics(
            substrate=tafc.grid["TAFCBI"],
            enzyme=estb.grid,
            k_m=estb.k_m,
            k_cat=estb.k_cat,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            voxel_volume=voxel_volume,
        )
        tafc.grid["TAFC"] -= v1
        tafc.grid["TAFCBI"] -= v2
        estb.iron_buffer += v2  # set equal to zero previously

        # Degrade EstB
        estb.grid *= estb.half_life_multiplier
        estb.grid *= turnover_rate(
            x=estb.grid,
            x_system=estb.system_amount_per_voxel,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

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

        return state
Exemple #2
0
    def advance(self, state: State, previous_time: float) -> State:
        """Advances the state by a single time step."""
        from nlisim.modules.tnfa import TNFaState

        anti_tnf_a: AntiTNFaState = state.antitnfa
        molecules: MoleculesState = state.molecules
        voxel_volume = state.voxel_volume
        tnf_a: TNFaState = state.tnfa

        # AntiTNFa / TNFa reaction
        reacted_quantity = michaelian_kinetics(
            substrate=anti_tnf_a.grid,
            enzyme=tnf_a.grid,
            k_m=anti_tnf_a.k_m,
            h=anti_tnf_a.
            react_time_unit,  # TODO: understand why units are seconds here
            k_cat=1.0,  # default TODO use k_cat to reparameterize into hours
            voxel_volume=voxel_volume,
        )
        reacted_quantity = np.min(
            [reacted_quantity, anti_tnf_a.grid, tnf_a.grid], axis=0)
        anti_tnf_a.grid[:] = np.maximum(0.0,
                                        anti_tnf_a.grid - reacted_quantity)
        tnf_a.grid[:] = np.maximum(0.0, tnf_a.grid - reacted_quantity)

        # Degradation of AntiTNFa
        anti_tnf_a.system_amount_per_voxel *= anti_tnf_a.half_life_multiplier
        anti_tnf_a.grid *= turnover_rate(
            x=anti_tnf_a.grid,
            x_system=anti_tnf_a.system_amount_per_voxel,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

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

        return state
Exemple #3
0
    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.hemoglobin import HemoglobinState

        hemopexin: HemopexinState = state.hemopexin
        hemoglobin: HemoglobinState = state.hemoglobin
        molecules: MoleculesState = state.molecules
        voxel_volume: float = state.voxel_volume  # units: L

        # Hemopexin / Hemoglobin reaction
        reacted_quantity = michaelian_kinetics(
            substrate=hemopexin.grid,
            enzyme=hemoglobin.grid,
            k_m=hemopexin.k_m,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            k_cat=hemopexin.k_cat,
            voxel_volume=voxel_volume,
        )
        reacted_quantity = np.min([reacted_quantity, hemopexin.grid, hemoglobin.grid], axis=0)
        hemopexin.grid[:] = np.maximum(0.0, hemopexin.grid - reacted_quantity)
        hemoglobin.grid[:] = np.maximum(0.0, hemoglobin.grid - reacted_quantity)

        # Degrade Hemopexin
        hemopexin.grid *= hemopexin.half_life_multiplier
        hemopexin.grid *= turnover_rate(
            x=hemopexin.grid,
            x_system=hemopexin.system_amount_per_voxel,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

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

        return state
    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.afumigatus import (
            AfumigatusCellData,
            AfumigatusCellState,
            AfumigatusCellStatus,
            AfumigatusState,
            NetworkSpecies,
        )
        from nlisim.modules.iron import IronState
        from nlisim.modules.transferrin import TransferrinState

        tafc: TAFCState = state.tafc
        transferrin: TransferrinState = state.transferrin
        iron: IronState = state.iron
        molecules: MoleculesState = state.molecules
        afumigatus: AfumigatusState = state.afumigatus
        grid: RectangularGrid = state.grid
        voxel_volume: float = state.voxel_volume  # units: L

        # interaction with transferrin
        # - calculate iron transfer from transferrin+[1,2]Fe to TAFC
        dfe2_dt = michaelian_kinetics(
            substrate=transferrin.grid["TfFe2"],
            enzyme=tafc.grid["TAFC"],
            k_m=tafc.k_m_tf_tafc,
            h=self.time_step /
            60,  # units: (min/step) / (min/hour) = hours/step
            k_cat=1.0,  # default
            voxel_volume=voxel_volume,
        )
        dfe_dt = michaelian_kinetics(
            substrate=transferrin.grid["TfFe"],
            enzyme=tafc.grid["TAFC"],
            k_m=tafc.k_m_tf_tafc,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            k_cat=1.0,  # default
            voxel_volume=voxel_volume,
        )

        # - enforce bounds from TAFC quantity
        total_change = dfe2_dt + dfe_dt
        rel = tafc.grid['TAFC'] / (total_change + EPSILON)
        # enforce bounds and zero out problem divides
        rel[total_change == 0] = 0.0
        rel[:] = np.maximum(np.minimum(rel, 1.0), 0.0)

        dfe2_dt = dfe2_dt * rel
        dfe_dt = dfe_dt * rel

        # transferrin+2Fe loses an iron, becomes transferrin+Fe
        transferrin.grid['TfFe2'] -= dfe2_dt
        transferrin.grid['TfFe'] += dfe2_dt

        # transferrin+Fe loses an iron, becomes transferrin
        transferrin.grid['TfFe'] -= dfe_dt
        transferrin.grid['Tf'] += dfe_dt

        # iron from transferrin becomes bound to TAFC (TAFC->TAFCBI)
        tafc.grid['TAFC'] -= dfe2_dt + dfe_dt
        tafc.grid['TAFCBI'] += dfe2_dt + dfe_dt

        # interaction with iron, all available iron is bound to TAFC
        potential_reactive_quantity = np.minimum(iron.grid, tafc.grid['TAFC'])
        tafc.grid['TAFC'] -= potential_reactive_quantity
        tafc.grid['TAFCBI'] += potential_reactive_quantity
        iron.grid -= potential_reactive_quantity

        # interaction with fungus
        for afumigatus_cell_index in afumigatus.cells.alive():
            afumigatus_cell: AfumigatusCellData = afumigatus.cells[
                afumigatus_cell_index]

            if afumigatus_cell['state'] != AfumigatusCellState.FREE:
                continue

            afumigatus_cell_voxel: Voxel = grid.get_voxel(
                afumigatus_cell['point'])
            afumigatus_bool_net: np.ndarray = afumigatus_cell[
                'boolean_network']

            # uptake iron from TAFCBI
            if afumigatus_bool_net[NetworkSpecies.MirB] & afumigatus_bool_net[
                    NetworkSpecies.EstB]:
                quantity = (tafc.grid['TAFCBI'][tuple(afumigatus_cell_voxel)] *
                            tafc.tafcbi_uptake_rate_unit_t)
                tafc.grid['TAFCBI'][tuple(afumigatus_cell_voxel)] -= quantity
                afumigatus_cell['iron_pool'] += quantity

            # secrete TAFC
            if afumigatus_bool_net[
                    NetworkSpecies.TAFC] and afumigatus_cell['status'] in {
                        AfumigatusCellStatus.SWELLING_CONIDIA,
                        AfumigatusCellStatus.HYPHAE,
                        AfumigatusCellStatus.GERM_TUBE,
                    }:
                tafc.grid['TAFC'][
                    tuple(afumigatus_cell_voxel
                          )] += tafc.afumigatus_secretion_rate_unit_t

        # Degrade TAFC
        trnvr_rt = 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,
        )
        tafc.grid['TAFC'] *= trnvr_rt
        tafc.grid['TAFCBI'] *= trnvr_rt

        # Diffusion of TAFC
        for component in {'TAFC', 'TAFCBI'}:
            tafc.grid[component][:] = apply_diffusion(
                variable=tafc.grid[component],
                laplacian=molecules.laplacian,
                diffusivity=molecules.diffusion_constant,
                dt=self.time_step,
            )

        return state
Exemple #5
0
    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.iron import IronState
        from nlisim.modules.macrophage import MacrophageCellData, MacrophageState
        from nlisim.modules.molecules import MoleculesState
        from nlisim.modules.neutrophil import NeutrophilCellData, NeutrophilState
        from nlisim.modules.phagocyte import PhagocyteState, PhagocyteStatus
        from nlisim.modules.transferrin import TransferrinState

        lactoferrin: LactoferrinState = state.lactoferrin
        transferrin: TransferrinState = state.transferrin
        iron: IronState = state.iron
        molecules: MoleculesState = state.molecules
        macrophage: MacrophageState = state.macrophage
        neutrophil: NeutrophilState = state.neutrophil
        grid: RectangularGrid = state.grid
        voxel_volume = state.voxel_volume

        # macrophages uptake iron from lactoferrin
        live_macrophages = macrophage.cells.alive()
        rg.shuffle(live_macrophages)
        for macrophage_cell_index in live_macrophages:
            macrophage_cell: MacrophageCellData = macrophage.cells[
                macrophage_cell_index]
            macrophage_cell_voxel: Voxel = grid.get_voxel(
                macrophage_cell['point'])

            uptake_proportion = np.minimum(lactoferrin.ma_iron_import_rate,
                                           1.0)

            qtty_fe2 = (lactoferrin.grid['LactoferrinFe2'][tuple(
                macrophage_cell_voxel)] * uptake_proportion)
            qtty_fe = (
                lactoferrin.grid['LactoferrinFe'][tuple(macrophage_cell_voxel)]
                * uptake_proportion)

            lactoferrin.grid['LactoferrinFe2'][tuple(
                macrophage_cell_voxel)] -= qtty_fe2
            lactoferrin.grid['LactoferrinFe'][tuple(
                macrophage_cell_voxel)] -= qtty_fe
            macrophage_cell['iron_pool'] += 2 * qtty_fe2 + qtty_fe

        # active and interacting neutrophils secrete lactoferrin
        for neutrophil_cell_index in neutrophil.cells.alive():
            neutrophil_cell: NeutrophilCellData = neutrophil.cells[
                neutrophil_cell_index]

            if (neutrophil_cell['status'] != PhagocyteStatus.ACTIVE
                    or neutrophil_cell['state'] != PhagocyteState.INTERACTING):
                continue

            neutrophil_cell_voxel: Voxel = grid.get_voxel(
                neutrophil_cell['point'])
            lactoferrin.grid['Lactoferrin'][
                tuple(neutrophil_cell_voxel
                      )] += lactoferrin.neutrophil_secretion_rate_unit_t

        # interaction with transferrin
        # - calculate iron transfer from transferrin+[1,2]Fe to lactoferrin
        dfe2_dt = michaelian_kinetics(
            substrate=transferrin.grid['TfFe2'],
            enzyme=lactoferrin.grid["Lactoferrin"],
            k_m=lactoferrin.k_m_tf_lac,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            k_cat=1.0,
            voxel_volume=voxel_volume,
        )
        dfe_dt = michaelian_kinetics(
            substrate=transferrin.grid['TfFe'],
            enzyme=lactoferrin.grid['Lactoferrin'],
            k_m=lactoferrin.k_m_tf_lac,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            k_cat=1.0,
            voxel_volume=voxel_volume,
        )
        # - enforce bounds from lactoferrin quantity
        dfex_dt = dfe2_dt + dfe_dt
        mask = dfex_dt > lactoferrin.grid['Lactoferrin']

        rel = lactoferrin.grid['Lactoferrin'] / (dfex_dt + EPSILON)
        # enforce bounds
        rel[dfex_dt == 0] = 0.0
        rel[:] = np.maximum(np.minimum(rel, 1.0), 0.0)

        dfe2_dt[mask] = (dfe2_dt * rel)[mask]
        dfe_dt[mask] = (dfe_dt * rel)[mask]

        # - calculate iron transfer from transferrin+[1,2]Fe to lactoferrin+Fe
        dfe2_dt_fe = michaelian_kinetics(
            substrate=transferrin.grid['TfFe2'],
            enzyme=lactoferrin.grid['LactoferrinFe'],
            k_m=lactoferrin.k_m_tf_lac,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            k_cat=1.0,
            voxel_volume=voxel_volume,
        )
        dfe_dt_fe = michaelian_kinetics(
            substrate=transferrin.grid['TfFe'],
            enzyme=lactoferrin.grid['LactoferrinFe'],
            k_m=lactoferrin.k_m_tf_lac,
            h=self.time_step / 60,  # units: (min/step) / (min/hour)
            k_cat=1.0,
            voxel_volume=voxel_volume,
        )
        # - enforce bounds from lactoferrin+Fe quantity
        dfex_dt_fe = dfe2_dt_fe + dfe_dt_fe
        mask = dfex_dt_fe > lactoferrin.grid['LactoferrinFe']

        rel = lactoferrin.grid['LactoferrinFe'] / (dfe2_dt_fe + dfe_dt_fe +
                                                   EPSILON)
        # enforce bounds
        rel[dfex_dt_fe == 0] = 0.0
        np.minimum(rel, 1.0, out=rel)
        np.maximum(rel, 0.0, out=rel)

        dfe2_dt_fe[mask] = (dfe2_dt_fe * rel)[mask]
        dfe_dt_fe[mask] = (dfe_dt_fe * rel)[mask]

        # transferrin+2Fe loses an iron, becomes transferrin+Fe
        transferrin.grid['TfFe2'] -= dfe2_dt + dfe2_dt_fe
        transferrin.grid['TfFe'] += dfe2_dt + dfe2_dt_fe

        # transferrin+Fe loses an iron, becomes transferrin
        transferrin.grid['TfFe'] -= dfe_dt + dfe_dt_fe
        transferrin.grid['Tf'] += dfe_dt + dfe_dt_fe

        # lactoferrin gains an iron, becomes lactoferrin+Fe
        lactoferrin.grid['Lactoferrin'] -= dfe2_dt + dfe_dt
        lactoferrin.grid['LactoferrinFe'] += dfe2_dt + dfe_dt

        # lactoferrin+Fe gains an iron, becomes lactoferrin+2Fe
        lactoferrin.grid['LactoferrinFe'] -= dfe2_dt_fe + dfe_dt_fe
        lactoferrin.grid['LactoferrinFe2'] += dfe2_dt_fe + dfe_dt_fe

        # interaction with iron
        lactoferrin_fe_capacity = (2 * lactoferrin.grid["Lactoferrin"] +
                                   lactoferrin.grid["LactoferrinFe"])
        potential_reactive_quantity = np.minimum(iron.grid,
                                                 lactoferrin_fe_capacity)
        rel_tf_fe = iron_tf_reaction(
            iron=potential_reactive_quantity,
            tf=lactoferrin.grid["Lactoferrin"],
            tf_fe=lactoferrin.grid["LactoferrinFe"],
            p1=lactoferrin.p1,
            p2=lactoferrin.p2,
            p3=lactoferrin.p3,
        )
        tffe_qtty = rel_tf_fe * potential_reactive_quantity
        tffe2_qtty = (potential_reactive_quantity - tffe_qtty) / 2
        lactoferrin.grid['Lactoferrin'] -= tffe_qtty + tffe2_qtty
        lactoferrin.grid['LactoferrinFe'] += tffe_qtty
        lactoferrin.grid['LactoferrinFe2'] += tffe2_qtty
        iron.grid -= potential_reactive_quantity

        # Degrade Lactoferrin
        # Note: ideally, this would be a constant computed in initialize, but we would have to
        # know that "molecules" is initialized first
        trnvr_rt = 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,
        )
        lactoferrin.grid['Lactoferrin'] *= trnvr_rt
        lactoferrin.grid['LactoferrinFe'] *= trnvr_rt
        lactoferrin.grid['LactoferrinFe2'] *= trnvr_rt

        # Diffusion of lactoferrin
        for component in {'Lactoferrin', 'LactoferrinFe', 'LactoferrinFe2'}:
            lactoferrin.grid[component][:] = apply_diffusion(
                variable=lactoferrin.grid[component],
                laplacian=molecules.laplacian,
                diffusivity=molecules.diffusion_constant,
                dt=self.time_step,
            )

        return state