Skip to content

Commit

Permalink
feat: added handling for line continuations in model files, added cap…
Browse files Browse the repository at this point in the history
…ability to ignore only directives and range options in execution of individual simulation tasks
  • Loading branch information
jonrkarr committed Feb 23, 2022
1 parent 2bc7997 commit 4120690
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 7 deletions.
9 changes: 7 additions & 2 deletions biosimulators_xpp/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from biosimulators_utils.combine.exec import exec_sedml_docs_in_archive
from biosimulators_utils.config import get_config, Config # noqa: F401
from biosimulators_utils.log.data_model import CombineArchiveLog, TaskLog, StandardOutputErrorCapturerLevel # noqa: F401
from biosimulators_utils.model_lang.xpp.validation import validate_model
from biosimulators_utils.model_lang.xpp.validation import validate_model, sanitize_model
from biosimulators_utils.report.data_model import ReportFormat, SedDocumentResults # noqa: F401
from biosimulators_utils.sedml import validation
from biosimulators_utils.sedml.data_model import (Task, ModelLanguage, ModelAttributeChange, # noqa: F401
Expand Down Expand Up @@ -137,7 +137,7 @@ def exec_sed_task(task, variables, preprocessed_task=None, log=None, config=None
exec_kisao_id = preprocessed_task['algorithm_kisao_id']

# run simulation
raw_results = exec_xpp_simulation(model.source, xpp_sim)
raw_results = exec_xpp_simulation(preprocessed_task['model_filename'], xpp_sim)

# transform results
variable_results = get_results_of_sed_variables(sim, raw_results, variables)
Expand Down Expand Up @@ -192,13 +192,18 @@ def preprocess_sed_task(task, variables, config=None):
# read model
_, _, xpp_sim = validate_model(model.source)

# sanitize model file
exclude_options = ['output', 'range', 'rangeover', 'rangelow', 'rangehigh', 'rangestep', 'rangereset', 'rangeoldic']
sanitized_filename = sanitize_model(model.source, keep_only_directives=False, exclude_options=exclude_options)

# validate observables
validate_variables(xpp_sim, variables)

# setup simulation
exec_kisao_id = set_up_simulation(sim, xpp_sim['simulation_method'], config=config)

return {
'model_filename': sanitized_filename,
'xpp_simulation': xpp_sim,
'algorithm_kisao_id': exec_kisao_id,
}
18 changes: 15 additions & 3 deletions biosimulators_xpp/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ def set_up_simulation(sed_sim, xpp_sim, config=None):
:obj:`str`: KiSAO id of the algorithm to execute
"""
xpp_sim['t0'] = str(sed_sim.initial_time)
if sed_sim.output_start_time != sed_sim.initial_time:
xpp_sim['trans'] = str(sed_sim.output_start_time)
xpp_sim['total'] = str(sed_sim.output_end_time - sed_sim.initial_time)
xpp_sim['dt'] = str((sed_sim.output_end_time - sed_sim.output_start_time) / sed_sim.number_of_points)
xpp_sim['njmp'] = str(1)
Expand Down Expand Up @@ -274,7 +276,12 @@ def exec_xpp_simulation(sim_filename, simulation,
if overwrite_method:
fid, temp_sim_filename = tempfile.mkstemp(suffix='.ode')
os.close(fid)
write_method_to_xpp_simulation_file(simulation['simulation_method'], sim_filename, temp_sim_filename)
options = {
**simulation['simulation_method'],
**(simulation.get('other_numerics', None) or {}),
**(simulation.get('other', None) or {}),
}
write_method_to_xpp_simulation_file(options, sim_filename, temp_sim_filename)
cmd[1] = temp_sim_filename

# execute simulation
Expand Down Expand Up @@ -302,8 +309,13 @@ def exec_xpp_simulation(sim_filename, simulation,
os.remove(temp_sim_filename)

# raise exception if XPP failed
if result.returncode != 0:
raise RuntimeError('XPP failed: {}'.format(result.stdout.decode("utf-8")))
stdout = result.stdout.decode("utf-8")
if (
result.returncode != 0
or 'Integration not completed' in stdout
or 'out of bounds' in stdout
):
raise RuntimeError('XPP failed: {}'.format(stdout))

# return results
return results
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
biosimulators_utils[logging] >= 0.1.120
biosimulators_utils[logging] >= 0.1.162
kisao >= 2.28
numpy
pandas
39 changes: 39 additions & 0 deletions tests/test_core_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,45 @@ def test_exec_sed_task_successfully(self):
variable_results_2, log = core.exec_sed_task(task, variables)
numpy.testing.assert_allclose(variable_results_2['u'][0], 0.3)

# output start time > initial time
task = sedml_data_model.Task(
model=sedml_data_model.Model(
source=self.EXAMPLE_MODEL_FILENAME,
language=sedml_data_model.ModelLanguage.XPP.value,
),
simulation=sedml_data_model.UniformTimeCourseSimulation(
initial_time=0.,
output_start_time=5.,
output_end_time=10.,
number_of_points=10,
algorithm=sedml_data_model.Algorithm(
kisao_id='KISAO_0000019',
),
),
)

variables = [
sedml_data_model.Variable(
id='Time',
symbol=sedml_data_model.Symbol.time,
task=task),
sedml_data_model.Variable(
id='u',
target="u",
task=task),
sedml_data_model.Variable(
id='v',
target="v",
task=task),
]

variable_results_3, log = core.exec_sed_task(task, variables)
self.assertEqual(set(variable_results_3.keys()), set(['Time', 'u', 'v']))
for variable_result in variable_results_3.values():
self.assertFalse(numpy.any(numpy.isnan(variable_result)))
numpy.testing.assert_allclose(variable_results_3['Time'], numpy.linspace(5., 10., 10 + 1))
numpy.testing.assert_allclose(variable_results_3['u'][0], variable_results['u'][5], rtol=1e-4)

def test_exec_sedml_docs_in_combine_archive_successfully(self):
doc, archive_filename = self._build_combine_archive()

Expand Down
6 changes: 5 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def test_set_up_simulation(self):

self.assertEqual(xpp_sim['simulation_method'], {
't0': '10.0',
'trans': '20.0',
'total': '20.0',
'dt': '1.0',
'njmp': '1',
Expand Down Expand Up @@ -158,6 +159,7 @@ def test_set_up_simulation(self):
utils.set_up_simulation(sed_sim, xpp_sim['simulation_method'])
self.assertEqual(xpp_sim['simulation_method'], {
't0': '10.0',
'trans': '20.0',
'total': '20.0',
'dt': '1.0',
'njmp': '1',
Expand Down Expand Up @@ -188,6 +190,7 @@ def test_set_up_simulation(self):

self.assertEqual(xpp_sim['simulation_method'], {
't0': '10.0',
'trans': '20.0',
'total': '20.0',
'dt': '1.0',
'njmp': '1',
Expand Down Expand Up @@ -336,13 +339,14 @@ def test_get_results_of_sed_variables(self):

utils.set_up_simulation(sed_sim, xpp_sim['simulation_method'])
self.assertEqual(xpp_sim['simulation_method']['t0'], '10.0')
self.assertEqual(xpp_sim['simulation_method']['trans'], '20.0')
self.assertEqual(xpp_sim['simulation_method']['total'], '20.0')
self.assertEqual(xpp_sim['simulation_method']['dt'], '0.5')
self.assertEqual(xpp_sim['simulation_method']['njmp'], '1')

xpp_results = utils.exec_xpp_simulation(filename, xpp_sim)
numpy.testing.assert_allclose(xpp_results.loc[:, Symbol.time.value],
numpy.linspace(10., 30., 40 + 1))
numpy.linspace(20., 30., 20 + 1))

sed_vars = [
Variable(id='time', symbol=Symbol.time.value),
Expand Down

0 comments on commit 4120690

Please sign in to comment.