diff --git a/Dockerfile b/Dockerfile index b344f80..27ec033 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Base OS FROM python:3.9-slim-buster -ARG VERSION="0.1.15" +ARG VERSION="0.1.16" ARG SIMULATOR_VERSION="0.11.18" # metadata diff --git a/biosimulators.json b/biosimulators.json index a06a0d3..ce905a8 100644 --- a/biosimulators.json +++ b/biosimulators.json @@ -261,7 +261,15 @@ { "variables": "parameter values", "targetPattern": "/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter/@value" - } + }, + { + "variables": "reaction fluxes", + "targetPattern": "/sbml:sbml/sbml:model/sbml:listOfReactions/sbml:reaction" + }, + { + "variables": "compartment sizes", + "targetPattern": "/sbml:sbml/sbml:model/sbml:listOfCompartments/sbml:compartment" + } ], "availableSoftwareInterfaceTypes": [ "library", diff --git a/biosimulators_amici/_version.py b/biosimulators_amici/_version.py index ac1125f..b7e15fa 100644 --- a/biosimulators_amici/_version.py +++ b/biosimulators_amici/_version.py @@ -1 +1 @@ -__version__ = '0.1.15' +__version__ = '0.1.16' diff --git a/biosimulators_amici/core.py b/biosimulators_amici/core.py index c728a41..e33e019 100644 --- a/biosimulators_amici/core.py +++ b/biosimulators_amici/core.py @@ -319,7 +319,7 @@ def extract_variables_from_results(model, sbml_model, variables, target_x_paths_ :obj:`NotImplementedError`: if a symbol could not be recorded :obj:`ValueError`: if a target could not be recorded """ - var_id_to_state_index = {id: index for index, id in enumerate(model.getStateIds())} + sbml_id_to_obs_index = {id: index for index, id in enumerate(model.getObservableIds())} variable_results = VariableResults() unpredicted_symbols = [] @@ -332,12 +332,12 @@ def extract_variables_from_results(model, sbml_model, variables, target_x_paths_ unpredicted_symbols.append(variable.symbol) else: - var_id = target_x_paths_ids.get(variable.target, None) - i_state = var_id_to_state_index.get(var_id, None) - if i_state is None: + sbml_id = target_x_paths_ids.get(variable.target, None) + i_obs = sbml_id_to_obs_index.get(sbml_id, None) + if i_obs is None: unpredicted_targets.append(variable.target) else: - variable_results[variable.id] = results['x'][:, i_state] + variable_results[variable.id] = results['y'][:, i_obs] if unpredicted_symbols: raise NotImplementedError("".join([ @@ -353,10 +353,7 @@ def extract_variables_from_results(model, sbml_model, variables, target_x_paths_ '\n - '.join(sorted(unpredicted_targets)), ), 'Targets must have one of the following ids:\n - {}'.format( - '\n - '.join(sorted(( - [s.getId() for s in sbml_model.species] - + [p.getId() for p in sbml_model.parameters] - ))), + '\n - '.join(sorted(model.getObservableIds())), ), ])) diff --git a/tests/test_core_main.py b/tests/test_core_main.py index 5264031..9f80837 100644 --- a/tests/test_core_main.py +++ b/tests/test_core_main.py @@ -87,6 +87,86 @@ def test_exec_sed_task_successfully(self): target="/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='IL']", target_namespaces=self.NAMESPACES, task=task), + sedml_data_model.Variable( + id='kf_0', + target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='kf_0']", + target_namespaces=self.NAMESPACES, + task=task), + sedml_data_model.Variable( + id='comp1', + target="/sbml:sbml/sbml:model/sbml:listOfCompartments/sbml:compartment[@id='comp1']", + target_namespaces=self.NAMESPACES, + task=task), + sedml_data_model.Variable( + id='React0', + target="/sbml:sbml/sbml:model/sbml:listOfReactions/sbml:reaction[@id='React0']", + target_namespaces=self.NAMESPACES, + task=task), + ] + + variable_results, _ = core.exec_sed_task(task, variables) + + self.assertTrue(sorted(variable_results.keys()), sorted([var.id for var in variables])) + self.assertEqual(variable_results[variables[0].id].shape, (task.simulation.number_of_points + 1,)) + numpy.testing.assert_almost_equal( + variable_results['time'], + numpy.linspace(task.simulation.output_start_time, task.simulation.output_end_time, task.simulation.number_of_points + 1), + ) + + for results in variable_results.values(): + self.assertFalse(numpy.any(numpy.isnan(results))) + numpy.testing.assert_almost_equal( + variable_results['kf_0'], + numpy.full((task.simulation.number_of_points + 1), 300000000.), + ) + numpy.testing.assert_almost_equal( + variable_results['comp1'], + numpy.full((task.simulation.number_of_points + 1), 1E-16), + ) + + def test_exec_sed_task_successfully_with_assignment_rule(self): + task = sedml_data_model.Task( + model=sedml_data_model.Model( + source=os.path.join(os.path.dirname(__file__), 'fixtures', 'BIOMD0000000297_url.xml'), + language=sedml_data_model.ModelLanguage.SBML.value, + changes=[], + ), + simulation=sedml_data_model.UniformTimeCourseSimulation( + algorithm=sedml_data_model.Algorithm( + kisao_id='KISAO_0000496', + ), + initial_time=0., + output_start_time=0., + output_end_time=10., + number_of_points=10, + ), + ) + + variables = [ + sedml_data_model.Variable( + id='time', + symbol=sedml_data_model.Symbol.time, + task=task), + sedml_data_model.Variable( + id='kswe', + target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='kswe']", + target_namespaces=self.NAMESPACES, + task=task), + sedml_data_model.Variable( + id='kswe_prime', + target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='kswe_prime']", + target_namespaces=self.NAMESPACES, + task=task), + sedml_data_model.Variable( + id='compartment', + target="/sbml:sbml/sbml:model/sbml:listOfCompartments/sbml:compartment[@id='compartment']", + target_namespaces=self.NAMESPACES, + task=task), + sedml_data_model.Variable( + id='R1', + target="/sbml:sbml/sbml:model/sbml:listOfReactions/sbml:reaction[@id='R1']", + target_namespaces=self.NAMESPACES, + task=task), ] variable_results, _ = core.exec_sed_task(task, variables) @@ -100,6 +180,14 @@ def test_exec_sed_task_successfully(self): for results in variable_results.values(): self.assertFalse(numpy.any(numpy.isnan(results))) + numpy.testing.assert_almost_equal( + variable_results['kswe_prime'], + numpy.full((task.simulation.number_of_points + 1), 2.), + ) + numpy.testing.assert_almost_equal( + variable_results['compartment'], + numpy.full((task.simulation.number_of_points + 1), 1.), + ) def test_exec_sed_task_error_handling(self): with mock.patch.dict('os.environ', {'ALGORITHM_SUBSTITUTION_POLICY': 'NONE'}):