From 190f083d221716842e2f5f371b9f70ce114fac63 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 2 May 2024 08:52:42 +0200 Subject: [PATCH 1/5] GHA: Let dependabot update actions (#2416) --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..d3e0189bdb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-patch", "version-update:semver-minor"] From 80c8cfafb96e211bfffa0d56829d5084f97a7b58 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 2 May 2024 10:19:09 +0200 Subject: [PATCH 2/5] Increase test tolerances (#2419) Fix test failures related to switching from macos-12 to macos-14-arm64. Fixes #2415. --- python/tests/splines_utils.py | 13 ++++--------- python/tests/test_sbml_import.py | 2 +- tests/cpp/steadystate/tests1.cpp | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/python/tests/splines_utils.py b/python/tests/splines_utils.py index 99c0da880c..19fd84eee6 100644 --- a/python/tests/splines_utils.py +++ b/python/tests/splines_utils.py @@ -6,6 +6,7 @@ import math import os +import platform import uuid from tempfile import mkdtemp from typing import Any @@ -716,13 +717,7 @@ def param_by_name(id): if sllh_atol is None: sllh_atol = np.finfo(float).eps sllh_err_abs = abs(sllh).max() - if ( - sllh_err_abs > sllh_atol and debug is not True - ) or debug == "print": - print(f"sllh_atol={sllh_atol}") - print(f"sllh_err_abs = {sllh_err_abs}") - if not debug: - assert sllh_err_abs <= sllh_atol + assert sllh_err_abs <= sllh_atol, f"{sllh_err_abs=} {sllh_atol=}" else: assert sllh is None @@ -917,11 +912,11 @@ def example_spline_1( extrapolate=extrapolate, ) - if os.name == "nt": + if os.name == "nt" or platform.system() == "Darwin": tols = ( dict(llh_rtol=1e-15, x_rtol=1e-8, x_atol=1e-7), dict(llh_rtol=1e-15, x_rtol=1e-8, x_atol=1e-7), - dict(llh_rtol=1e-15, sllh_atol=5e-8, x_rtol=1e-8, x_atol=1e-7), + dict(llh_rtol=1e-15, sllh_atol=5e-7, x_rtol=1e-8, x_atol=1e-7), ) else: tols = ( diff --git a/python/tests/test_sbml_import.py b/python/tests/test_sbml_import.py index f0400396f8..4936a3c901 100644 --- a/python/tests/test_sbml_import.py +++ b/python/tests/test_sbml_import.py @@ -759,7 +759,7 @@ def test_constraints(): # in practice assert np.any(rdata.x < 0) - amici_solver.setRelativeTolerance(1e-14) + amici_solver.setRelativeTolerance(1e-13) amici_solver.setConstraints( [Constraint.non_negative, Constraint.non_negative] ) diff --git a/tests/cpp/steadystate/tests1.cpp b/tests/cpp/steadystate/tests1.cpp index e939a84ff2..109cc9eecb 100644 --- a/tests/cpp/steadystate/tests1.cpp +++ b/tests/cpp/steadystate/tests1.cpp @@ -1,7 +1,6 @@ #include "testfunctions.h" #include "wrapfunctions.h" -#include #include @@ -175,7 +174,8 @@ TEST(ExampleSteadystate, SensitivityForwardErrorNewt) TEST(ExampleSteadystate, SensitivityForwardDense) { - amici::simulateVerifyWrite("/model_steadystate/sensiforwarddense/"); + amici::simulateVerifyWrite("/model_steadystate/sensiforwarddense/", + 1e-9, TEST_RTOL); } TEST(ExampleSteadystate, SensiFwdNewtonPreeq) From 304c23a2d2120535106dca1999d225f819851b1f Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 2 May 2024 10:19:52 +0200 Subject: [PATCH 3/5] Remove setup.cfg (#2420) Remove setup.cfg, originally removed in #2408, accidentally re-added in #2391 --- python/sdist/setup.cfg | 91 ------------------------------------------ 1 file changed, 91 deletions(-) delete mode 100644 python/sdist/setup.cfg diff --git a/python/sdist/setup.cfg b/python/sdist/setup.cfg deleted file mode 100644 index 7b8f7b32e7..0000000000 --- a/python/sdist/setup.cfg +++ /dev/null @@ -1,91 +0,0 @@ -[metadata] -name = amici -description = Advanced multi-language Interface to CVODES and IDAS -version = file: amici/version.txt -license = BSD 3-Clause License -url = https://github.com/AMICI-dev/AMICI -keywords = differential equations, simulation, ode, cvodes, systems biology, sensitivity analysis, sbml, pysb, petab -author = Fabian Froehlich, Jan Hasenauer, Daniel Weindl and Paul Stapor -author_email = fabian_froehlich@hms.harvard.edu -project_urls = - Bug Reports = https://github.com/AMICI-dev/AMICI/issues - Source = https://github.com/AMICI-dev/AMICI - Documentation = https://amici.readthedocs.io/en/latest/ -classifiers = - Development Status :: 5 - Production/Stable - Intended Audience :: Science/Research - License :: OSI Approved :: BSD License - Operating System :: POSIX :: Linux - Operating System :: MacOS :: MacOS X - Programming Language :: Python - Programming Language :: C++ - Topic :: Scientific/Engineering :: Bio-Informatics - -[options] -packages = find_namespace: -package_dir = - amici = amici -python_requires = >=3.10 -install_requires = - cmake-build-extension==0.5.1 - sympy>=1.9 - numpy>=1.21.4; python_version>='3.10' - numpy>=1.23.2; python_version=='3.11' - numpy>=1.26.2; python_version=='3.12' - numpy; python_version>='3.13' - python-libsbml - pandas>=2.0.2 - pyarrow - wurlitzer - toposort - setuptools>=48 - mpmath -include_package_data = True -zip_safe = False - -[options.extras_require] -# Don't include any URLs here - they are not supported by PyPI: -# HTTPError: 400 Bad Request from https://upload.pypi.org/legacy/ -# Invalid value for requires_dist. Error: Can't have direct dependency: ... -petab = petab>=0.2.9 -pysb = pysb>=1.13.1 -test = - benchmark_models_petab @ git+https://github.com/Benchmarking-Initiative/Benchmark-Models-PEtab.git@master#subdirectory=src/python - h5py - pytest - pytest-cov - pytest-rerunfailures - coverage - shyaml - antimony>=2.13 - # see https://github.com/sys-bio/antimony/issues/92 - # unsupported x86_64 / x86_64h - antimony!=2.14; platform_system=='Darwin' and platform_machine in 'x86_64h' - scipy - pooch -vis = - matplotlib - seaborn -examples = - jupyter - scipy - -[options.package_data] -amici = - amici/include/amici/* - src/*template* - swig/* - libs/* - setup.py.template - -[options.exclude_package_data] -* = - README.txt - - -[options.entry_points] - -; amici_import_petab.py is kept for backwards compatibility -console_scripts = - amici_import_petab = amici.petab.cli.import_petab:_main - amici_import_petab.py = amici.petab.cli.import_petab:_main From 6b05ddd19a19b5d18a5ab6656f82bfdc39ec9c77 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 2 May 2024 11:03:20 +0200 Subject: [PATCH 4/5] Faster generation of drootdt_total for models without state-dependent root functions (#2417) Don't compute things we don't need. For my test model, this reduces code generation time from 76s to 12s (-83%). --- python/sdist/amici/de_model.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/python/sdist/amici/de_model.py b/python/sdist/amici/de_model.py index 0caac635a7..0e48bf3af8 100644 --- a/python/sdist/amici/de_model.py +++ b/python/sdist/amici/de_model.py @@ -1561,16 +1561,18 @@ def _compute_equation(self, name: str) -> None: self._eqs[name] = smart_jacobian(self.eq("root"), time_symbol) elif name == "drootdt_total": - # backsubstitution of optimized right-hand side terms into RHS - # calling subs() is costly. Due to looping over events though, the - # following lines are only evaluated if a model has events - w_sorted = toposort_symbols( - dict(zip(self.sym("w"), self.eq("w"), strict=True)) - ) - tmp_xdot = smart_subs_dict(self.eq("xdot"), w_sorted) self._eqs[name] = self.eq("drootdt") - if self.num_states_solver(): - self._eqs[name] += smart_multiply(self.eq("drootdx"), tmp_xdot) + # backsubstitution of optimized right-hand side terms into RHS + # calling subs() is costly. We can skip it if we don't have any + # state-dependent roots. + if self.num_states_solver() and not smart_is_zero_matrix( + drootdx := self.eq("drootdx") + ): + w_sorted = toposort_symbols( + dict(zip(self.sym("w"), self.eq("w"), strict=True)) + ) + tmp_xdot = smart_subs_dict(self.eq("xdot"), w_sorted) + self._eqs[name] += smart_multiply(drootdx, tmp_xdot) elif name == "deltax": # fill boluses for Heaviside functions, as empty state updates From 8c3b59ac9f47f798d07cdeef79ddf6df6c36d5b4 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 3 May 2024 15:31:11 +0200 Subject: [PATCH 5/5] Add stacklevel to warnings (#2421) Make it easier to find out where warnings originate from. --- python/sdist/amici/logging.py | 3 ++- python/sdist/amici/parameter_mapping.py | 1 + python/sdist/amici/petab/conditions.py | 1 + python/sdist/amici/petab_import.py | 1 + python/sdist/amici/petab_import_pysb.py | 1 + python/sdist/amici/petab_objective.py | 1 + python/sdist/amici/petab_simulate.py | 1 + python/sdist/amici/petab_util.py | 1 + python/sdist/amici/sbml_import.py | 18 ++++++++++++------ python/sdist/amici/swig_wrappers.py | 6 ++++-- python/sdist/pyproject.toml | 1 + 11 files changed, 26 insertions(+), 9 deletions(-) diff --git a/python/sdist/amici/logging.py b/python/sdist/amici/logging.py index 0a345ee0a7..1f5ae1f175 100644 --- a/python/sdist/amici/logging.py +++ b/python/sdist/amici/logging.py @@ -175,7 +175,8 @@ def get_logger( elif kwargs: warnings.warn( "AMICI logger already exists, ignoring keyword " - "arguments to setup_logger" + "arguments to setup_logger", + stacklevel=2, ) logger = logging.getLogger(logger_name) diff --git a/python/sdist/amici/parameter_mapping.py b/python/sdist/amici/parameter_mapping.py index b39d54c87e..dc369b448b 100644 --- a/python/sdist/amici/parameter_mapping.py +++ b/python/sdist/amici/parameter_mapping.py @@ -27,6 +27,7 @@ warnings.warn( "Importing amici.parameter_mapping is deprecated. Use `amici.petab.parameter_mapping` instead.", DeprecationWarning, + stacklevel=2, ) __all__ = [ diff --git a/python/sdist/amici/petab/conditions.py b/python/sdist/amici/petab/conditions.py index 831420f68e..c0b702b69d 100644 --- a/python/sdist/amici/petab/conditions.py +++ b/python/sdist/amici/petab/conditions.py @@ -67,6 +67,7 @@ def fill_in_parameters( "The following problem parameters were not used: " + str(unused_parameters), RuntimeWarning, + stacklevel=2, ) for edata, mapping_for_condition in zip( diff --git a/python/sdist/amici/petab_import.py b/python/sdist/amici/petab_import.py index b81484c1cc..1bcadaa1d2 100644 --- a/python/sdist/amici/petab_import.py +++ b/python/sdist/amici/petab_import.py @@ -13,6 +13,7 @@ warnings.warn( "Importing amici.petab_import is deprecated. Use `amici.petab` instead.", DeprecationWarning, + stacklevel=2, ) from .petab.import_helpers import ( # noqa # pylint: disable=unused-import diff --git a/python/sdist/amici/petab_import_pysb.py b/python/sdist/amici/petab_import_pysb.py index a1597d53b5..4d73a4bab3 100644 --- a/python/sdist/amici/petab_import_pysb.py +++ b/python/sdist/amici/petab_import_pysb.py @@ -14,6 +14,7 @@ warnings.warn( "Importing amici.petab_import_pysb is deprecated. Use `amici.petab.pysb_import` instead.", DeprecationWarning, + stacklevel=2, ) __all__ = [ diff --git a/python/sdist/amici/petab_objective.py b/python/sdist/amici/petab_objective.py index 01724b7a7d..6d0dc44d84 100644 --- a/python/sdist/amici/petab_objective.py +++ b/python/sdist/amici/petab_objective.py @@ -12,6 +12,7 @@ warnings.warn( f"Importing {__name__} is deprecated. Use `amici.petab.simulations` instead.", DeprecationWarning, + stacklevel=2, ) from .petab.conditions import fill_in_parameters # noqa: F401 diff --git a/python/sdist/amici/petab_simulate.py b/python/sdist/amici/petab_simulate.py index 2dd25a8e4a..5f81d02a93 100644 --- a/python/sdist/amici/petab_simulate.py +++ b/python/sdist/amici/petab_simulate.py @@ -11,6 +11,7 @@ warnings.warn( f"Importing {__name__} is deprecated. Use `amici.petab.simulator` instead.", DeprecationWarning, + stacklevel=2, ) from .petab.simulator import PetabSimulator # noqa: F401 diff --git a/python/sdist/amici/petab_util.py b/python/sdist/amici/petab_util.py index ff202bf2e0..cf12a7411d 100644 --- a/python/sdist/amici/petab_util.py +++ b/python/sdist/amici/petab_util.py @@ -15,6 +15,7 @@ warnings.warn( f"Importing {__name__} is deprecated. Use `amici.petab.util` instead.", DeprecationWarning, + stacklevel=2, ) __all__ = [ diff --git a/python/sdist/amici/sbml_import.py b/python/sdist/amici/sbml_import.py index 843b954a8f..a26c6e7d4a 100644 --- a/python/sdist/amici/sbml_import.py +++ b/python/sdist/amici/sbml_import.py @@ -442,7 +442,8 @@ def sbml2amici( if not has_clibs: warnings.warn( "AMICI C++ extensions have not been built. " - "Generated model code, but unable to compile." + "Generated model code, but unable to compile.", + stacklevel=2, ) exporter.compile_model() @@ -1838,7 +1839,8 @@ def _process_event_observables( f'Event observable {eo["name"]} uses `t` in ' "it's formula which is not the time variable. " "For the time variable, please use `time` " - "instead!" + "instead!", + stacklevel=1, ) # check for nesting of observables (unsupported) @@ -2157,7 +2159,8 @@ def _get_conservation_laws_demartino( "Conservation laws for non-constant species in " "combination with parameterized stoichiometric " "coefficients are not currently supported " - "and will be turned off." + "and will be turned off.", + stacklevel=1, ) return [] @@ -2234,7 +2237,8 @@ def _get_conservation_laws_rref( "Conservation laws for non-constant species in " "combination with parameterized stoichiometric " "coefficients are not currently supported " - "and will be turned off." + "and will be turned off.", + stacklevel=1, ) return [] @@ -3048,7 +3052,8 @@ def _non_const_conservation_laws_supported(sbml_model: sbml.Model) -> bool: warnings.warn( "Conservation laws for non-constant species in " "models with RateRules are currently not supported " - "and will be turned off." + "and will be turned off.", + stacklevel=1, ) return False @@ -3060,7 +3065,8 @@ def _non_const_conservation_laws_supported(sbml_model: sbml.Model) -> bool: warnings.warn( "Conservation laws for non-constant species in " "models with Species-AssignmentRules are currently not " - "supported and will be turned off." + "supported and will be turned off.", + stacklevel=1, ) return False diff --git a/python/sdist/amici/swig_wrappers.py b/python/sdist/amici/swig_wrappers.py index 3c4df44809..5762f50bec 100644 --- a/python/sdist/amici/swig_wrappers.py +++ b/python/sdist/amici/swig_wrappers.py @@ -78,7 +78,8 @@ def runAmiciSimulation( warnings.warn( "Adjoint sensitivity analysis for models with discontinuous right hand sides (events/piecewise functions) has not been thoroughly tested." "Sensitivities might be wrong. Tracked at https://github.com/AMICI-dev/AMICI/issues/18. " - "Adjoint sensitivity analysis may work if the location of the discontinuity is not parameter-dependent, but we still recommend testing accuracy of gradients." + "Adjoint sensitivity analysis may work if the location of the discontinuity is not parameter-dependent, but we still recommend testing accuracy of gradients.", + stacklevel=1, ) with _capture_cstdout(): @@ -119,7 +120,8 @@ def runAmiciSimulations( warnings.warn( "Adjoint sensitivity analysis for models with discontinuous right hand sides (events/piecewise functions) has not been thoroughly tested. " "Sensitivities might be wrong. Tracked at https://github.com/AMICI-dev/AMICI/issues/18. " - "Adjoint sensitivity analysis may work if the location of the discontinuity is not parameter-dependent, but we still recommend testing accuracy of gradients." + "Adjoint sensitivity analysis may work if the location of the discontinuity is not parameter-dependent, but we still recommend testing accuracy of gradients.", + stacklevel=1, ) with _capture_cstdout(): diff --git a/python/sdist/pyproject.toml b/python/sdist/pyproject.toml index 58d39d4ea7..7c903273b5 100644 --- a/python/sdist/pyproject.toml +++ b/python/sdist/pyproject.toml @@ -130,4 +130,5 @@ line-length = 79 extend-include = ["*.ipynb"] [tool.ruff.lint] +extend-select = ["B028"] ignore = ["E402", "F403", "F405", "E741"]