diff --git a/.github/workflows/test_sbml_semantic_test_suite.yml b/.github/workflows/test_sbml_semantic_test_suite.yml index 537116debe..81ccae5fc5 100644 --- a/.github/workflows/test_sbml_semantic_test_suite.yml +++ b/.github/workflows/test_sbml_semantic_test_suite.yml @@ -7,7 +7,7 @@ on: pull_request: paths: - .github/workflows/test_sbml_semantic_test_suite.yml - - python/sdist/amici/de_export.py + - python/sdist/amici/exporters/sundials/de_export.py - python/sdist/amici/de_model_components.py - python/sdist/amici/de_model.py - python/sdist/amici/sbml_import.py diff --git a/CMakeLists.txt b/CMakeLists.txt index e94d2cd7c6..3ac0432f8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,7 +143,8 @@ else() set(VENDORED_SUNDIALS_INSTALL_DIR ${VENDORED_SUNDIALS_BUILD_DIR}) endif() set(SUNDIALS_ROOT "${VENDORED_SUNDIALS_INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}") -find_package(SUNDIALS 7.1.1 REQUIRED CONFIG PATHS "${SUNDIALS_ROOT}/cmake/sundials/" ) +find_package(SUNDIALS 7.1.1 REQUIRED CONFIG PATHS + "${SUNDIALS_ROOT}/cmake/sundials/") message(STATUS "Found SUNDIALS: ${SUNDIALS_DIR}") set(GSL_LITE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty/gsl") @@ -306,22 +307,25 @@ if(AMICI_PYTHON_BUILD_EXT_ONLY) "gsl_CONFIG_NARROW_THROWS_ON_TRUNCATION=1") endif() -# Create targets to make the sources show up in IDEs for convenience -# For template files -add_custom_target( - fileTemplates - SOURCES src/CMakeLists.template.cmake - src/main.template.cpp - src/model_header.template.h - src/model.template.cpp - src/wrapfunctions.template.h - src/wrapfunctions.template.cpp - swig/CMakeLists_model.cmake - swig/modelname.template.i - COMMENT "Dummy target for SWIG files") -set_target_properties( - fileTemplates PROPERTIES INCLUDE_DIRECTORIES - "${CMAKE_CURRENT_SOURCE_DIR}/include/") +if(NOT AMICI_PYTHON_BUILD_EXT_ONLY) + # Create targets to make the sources show up in IDEs for convenience For + # template files + set(template_dir "python/sdist/amici/exporters/sundials/templates") + add_custom_target( + fileTemplates + SOURCES ${template_dir}/CMakeLists.template.cmake + ${template_dir}//main.template.cpp + ${template_dir}//model_header.template.h + ${template_dir}//model.template.cpp + ${template_dir}//wrapfunctions.template.h + ${template_dir}//wrapfunctions.template.cpp + ${template_dir}//CMakeLists_model.cmake + ${template_dir}//modelname.template.i + COMMENT "Dummy target for SWIG files") + set_target_properties( + fileTemplates PROPERTIES INCLUDE_DIRECTORIES + "${CMAKE_CURRENT_SOURCE_DIR}/include/") +endif() if(NOT AMICI_PYTHON_BUILD_EXT_ONLY) include(clang-tools) diff --git a/doc/python_modules.rst b/doc/python_modules.rst index 6b490664a4..87a5f691c2 100644 --- a/doc/python_modules.rst +++ b/doc/python_modules.rst @@ -23,7 +23,7 @@ AMICI Python API amici.petab.simulator amici.import_utils amici.jax - amici.de_export + amici.exporters.sundials.de_export amici.de_model amici.de_model_components amici.plotting diff --git a/python/sdist/MANIFEST.in b/python/sdist/MANIFEST.in index 7cd9792a20..183e9cc69b 100644 --- a/python/sdist/MANIFEST.in +++ b/python/sdist/MANIFEST.in @@ -5,6 +5,7 @@ recursive-include amici/cmake * recursive-include amici/include/amici *.h recursive-include amici/src * recursive-include amici/swig * +recursive-include amici/exporters/sundials/templates * include amici/* include version.txt include LICENSE.md diff --git a/python/sdist/amici/__init__.py b/python/sdist/amici/__init__.py index 642ba14cf1..3e293c8806 100644 --- a/python/sdist/amici/__init__.py +++ b/python/sdist/amici/__init__.py @@ -178,7 +178,6 @@ def get_model_dir(model_id: str | None = None, jax: bool = False) -> Path: # These modules don't require the swig interface from typing import Protocol, runtime_checkable - from .de_export import DEExporter # noqa: F401 from .import_utils import MeasurementChannel # noqa: F401 from .sbml_import import ( # noqa: F401 SbmlImporter, diff --git a/python/sdist/amici/de_model.py b/python/sdist/amici/de_model.py index b69fb5a28d..2832814b48 100644 --- a/python/sdist/amici/de_model.py +++ b/python/sdist/amici/de_model.py @@ -15,13 +15,6 @@ import sympy as sp from sympy import ImmutableDenseMatrix, MutableDenseMatrix -from ._codegen.cxx_functions import ( - nobody_functions, - sensi_functions, - sparse_functions, - var_in_function_signature, -) -from .cxxcodeprinter import csc_matrix from .de_model_components import ( AlgebraicEquation, AlgebraicState, @@ -45,6 +38,13 @@ SigmaZ, State, ) +from .exporters.sundials.cxx_functions import ( + nobody_functions, + sensi_functions, + sparse_functions, + var_in_function_signature, +) +from .exporters.sundials.cxxcodeprinter import csc_matrix from .import_utils import ( ObservableTransformation, SBMLException, @@ -1135,18 +1135,14 @@ def _generate_symbol(self, name: str) -> None: components = sorted( components, key=lambda x: int( - x.get_id().replace( - "observableParameter", "" - ) + x.get_id().replace("observableParameter", "") ), ) if name == "np": components = sorted( components, key=lambda x: int( - x.get_id().replace( - "noiseParameter", "" - ) + x.get_id().replace("noiseParameter", "") ), ) self._syms[name] = sp.Matrix( @@ -1213,8 +1209,7 @@ def _generate_symbol(self, name: str) -> None: [ [ sp.Symbol( - f"s{tcl.get_id()}__" - f"{par.get_id()}", + f"s{tcl.get_id()}__{par.get_id()}", real=True, ) for par in self._parameters diff --git a/python/sdist/amici/_codegen/__init__.py b/python/sdist/amici/exporters/__init__.py similarity index 100% rename from python/sdist/amici/_codegen/__init__.py rename to python/sdist/amici/exporters/__init__.py diff --git a/python/sdist/amici/exporters/sundials/__init__.py b/python/sdist/amici/exporters/sundials/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python/sdist/amici/compile.py b/python/sdist/amici/exporters/sundials/compile.py similarity index 100% rename from python/sdist/amici/compile.py rename to python/sdist/amici/exporters/sundials/compile.py diff --git a/python/sdist/amici/_codegen/cxx_functions.py b/python/sdist/amici/exporters/sundials/cxx_functions.py similarity index 100% rename from python/sdist/amici/_codegen/cxx_functions.py rename to python/sdist/amici/exporters/sundials/cxx_functions.py diff --git a/python/sdist/amici/cxxcodeprinter.py b/python/sdist/amici/exporters/sundials/cxxcodeprinter.py similarity index 99% rename from python/sdist/amici/cxxcodeprinter.py rename to python/sdist/amici/exporters/sundials/cxxcodeprinter.py index d70ee8b364..3cc1751b4f 100644 --- a/python/sdist/amici/cxxcodeprinter.py +++ b/python/sdist/amici/exporters/sundials/cxxcodeprinter.py @@ -12,7 +12,7 @@ from sympy.utilities.iterables import numbered_symbols from toposort import toposort -from .import_utils import symbol_with_assumptions +from ...import_utils import symbol_with_assumptions class AmiciCxxCodePrinter(CXX11CodePrinter): diff --git a/python/sdist/amici/de_export.py b/python/sdist/amici/exporters/sundials/de_export.py similarity index 97% rename from python/sdist/amici/de_export.py rename to python/sdist/amici/exporters/sundials/de_export.py index 4cc90f2396..232fe7ad33 100644 --- a/python/sdist/amici/de_export.py +++ b/python/sdist/amici/exporters/sundials/de_export.py @@ -24,16 +24,23 @@ import sympy as sp -from . import ( +from ... import ( __commit__, __version__, - amiciModulePath, - amiciSrcPath, - amiciSwigPath, get_model_dir, splines, ) -from ._codegen.cxx_functions import ( +from ...de_model import DEModel +from ...de_model_components import * +from ...logging import get_logger, log_execution_time, set_log_level +from ...sympy_utils import ( + _custom_pow_eval_derivative, + _monkeypatched, + smart_is_zero_matrix, +) +from ..template import apply_template +from .compile import build_model_extension +from .cxx_functions import ( _FunctionInfo, event_functions, event_sensi_functions, @@ -44,38 +51,25 @@ sparse_functions, sparse_sensi_functions, ) -from ._codegen.model_class import ( - get_function_extern_declaration, - get_model_override_implementation, - get_sunindex_extern_declaration, - get_sunindex_override_implementation, -) -from ._codegen.template import apply_template -from .compile import build_model_extension from .cxxcodeprinter import ( AmiciCxxCodePrinter, get_initializer_list, get_switch_statement, ) -from .de_model import DEModel -from .de_model_components import * -from .logging import get_logger, log_execution_time, set_log_level -from .sympy_utils import ( - _custom_pow_eval_derivative, - _monkeypatched, - smart_is_zero_matrix, +from .model_class import ( + get_function_extern_declaration, + get_model_override_implementation, + get_sunindex_extern_declaration, + get_sunindex_override_implementation, ) +TEMPLATE_DIR = Path(__file__).parent / "templates" # Template for model simulation main.cpp file -CXX_MAIN_TEMPLATE_FILE = os.path.join(amiciSrcPath, "main.template.cpp") +CXX_MAIN_TEMPLATE_FILE = TEMPLATE_DIR / "main.template.cpp" # Template for model/swig/CMakeLists.txt -SWIG_CMAKE_TEMPLATE_FILE = os.path.join( - amiciSwigPath, "CMakeLists_model.cmake" -) +SWIG_CMAKE_TEMPLATE_FILE = TEMPLATE_DIR / "CMakeLists_model.cmake" # Template for model/CMakeLists.txt -MODEL_CMAKE_TEMPLATE_FILE = os.path.join( - amiciSrcPath, "CMakeLists.template.cmake" -) +MODEL_CMAKE_TEMPLATE_FILE = TEMPLATE_DIR / "CMakeLists.template.cmake" IDENTIFIER_PATTERN = re.compile(r"^[a-zA-Z_]\w*$") @@ -950,7 +944,7 @@ def _write_wrapfunctions_cpp(self) -> None: """ template_data = {"MODELNAME": self.model_name} apply_template( - os.path.join(amiciSrcPath, "wrapfunctions.template.cpp"), + TEMPLATE_DIR / "wrapfunctions.template.cpp", os.path.join(self.model_path, "wrapfunctions.cpp"), template_data, ) @@ -961,7 +955,7 @@ def _write_wrapfunctions_header(self) -> None: """ template_data = {"MODELNAME": str(self.model_name)} apply_template( - os.path.join(amiciSrcPath, "wrapfunctions.template.h"), + TEMPLATE_DIR / "wrapfunctions.template.h", os.path.join(self.model_path, "wrapfunctions.h"), template_data, ) @@ -1184,13 +1178,13 @@ def event_initializer_list() -> str: tpl_data = {k: str(v) for k, v in tpl_data.items()} apply_template( - os.path.join(amiciSrcPath, "model_header.template.h"), + TEMPLATE_DIR / "model_header.template.h", os.path.join(self.model_path, f"{self.model_name}.h"), tpl_data, ) apply_template( - os.path.join(amiciSrcPath, "model.template.cpp"), + TEMPLATE_DIR / "model.template.cpp", os.path.join(self.model_path, f"{self.model_name}.cpp"), tpl_data, ) @@ -1256,7 +1250,7 @@ def _write_swig_files(self) -> None: Path(self.model_swig_path).mkdir(exist_ok=True) template_data = {"MODELNAME": self.model_name} apply_template( - Path(amiciSwigPath, "modelname.template.i"), + TEMPLATE_DIR / "modelname.template.i", Path(self.model_swig_path, self.model_name + ".i"), template_data, ) @@ -1276,12 +1270,12 @@ def _write_module_setup(self) -> None: "PACKAGE_VERSION": "0.1.0", } apply_template( - Path(amiciModulePath, "setup.template.py"), + TEMPLATE_DIR / "setup.template.py", Path(self.model_path, "setup.py"), template_data, ) apply_template( - Path(amiciModulePath, "MANIFEST.template.in"), + TEMPLATE_DIR / "MANIFEST.template.in", Path(self.model_path, "MANIFEST.in"), {}, ) @@ -1289,7 +1283,7 @@ def _write_module_setup(self) -> None: Path(self.model_path, self.model_name).mkdir(exist_ok=True) apply_template( - Path(amiciModulePath, "__init__.template.py"), + TEMPLATE_DIR / "__init__.template.py", Path(self.model_path, self.model_name, "__init__.py"), template_data, ) diff --git a/python/sdist/amici/_codegen/model_class.py b/python/sdist/amici/exporters/sundials/model_class.py similarity index 100% rename from python/sdist/amici/_codegen/model_class.py rename to python/sdist/amici/exporters/sundials/model_class.py diff --git a/src/CMakeLists.template.cmake b/python/sdist/amici/exporters/sundials/templates/CMakeLists.template.cmake similarity index 100% rename from src/CMakeLists.template.cmake rename to python/sdist/amici/exporters/sundials/templates/CMakeLists.template.cmake diff --git a/swig/CMakeLists_model.cmake b/python/sdist/amici/exporters/sundials/templates/CMakeLists_model.cmake similarity index 100% rename from swig/CMakeLists_model.cmake rename to python/sdist/amici/exporters/sundials/templates/CMakeLists_model.cmake diff --git a/python/sdist/amici/MANIFEST.template.in b/python/sdist/amici/exporters/sundials/templates/MANIFEST.template.in similarity index 100% rename from python/sdist/amici/MANIFEST.template.in rename to python/sdist/amici/exporters/sundials/templates/MANIFEST.template.in diff --git a/python/sdist/amici/__init__.template.py b/python/sdist/amici/exporters/sundials/templates/__init__.template.py similarity index 100% rename from python/sdist/amici/__init__.template.py rename to python/sdist/amici/exporters/sundials/templates/__init__.template.py diff --git a/src/main.template.cpp b/python/sdist/amici/exporters/sundials/templates/main.template.cpp similarity index 100% rename from src/main.template.cpp rename to python/sdist/amici/exporters/sundials/templates/main.template.cpp diff --git a/src/model.template.cpp b/python/sdist/amici/exporters/sundials/templates/model.template.cpp similarity index 100% rename from src/model.template.cpp rename to python/sdist/amici/exporters/sundials/templates/model.template.cpp diff --git a/src/model_header.template.h b/python/sdist/amici/exporters/sundials/templates/model_header.template.h similarity index 100% rename from src/model_header.template.h rename to python/sdist/amici/exporters/sundials/templates/model_header.template.h diff --git a/swig/modelname.template.i b/python/sdist/amici/exporters/sundials/templates/modelname.template.i similarity index 100% rename from swig/modelname.template.i rename to python/sdist/amici/exporters/sundials/templates/modelname.template.i diff --git a/python/sdist/amici/setup.template.py b/python/sdist/amici/exporters/sundials/templates/setup.template.py similarity index 99% rename from python/sdist/amici/setup.template.py rename to python/sdist/amici/exporters/sundials/templates/setup.template.py index ac03fc9866..2439704e66 100644 --- a/python/sdist/amici/setup.template.py +++ b/python/sdist/amici/exporters/sundials/templates/setup.template.py @@ -5,11 +5,10 @@ import sys from pathlib import Path -from cmake_build_extension import CMakeExtension -from setuptools import find_namespace_packages, setup - from amici import _get_amici_path from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup def get_extension() -> CMakeExtension: diff --git a/src/wrapfunctions.template.cpp b/python/sdist/amici/exporters/sundials/templates/wrapfunctions.template.cpp similarity index 100% rename from src/wrapfunctions.template.cpp rename to python/sdist/amici/exporters/sundials/templates/wrapfunctions.template.cpp diff --git a/src/wrapfunctions.template.h b/python/sdist/amici/exporters/sundials/templates/wrapfunctions.template.h similarity index 100% rename from src/wrapfunctions.template.h rename to python/sdist/amici/exporters/sundials/templates/wrapfunctions.template.h diff --git a/python/sdist/amici/_codegen/template.py b/python/sdist/amici/exporters/template.py similarity index 100% rename from python/sdist/amici/_codegen/template.py rename to python/sdist/amici/exporters/template.py diff --git a/python/sdist/amici/jax/nn.py b/python/sdist/amici/jax/nn.py index 0bd16b4655..28bda1249a 100644 --- a/python/sdist/amici/jax/nn.py +++ b/python/sdist/amici/jax/nn.py @@ -4,7 +4,8 @@ import jax.numpy as jnp from amici import amiciModulePath -from amici._codegen.template import apply_template + +from ..exporters.template import apply_template class Flatten(eqx.Module): diff --git a/python/sdist/amici/jax/ode_export.py b/python/sdist/amici/jax/ode_export.py index f1533a0aab..5c27cc22a0 100644 --- a/python/sdist/amici/jax/ode_export.py +++ b/python/sdist/amici/jax/ode_export.py @@ -21,9 +21,9 @@ from amici import ( amiciModulePath, ) -from amici._codegen.template import apply_template -from amici.de_export import is_valid_identifier from amici.de_model import DEModel +from amici.exporters.sundials.de_export import is_valid_identifier +from amici.exporters.template import apply_template from amici.jax.jaxcodeprinter import AmiciJaxCodePrinter, _jnp_array_str from amici.jax.model import JAXModel from amici.jax.nn import generate_equinox diff --git a/python/sdist/amici/pysb_import.py b/python/sdist/amici/pysb_import.py index 8ba6926663..e29ee986e9 100644 --- a/python/sdist/amici/pysb_import.py +++ b/python/sdist/amici/pysb_import.py @@ -24,18 +24,19 @@ import amici -from .de_export import ( +from .de_model import DEModel +from .de_model_components import ( Constant, - DEExporter, DifferentialState, + Event, Expression, LogLikelihoodY, + NoiseParameter, Observable, + ObservableParameter, Parameter, SigmaY, ) -from .de_model import DEModel -from .de_model_components import Event, NoiseParameter, ObservableParameter from .import_utils import ( MeasurementChannel, _default_simplify, @@ -265,6 +266,11 @@ def pysb2amici( pysb_model_has_obs_and_noise=pysb_model_has_obs_and_noise, events=_events, ) + + from .exporters.sundials.de_export import ( + DEExporter, + ) + exporter = DEExporter( ode_model, outdir=output_dir, diff --git a/python/sdist/amici/sbml_import.py b/python/sdist/amici/sbml_import.py index 9549827ef3..675245f75b 100644 --- a/python/sdist/amici/sbml_import.py +++ b/python/sdist/amici/sbml_import.py @@ -30,9 +30,6 @@ from . import get_model_dir, has_clibs from .constants import SymbolId -from .de_export import ( - DEExporter, -) from .de_model import DEModel from .de_model_components import Expression, symbol_to_type from .import_utils import ( @@ -401,6 +398,10 @@ def sbml2amici( output_dir = output_dir or get_model_dir(model_name) + from .exporters.sundials.de_export import ( + DEExporter, + ) + exporter = DEExporter( ode_model, model_name=model_name, diff --git a/python/tests/test_cxxcodeprinter.py b/python/tests/test_cxxcodeprinter.py index 8164bbb664..dfd5cfea1b 100644 --- a/python/tests/test_cxxcodeprinter.py +++ b/python/tests/test_cxxcodeprinter.py @@ -1,6 +1,6 @@ import pytest import sympy as sp -from amici.cxxcodeprinter import AmiciCxxCodePrinter +from amici.exporters.sundials.cxxcodeprinter import AmiciCxxCodePrinter from amici.testing import skip_on_valgrind from sympy.codegen.rewriting import optims_c99 diff --git a/python/tests/test_ode_export.py b/python/tests/test_ode_export.py index ce510741f8..86e064e9c4 100644 --- a/python/tests/test_ode_export.py +++ b/python/tests/test_ode_export.py @@ -1,7 +1,7 @@ """Miscellaneous AMICI Python interface tests""" import sympy as sp -from amici.cxxcodeprinter import csc_matrix +from amici.exporters.sundials.cxxcodeprinter import csc_matrix from amici.import_utils import symbol_with_assumptions from amici.testing import skip_on_valgrind diff --git a/tests/performance/test.py b/tests/performance/test.py index 6b0971aeb4..56a348c973 100755 --- a/tests/performance/test.py +++ b/tests/performance/test.py @@ -72,7 +72,7 @@ def run_import(model_name, model_dir: Path): git_dir / "FroehlichKes2018" / "PEtab" / "FroehlichKes2018.yaml" ) petab.lint_problem(pp) - amici.de_export.logger.setLevel(logging.DEBUG) + amici.exporters.sundials.de_export.logger.setLevel(logging.DEBUG) amici.sbml_import.logger.setLevel(logging.DEBUG) import_model_sbml( model_name=model_name,