def next_update(self, timestep, states): # get mmol_to_counts for converting flux to exchange counts mmol_to_counts = states['global']['mmol_to_counts'] # kinetic rate law requires a flat dict with ('port', 'state') keys. flattened_states = remove_units(tuplify_port_dicts(states)) # get flux fluxes = self.kinetic_rate_laws.get_fluxes(flattened_states) # make the update # add fluxes to update update = {port: {} for port in self.port_ids} update.update({'fluxes': fluxes}) # get exchange and update fields for reaction_id, flux in fluxes.items(): stoichiometry = self.reactions[reaction_id]['stoichiometry'] for port_state_id, coeff in stoichiometry.items(): for port_id in self.port_ids: # separate the state_id and port_id if port_id in port_state_id: state_id = port_state_id[1] state_flux = coeff * flux * timestep if port_id == 'external': # convert exchange fluxes to counts with mmol_to_counts delta = int((state_flux * mmol_to_counts).magnitude) existing_delta = update['fields'].get( state_id, {}).get('_value', 0) update['fields'][state_id] = { '_value': existing_delta + delta, '_updater': { 'updater': ( 'update_field_with_exchange'), 'port_mapping': { 'global': 'global', 'dimensions': 'dimensions', }, }, } else: update[port_id][state_id] = ( update[port_id].get(state_id, 0) + state_flux ) # note: external and internal ports update change in mmol. return update
def next_update(self, timestep, states): # get mmol_to_counts for converting flux to exchange counts mmol_to_counts = states['global']['mmol_to_counts'] # kinetic rate law requires a flat dict with ('port', 'state') keys. flattened_states = tuplify_port_dicts(states) # get flux fluxes = self.kinetic_rate_laws.get_fluxes(flattened_states) # make the update # add fluxes to update update = {port: {} for port in self.port_ids} update.update({'fluxes': fluxes}) # get exchange for reaction_id, flux in fluxes.items(): stoichiometry = self.reactions[reaction_id]['stoichiometry'] for port_state_id, coeff in stoichiometry.items(): for port_id in self.port_ids: # separate the state_id and port_id if port_id in port_state_id: state_id = port_state_id[1] state_flux = coeff * flux * timestep if port_id == 'external': # convert exchange fluxes to counts with mmol_to_counts # TODO -- use deriver to get exchanges delta_counts = int((state_flux * mmol_to_counts).magnitude) update['exchange'][state_id] = ( update['exchange'].get(state_id, 0) + delta_counts ) else: update[port_id][state_id] = ( update[port_id].get(state_id, 0) + state_flux ) # note: external and internal ports update change in mmol. return update
def next_update(self, timestep, states): internal = states['internal'] step_size = self.parameters['step_size'] n_steps = int(timestep / step_size) # get state of regulated reactions (True/False) flattened_states = tuplify_port_dicts(states) regulation_state = {} for gene_id, reg_logic in self.regulation.items(): regulation_state[gene_id] = reg_logic(flattened_states) internal_update = {state_id: 0 for state_id in internal.keys()} for state_id in internal.keys(): if state_id in regulation_state and not regulation_state[state_id]: break rate = self.parameters['expression_rates'][state_id] for step in range(n_steps): if random.random() < rate: internal_update[state_id] += 1 return {'internal': internal_update}
def next_update(self, timestep, states): internal_state = states['internal'] # get state of regulated reactions (True/False) flattened_states = tuplify_port_dicts(states) regulation_state = {} for gene_id, reg_logic in self.regulation.items(): regulation_state[gene_id] = reg_logic(flattened_states) internal_update = {} # transcription: dM/dt = k_M - d_M * M # M: conc of mRNA, k_M: transcription rate, d_M: degradation rate for transcript, rate in self.transcription.items(): transcript_state = internal_state[transcript] # do not transcribe inhibited genes, except for transcription leaks if transcript in regulation_state and regulation_state.get( transcript): # leak probability for probability as function of the time step rate = -math.log(1 - self.transcription_leak_rate) leak_probability = 1 - math.exp(-rate * timestep) if random.uniform(0, 1) < leak_probability: rate = self.transcription_leak_magnitude else: rate = 0.0 internal_update[transcript] = \ (rate - self.degradation.get(transcript, 0) * transcript_state) * timestep # translation: dP/dt = k_P * m_P - d_P * P # P: conc of protein, m_P: conc of P's transcript, k_P: translation rate, d_P: degradation rate for protein, rate in self.translation.items(): transcript = self.protein_map[protein] transcript_state = internal_state[transcript] protein_state = internal_state[protein] internal_update[protein] = \ (rate * transcript_state - self.degradation.get(protein, 0) * protein_state) * timestep return {'internal': internal_update}
def next_update(self, timestep, states): internal_state = states['internal'] # get state of regulated reactions (True/False) flattened_states = tuplify_port_dicts(states) regulation_state = {} for gene_id, reg_logic in self.regulation.items(): regulation_state[gene_id] = reg_logic(flattened_states) internal_update = {} # transcription: dM/dt = k_M - d_M * M # M: conc of mRNA, k_M: transcription rate, d_M: degradation rate for transcript, rate in self.transcription.items(): transcript_state = internal_state[transcript] # do not transcribe inhibited genes if transcript in regulation_state and not regulation_state[ transcript]: if random.uniform(0, 1) < abs( random.gauss(0, self.transcription_leak_sigma)): rate = self.transcription_leak_magnitude else: rate = 0.0 internal_update[transcript] = \ (rate - self.degradation.get(transcript, 0) * transcript_state) * timestep # translation: dP/dt = k_P * m_P - d_P * P # P: conc of protein, m_P: conc of P's transcript, k_P: translation rate, d_P: degradation rate for protein, rate in self.translation.items(): transcript = self.protein_map[protein] transcript_state = internal_state[transcript] protein_state = internal_state[protein] internal_update[protein] = \ (rate * transcript_state - self.degradation.get(protein, 0) * protein_state) * timestep return {'internal': internal_update}
def test_kinetics(): kinetic_rate_laws = KineticFluxModel(toy_reactions, toy_kinetics) flattened_toy_states = tuplify_port_dicts(toy_initial_state) flux = kinetic_rate_laws.get_fluxes(flattened_toy_states) print(flux)
def next_update(self, timestep, states): ## get the state external_state = states['external'] constrained_reaction_bounds = states[ 'flux_bounds'] # (units.mmol / units.L / units.s) mmol_to_counts = states['global']['mmol_to_counts'] ## get flux constraints # exchange_constraints based on external availability exchange_constraints = { mol_id: 0.0 for mol_id, conc in external_state.items() if conc <= self.exchange_threshold } # get state of regulated reactions (True/False) flattened_states = tuplify_port_dicts(states) regulation_state = {} for reaction_id, reg_logic in self.regulation.items(): regulation_state[reaction_id] = reg_logic(flattened_states) ## apply flux constraints # first, add exchange constraints self.fba.set_exchange_bounds(exchange_constraints) # next, add constraints coming from flux_bounds # to constrain exchange fluxes, add the suffix 'EX_' to the external molecule ID if constrained_reaction_bounds: self.fba.constrain_flux(constrained_reaction_bounds) # finally, turn reactions on/off based on regulation self.fba.regulate_flux(regulation_state) ## solve the fba problem objective_exchange = self.fba.optimize( ) * timestep # (units.mmol / units.L / units.s) exchange_reactions = self.fba.read_exchange_reactions() exchange_fluxes = self.fba.read_exchange_fluxes( ) # (units.mmol / units.L / units.s) internal_fluxes = self.fba.read_internal_fluxes( ) # (units.mmol / units.L / units.s) # timestep dependence on fluxes exchange_fluxes.update((mol_id, flux * timestep) for mol_id, flux in exchange_fluxes.items()) internal_fluxes.update((mol_id, flux * timestep) for mol_id, flux in internal_fluxes.items()) # update internal counts from objective flux # calculate added mass from the objective molecules' molecular weights objective_count = (objective_exchange * mmol_to_counts).magnitude internal_state_update = {} for reaction_id, coeff1 in self.fba.objective.items(): for mol_id, coeff2 in self.fba.stoichiometry[reaction_id].items(): if coeff2 < 0: # pull out molecule if it is USED to make biomass (negative coefficient) added_count = int(-coeff1 * coeff2 * objective_count) internal_state_update[mol_id] = added_count # convert exchange fluxes to counts field_updates = { reaction: { '_value': int((flux * mmol_to_counts).magnitude), '_updater': { 'updater': 'update_field_with_exchange', 'port_mapping': { 'global': 'global', 'dimensions': 'dimensions', }, }, } for reaction, flux in exchange_fluxes.items() } all_fluxes = {} all_fluxes.update(internal_fluxes) all_fluxes.update(exchange_reactions) return { 'fields': field_updates, 'internal': internal_state_update, 'reactions': all_fluxes, }
def next_update(self, timestep, states): # get the state external_state = states['external'] flux_bounds = states['flux_bounds'] # mmol/L/s mmol_to_counts = states['global']['mmol_to_counts'].to( 'L/mmol').magnitude # get constraints ## exchange_constraints based on external availability exchange_constraints = { mol_id: 0.0 for mol_id, conc in external_state.items() if conc <= self.parameters['exchange_threshold'] } ## state of regulated reactions (True/False) flattened_states = tuplify_port_dicts(states) regulation_state = {} for reaction_id, reg_logic in self.regulation.items(): regulation_state[reaction_id] = reg_logic(flattened_states) # apply constraints ## exchange constraints self.fba.set_exchange_bounds(exchange_constraints) ## constraints from flux_bounds if flux_bounds: # only pass in reaction_ids that exist in the fba model constrained_reaction_bounds = { reaction_id: constraint for reaction_id, constraint in flux_bounds.items() if reaction_id in self.reaction_ids } self.fba.constrain_flux(constrained_reaction_bounds) ## turn reactions on/off based on regulation self.fba.regulate_flux(regulation_state) # solve the fba problem objective_exchange = self.fba.optimize() * timestep # mmol/L/s exchange_reactions = self.fba.read_exchange_reactions() exchange_fluxes = self.fba.read_exchange_fluxes() # mmol/L/s internal_fluxes = self.fba.read_internal_fluxes() # mmol/L/s # convert results ## time step dependence on fluxes exchange_fluxes.update((mol_id, flux * timestep) for mol_id, flux in exchange_fluxes.items()) internal_fluxes.update((mol_id, flux * timestep) for mol_id, flux in internal_fluxes.items()) ## update internal counts from objective flux ## calculate added mass from the objective molecules' molecular weights objective_count = objective_exchange * mmol_to_counts if self.parameters[ 'no_negative_objective'] and objective_exchange < 0.0: return {} internal_state_update = {} for reaction_id, coeff1 in self.fba.objective.items(): for mol_id, coeff2 in self.fba.stoichiometry[reaction_id].items(): if coeff2 < 0: # pull out molecule if it is used to make biomass (negative coefficient) added_count = int(-coeff1 * coeff2 * objective_count) internal_state_update[mol_id] = added_count ## convert exchange fluxes to counts exchanges_updates = { mol_id: int(flux * mmol_to_counts) for mol_id, flux in exchange_fluxes.items() } all_fluxes = {} all_fluxes.update(internal_fluxes) all_fluxes.update(exchange_reactions) update = { 'exchanges': exchanges_updates, 'internal_counts': internal_state_update, 'reactions': all_fluxes } return update