Skip to content

Commit

Permalink
begin parameter scan process. update cobra process.
Browse files Browse the repository at this point in the history
  • Loading branch information
eagmon committed Feb 6, 2024
1 parent 6562e6e commit 94e86a8
Show file tree
Hide file tree
Showing 6 changed files with 10,081 additions and 23 deletions.
1 change: 1 addition & 0 deletions biosimulator_processes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from process_bigraph import process_registry


# Attempt to import and register CobraProcess
try:
from biosimulator_processes.cobra_process import CobraProcess
Expand Down
98 changes: 76 additions & 22 deletions biosimulator_processes/cobra_process.py
Original file line number Diff line number Diff line change
@@ -1,63 +1,117 @@
"""
COBRA FBA Process
"""
import cobra.io
from process_bigraph import Process, core
from cobra.io import read_sbml_model


from process_bigraph import Process
from cobra.io import read_sbml_model
def check_sbml(state, schema, core):
# Do something to check that the value is a valid SBML file
valid = cobra.io.sbml.validate_sbml_model(state) # TODO -- this requires XML
# valid = cobra.io.load_json_model(value)
if valid:
return True
else:
return False


bounds_type = {
'lower_bound': {'_type': 'float', '_default': -1000.0},
'upper_bound': {'_type': 'float', '_default': 1000.0},
}
bounds_tree_type = {
'_type': 'tree[bounds]', # TODO -- make this a dict, to make it only one level deep
}
sbml_type = {
'_type': 'string',
'_check': check_sbml,
'_apply': 'set',
}

# register new types
core.register('bounds', bounds_type)
core.register('sbml', sbml_type)


class CobraProcess(Process):
config_schema = {
'model_file': 'string'
'model_file': 'sbml',
}

def __init__(self, config=None):
super().__init__(config)

self.model = read_sbml_model(self.config['model_file'])
self.reactions = self.model.reactions
self.metabolites = self.model.metabolites
self.objective = self.model.objective
self.objective = self.model.objective.to_json()['expression']['args'][0]['args'][1]['name'] # TODO -- fix this in cobra
self.boundary = self.model.boundary

def initial_state(self):
solution = self.model.optimize()
optimized_fluxes = solution.fluxes

state = {'fluxes': {}, 'reaction_bounds': {}}
state = {
'inputs': {
'reaction_bounds': {}
},
'outputs': {
'fluxes': {}
}
}
for reaction in self.model.reactions:
state['fluxes'][reaction.id] = optimized_fluxes[reaction.id]
state['reaction_bounds'][reaction.id] = {
state['inputs']['reaction_bounds'][reaction.id] = {
'lower_bound': reaction.lower_bound,
'upper_bound': reaction.upper_bound}
'upper_bound': reaction.upper_bound
}
state['outputs']['fluxes'][reaction.id] = optimized_fluxes[reaction.id]
return state

def schema(self):
return {
'fluxes': {
reaction.id: 'float' for reaction in self.reactions
},
'objective_value': 'float',
'reaction_bounds': {
reaction.id: {
'upper_bound': 'float',
'lower_bound': 'float'
} for reaction in self.reactions
'inputs': {
'model': 'sbml',
'reaction_bounds': {
reaction.id: 'bounds' for reaction in self.reactions
},
'objective_reaction': {
'_type': 'string',
'_default': self.objective
},
},
'outputs': {
'fluxes': {
reaction.id: 'float' for reaction in self.reactions
},
'objective_value': 'float',
'reaction_dual_values': {
reaction.id: 'float' for reaction in self.reactions
},
'metabolite_dual_values': {
metabolite.id: 'float' for metabolite in self.metabolites
},
'status': 'string',
}
}

def update(self, state, interval):
def update(self, inputs, interval):

# set reaction bounds
reaction_bounds = state['reaction_bounds']
reaction_bounds = inputs['reaction_bounds']
for reaction_id, bounds in reaction_bounds.items():
self.model.reactions.get_by_id(reaction_id).bounds = (bounds['lower_bound'], bounds['upper_bound'])

# set objective
# TODO -- look into optlang for specifying objective and constraints
self.model.objective = self.model.reactions.get_by_id(inputs['objective_reaction'])

# run solver
solution = self.model.optimize()

return {
'fluxes': solution.fluxes.to_dict(),
'objective_value': solution.objective_value
}
'objective_value': solution.objective_value,
'reaction_dual_values': solution.reduced_costs.to_dict(),
'metabolite_dual_values': solution.shadow_prices.to_dict(),
'status': solution.status,
}
2 changes: 1 addition & 1 deletion biosimulator_processes/copasi_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ def __init__(self, config=None):
# TODO -- make this configurable.
self.input_ports = [
'floating_species',
# 'boundary_species',
'model_parameters'
'time',
# 'boundary_species',
# 'compartments',
# 'parameters',
# 'stoichiometries',
Expand Down
Empty file.
105 changes: 105 additions & 0 deletions biosimulator_processes/experiments/parameter_scan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from process_bigraph import Composite, Step, pf


class ParameterScan(Step):
config_schema = {
'parameters': 'tree' # this should be from parameter id to range of values
}

def __init__(self, config=None):
super().__init__(config)

def inputs(self):
return {}

def outputs(self):
return {}

def update(self, inputs):
return {}


def test_param_scan_copasi():
initial_sim_state = {
'copasi': {
'_type': 'process',
'address': 'local:copasi',
'config': {
'model_file': 'tests/model_files/Caravagna2010.xml'
},
'inputs': {
'floating_species': ['floating_species_store'],
# 'boundary_species': ['boundary_species_store'],
'model_parameters': ['model_parameters_store'],
'time': ['time_store'],
# 'compartments': ['compartments_store'],
# 'parameters': ['parameters_store'],
# 'stoichiometries': ['stoichiometries_store']
},
'outputs': {
'floating_species': ['floating_species_store'],
'time': ['time_store'],
}
},
}

# 2. Make the composite:
workflow = Composite({
'state': initial_sim_state
})

# 3. Run the composite workflow:
workflow.run(10)

# 4. Gather and pretty print results
results = workflow.gather_results()
print(f'RESULTS: {pf(results)}')


def run_param_scan_cobra():
instance = {
'fba': {
'_type': 'process',
'address': 'local:cobra',
'config': {
'model_file': 'tests/model_files/e_coli_core.xml'
},
'inputs': {
'model': ['model_store'],
'reaction_bounds': ['reaction_bounds_store'],
'objective_reaction': ['objective_reaction_store'],
},
'outputs': {
'fluxes': ['fluxes_store'],
'objective_value': ['objective_value_store'],
'reaction_dual_values': ['reaction_dual_values_store'],
'metabolite_dual_values': ['metabolite_dual_values_store'],
'status': ['status_store'],
}
},
'emitter': {
'_type': 'step',
'address': f'local:ram-emitter',
'config': {
'inputs_schema': 'tree[any]'
},
'inputs': {'data': 'fluxes_store'},
}
}

# make the composite
workflow = Composite({
'state': instance
})

# run
workflow.run(1)

# gather results
results = workflow.gather_results()
print(f'RESULTS: {pf(results)}')


if __name__ == '__main__':
test_param_scan_copasi()
# test_param_scan_cobra()
Loading

0 comments on commit 94e86a8

Please sign in to comment.