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
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
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
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