diff --git a/biosimulator_processes/steps/ode_simulation.py b/biosimulator_processes/steps/ode_simulation.py index d24a6675f..9dc5e4c70 100644 --- a/biosimulator_processes/steps/ode_simulation.py +++ b/biosimulator_processes/steps/ode_simulation.py @@ -4,45 +4,89 @@ from process_bigraph.experiments.parameter_scan import RunProcess from biosimulator_processes import CORE +from biosimulator_processes.utils import calc_num_steps, calc_duration, calc_step_size class OdeSimulation(Step, abc.ABC): config_schema = { 'sbml_filepath': 'string', - 'n_steps': 'integer', - 'step_size': 'float', - 'duration': { - '_type': 'string', - '_default': 10} + 'time_config': { + 'step_size': 'maybe[float]', + 'num_steps': 'maybe[float]', + 'duration': 'maybe[float]' + } } def __init__(self, config=None, core=None): super().__init__(config, core) + assert len(list(self.config['time_config'].values())) >= 2, "you must pass two of either: step size, n steps, or duration." + self.step_size = self.config.get('step_size') + self.num_steps = self.config.get('num_steps') + self.duration = self.config.get('duration') + self._set_time_params() + + def _set_time_params(self): + if self.step_size and self.num_steps: + self.duration = calc_duration(self.num_steps, self.step_size) + elif self.step_size and self.duration: + self.num_steps = calc_num_steps(self.duration, self.step_size) + else: + self.step_size = calc_step_size(self.duration, self.num_steps) + @abc.abstractmethod - def inputs(self): + def _set_simulator(self, sbml_fp: str) -> object: + """Load simulator instance""" pass @abc.abstractmethod - def outputs(self): + def _get_floating_species_ids(self) -> list[str]: + """Sim specific method""" pass - def update(self, inputs): + '''@abc.abstractmethod + def _set_floating_species(self): + """Sim specific method for starting values relative to this property.""" pass @abc.abstractmethod - def set_species_list(self): + def _set_global_parameters(self): + """Sim specific method for starting values relative to this property.""" pass @abc.abstractmethod - def set_global_parameters(self): - pass + def _set_reactions(self): + """Sim specific method for starting values relative to this property.""" + pass''' + + def inputs(self): + """For now, none""" + return {} + + def outputs(self): + return { + 'time': 'float', + 'floating_species': { + spec_id: 'float' + for spec_id in self.floating_species_ids + } + } @abc.abstractmethod - def set_reactions(self): + def update(self, inputs): + """Iteratively update over self.floating_species_ids as per the requirements of the simulator library.""" pass + + + + + + + + + class ODEProcess(RunProcess): def __init__(self, address: str, diff --git a/biosimulator_processes/utils.py b/biosimulator_processes/utils.py index c02032a72..4aa29d5ad 100644 --- a/biosimulator_processes/utils.py +++ b/biosimulator_processes/utils.py @@ -8,6 +8,18 @@ import nbformat +def calc_num_steps(dur, step_size): + return dur / step_size + + +def calc_duration(n_steps, step_size): + return n_steps * step_size + + +def calc_step_size(dur, n_steps): + return dur / n_steps + + def register_module(items_to_register: List[Tuple[str, str]], core: ProcessTypes) -> None: for process_name, path in items_to_register: module_name, class_name = path.rsplit('.', 1) diff --git a/demos/ode_process_demo.ipynb b/demos/ode_process_demo.ipynb index 47c7617cb..47cd97db4 100644 --- a/demos/ode_process_demo.ipynb +++ b/demos/ode_process_demo.ipynb @@ -6,13 +6,14 @@ "metadata": { "collapsed": true, "ExecuteTime": { - "end_time": "2024-05-26T18:47:36.234190Z", - "start_time": "2024-05-26T18:47:34.708184Z" + "end_time": "2024-05-26T22:01:18.142414Z", + "start_time": "2024-05-26T22:01:16.150749Z" } }, "source": [ "import sys\n", - "import os \n", + "import os\n", + "import tempfile\n", "\n", "import numpy as np\n", "from process_bigraph import pp\n", @@ -69,8 +70,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2024-05-26T18:47:36.237044Z", - "start_time": "2024-05-26T18:47:36.235328Z" + "end_time": "2024-05-26T22:01:18.145262Z", + "start_time": "2024-05-26T22:01:18.143492Z" } }, "cell_type": "code", @@ -87,8 +88,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2024-05-26T18:47:36.295379Z", - "start_time": "2024-05-26T18:47:36.237603Z" + "end_time": "2024-05-26T22:01:18.206773Z", + "start_time": "2024-05-26T22:01:18.145890Z" } }, "cell_type": "code", @@ -109,8 +110,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2024-05-26T18:47:36.350706Z", - "start_time": "2024-05-26T18:47:36.296031Z" + "end_time": "2024-05-26T22:01:18.262359Z", + "start_time": "2024-05-26T22:01:18.207352Z" } }, "cell_type": "code", @@ -133,21 +134,37 @@ { "metadata": { "ExecuteTime": { - "end_time": "2024-05-26T18:47:36.354084Z", - "start_time": "2024-05-26T18:47:36.352268Z" + "end_time": "2024-05-26T22:01:18.265598Z", + "start_time": "2024-05-26T22:01:18.263847Z" + } + }, + "cell_type": "code", + "source": [ + "def generate_ode_output(process_address: str, model_fp: str, step_size: float, duration: float):\n", + " pass\n" + ], + "id": "d420c3e7fcd6d001", + "outputs": [], + "execution_count": 5 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-05-26T22:01:18.267683Z", + "start_time": "2024-05-26T22:01:18.266336Z" } }, "cell_type": "code", "source": "from biosimulator_processes.instance import plot_ode_output_data", "id": "a7cf4c427f5eeafc", "outputs": [], - "execution_count": 5 + "execution_count": 6 }, { "metadata": { "ExecuteTime": { - "end_time": "2024-05-26T18:47:36.445755Z", - "start_time": "2024-05-26T18:47:36.354856Z" + "end_time": "2024-05-26T22:01:18.360169Z", + "start_time": "2024-05-26T22:01:18.268189Z" } }, "cell_type": "code", @@ -165,20 +182,379 @@ "output_type": "display_data" } ], - "execution_count": 6 + "execution_count": 7 }, { "metadata": { "ExecuteTime": { - "end_time": "2024-05-26T18:47:36.447869Z", - "start_time": "2024-05-26T18:47:36.446498Z" + "end_time": "2024-05-26T22:07:26.656611Z", + "start_time": "2024-05-26T22:07:26.624041Z" } }, "cell_type": "code", - "source": "", + "source": [ + "from basico import *\n", + "\n", + "mod = load_model(model_fp)\n", + "copasi_species = get_species(model=mod)\n", + "\n", + "run_time_course(\n", + " start_time=0,\n", + " duration=duration,\n", + " step_number=400,\n", + " update_model=True,\n", + " model=mod)" + ], "id": "2886af0283eb3da3", + "outputs": [ + { + "data": { + "text/plain": [ + " T E I\n", + "Time \n", + "0.0 1.000000 1.000000 1.000000\n", + "0.1 1.018163 0.999020 0.367911\n", + "0.2 1.036655 0.998079 0.135378\n", + "0.3 1.055484 0.997178 0.049835\n", + "0.4 1.074654 0.996318 0.018366\n", + "... ... ... ...\n", + "9.6 5.629215 1.214479 0.000325\n", + "9.7 5.731456 1.222184 0.000333\n", + "9.8 5.835554 1.230073 0.000342\n", + "9.9 5.941543 1.238147 0.000350\n", + "10.0 6.049457 1.246411 0.000359\n", + "\n", + "[101 rows x 3 columns]" + ], + "text/html": [ + "
\n", + " | T | \n", + "E | \n", + "I | \n", + "
---|---|---|---|
Time | \n", + "\n", + " | \n", + " | \n", + " |
0.0 | \n", + "1.000000 | \n", + "1.000000 | \n", + "1.000000 | \n", + "
0.1 | \n", + "1.018163 | \n", + "0.999020 | \n", + "0.367911 | \n", + "
0.2 | \n", + "1.036655 | \n", + "0.998079 | \n", + "0.135378 | \n", + "
0.3 | \n", + "1.055484 | \n", + "0.997178 | \n", + "0.049835 | \n", + "
0.4 | \n", + "1.074654 | \n", + "0.996318 | \n", + "0.018366 | \n", + "
... | \n", + "... | \n", + "... | \n", + "... | \n", + "
9.6 | \n", + "5.629215 | \n", + "1.214479 | \n", + "0.000325 | \n", + "
9.7 | \n", + "5.731456 | \n", + "1.222184 | \n", + "0.000333 | \n", + "
9.8 | \n", + "5.835554 | \n", + "1.230073 | \n", + "0.000342 | \n", + "
9.9 | \n", + "5.941543 | \n", + "1.238147 | \n", + "0.000350 | \n", + "
10.0 | \n", + "6.049457 | \n", + "1.246411 | \n", + "0.000359 | \n", + "
101 rows × 3 columns
\n", + "