From 2434e8e542694e55a1508749d9fd6bdc8064df91 Mon Sep 17 00:00:00 2001 From: Jonathan Karr Date: Wed, 30 Dec 2020 13:16:15 -0500 Subject: [PATCH] updating for improved handling of algorithm substitution policy --- Dockerfile | 5 +++-- biosimulators_copasi/__main__.py | 7 ++++++- biosimulators_copasi/_version.py | 2 +- biosimulators_copasi/utils.py | 27 ++++++++++++++++++++++++++- requirements.txt | 2 +- tests/test_utils.py | 16 ++++++++++++++++ 6 files changed, 53 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index b0d5ebe..60b603c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ # Base OS FROM python:3.7.9-slim-buster -ARG VERSION="0.1.9" +ARG VERSION="0.1.10" ARG SIMULATOR_VERSION=4.30.233 # metadata @@ -46,7 +46,8 @@ COPY . /root/Biosimulators_COPASI RUN pip install /root/Biosimulators_COPASI \ && rm -rf /root/Biosimulators_COPASI RUN pip install "python_copasi==${SIMULATOR_VERSION}" -ENV MPLBACKEND=PDF +ENV ALGORITHM_SUBSTITUTION_POLICY=SAME_FRAMEWORK \ + MPLBACKEND=PDF # Entrypoint ENTRYPOINT ["copasi"] diff --git a/biosimulators_copasi/__main__.py b/biosimulators_copasi/__main__.py index e13ba6d..f9c7f68 100644 --- a/biosimulators_copasi/__main__.py +++ b/biosimulators_copasi/__main__.py @@ -10,11 +10,16 @@ from ._version import __version__ from .core import exec_sedml_docs_in_combine_archive from biosimulators_utils.simulator.cli import build_cli +from biosimulators_utils.simulator.data_model import AlgorithmSubstitutionPolicy +from biosimulators_utils.simulator.environ import ENVIRONMENT_VARIABLES import COPASI App = build_cli('copasi', __version__, 'COPASI', COPASI.__version__, 'http://copasi.org', - exec_sedml_docs_in_combine_archive) + exec_sedml_docs_in_combine_archive, + environment_variables=[ + ENVIRONMENT_VARIABLES[AlgorithmSubstitutionPolicy] + ]) def main(): diff --git a/biosimulators_copasi/_version.py b/biosimulators_copasi/_version.py index 1c98a23..850505a 100644 --- a/biosimulators_copasi/_version.py +++ b/biosimulators_copasi/_version.py @@ -1 +1 @@ -__version__ = '0.1.9' +__version__ = '0.1.10' diff --git a/biosimulators_copasi/utils.py b/biosimulators_copasi/utils.py index 652d91b..2f99661 100644 --- a/biosimulators_copasi/utils.py +++ b/biosimulators_copasi/utils.py @@ -8,8 +8,13 @@ from .data_model import KISAO_ALGORITHMS_MAP, KISAO_PARAMETERS_MAP from biosimulators_utils.data_model import ValueType +from biosimulators_utils.simulator.data_model import AlgorithmSubstitutionPolicy, ALGORITHM_SUBSTITUTION_POLICY_LEVELS +from biosimulators_utils.simulator.exceptions import AlgorithmCannotBeSubstitutedException +from biosimulators_utils.simulator.utils import get_algorithm_substitution_policy +from biosimulators_utils.simulator.warnings import AlgorithmSubstitutedWarning from biosimulators_utils.utils.core import validate_str_value, parse_value import COPASI +import warnings __all__ = ['get_algorithm_id', 'set_algorithm_parameter_value'] @@ -23,10 +28,30 @@ def get_algorithm_id(kisao_id): Returns: :obj:`int`: COPASI id for algorithm """ + requested_kisao_id = kisao_id + + substitution_policy = get_algorithm_substitution_policy() + if kisao_id in ['KISAO_0000088', 'KISAO_0000089']: + alg_name = 'LSODA' if kisao_id == 'KISAO_0000088' else 'LSODAR' + if ( + ALGORITHM_SUBSTITUTION_POLICY_LEVELS[substitution_policy] + >= ALGORITHM_SUBSTITUTION_POLICY_LEVELS[AlgorithmSubstitutionPolicy.SAME_FRAMEWORK] + ): + warnings.warn('Hybrid LSODA/LSODAR method (KISAO_0000560) will be used rather than {} ({}).'.format( + alg_name, kisao_id), + AlgorithmSubstitutedWarning) + kisao_id = 'KISAO_0000560' + else: + raise AlgorithmCannotBeSubstitutedException(( + '{} ({}) cannot be substituted to the hybrid LSODA/LSODAR method (KISAO_0000560) ' + 'under the current algorithm substitution policy {}.').format( + alg_name, kisao_id, substitution_policy.name + )) + alg = KISAO_ALGORITHMS_MAP.get(kisao_id, None) if alg is None: raise NotImplementedError( - "Algorithm with KiSAO id '{}' is not supported".format(kisao_id)) + "Algorithm with KiSAO id '{}' is not supported".format(requested_kisao_id)) return alg['id'] diff --git a/requirements.txt b/requirements.txt index 2f2ea15..69d9f1e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -biosimulators_utils >= 0.1.23 +biosimulators_utils >= 0.1.24 numpy python_copasi >= 4.30.233 diff --git a/tests/test_utils.py b/tests/test_utils.py index d3d6c61..cd1b984 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,9 @@ from biosimulators_copasi import data_model from biosimulators_copasi import utils from biosimulators_utils.data_model import ValueType +from biosimulators_utils.simulator.exceptions import AlgorithmCannotBeSubstitutedException +from biosimulators_utils.simulator.warnings import AlgorithmSubstitutedWarning +from unittest import mock import COPASI import os import unittest @@ -9,6 +12,19 @@ class UtilsTestCase(unittest.TestCase): def test_get_algorithm_id(self): self.assertEqual(utils.get_algorithm_id('KISAO_0000027'), COPASI.CTaskEnum.Method_stochastic) + + self.assertEqual(utils.get_algorithm_id('KISAO_0000560'), COPASI.CTaskEnum.Method_deterministic) + + with self.assertWarns(AlgorithmSubstitutedWarning): + self.assertEqual(utils.get_algorithm_id('KISAO_0000088'), COPASI.CTaskEnum.Method_deterministic) + + with self.assertWarns(AlgorithmSubstitutedWarning): + self.assertEqual(utils.get_algorithm_id('KISAO_0000089'), COPASI.CTaskEnum.Method_deterministic) + + with mock.patch.dict(os.environ, {'ALGORITHM_SUBSTITUTION_POLICY': 'NONE'}): + with self.assertRaises(AlgorithmCannotBeSubstitutedException): + self.assertEqual(utils.get_algorithm_id('KISAO_0000088'), COPASI.CTaskEnum.Method_deterministic) + with self.assertRaises(NotImplementedError): utils.get_algorithm_id('KISAO_0000000')