diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..f6135accef --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,26 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: new +assignees: '' + +--- + +**What did you expect to happen?** + +**What has happened instead?** + +**To Reproduce** +*Steps to reproduce the behavior* +*Ideally include minimal code examples here* + +**AMICI version and system environment** + - OS and version: [e.g. Ubuntu, iOS, Windows] + - AMICI interface: [e.g. Python, Matlab, C++] + - AMICI version: + - Additional information: Compiler name and version used, Python/Matlab version, ... + +**How to fix** +Do you know how to resolve the problem? +Can you submit a pull request? diff --git a/.travis.yml b/.travis.yml index 47d606f386..648ce0e026 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ sudo: required branches: only: - master - - staging + - develop matrix: fast_finish: true diff --git a/CMakeLists.txt b/CMakeLists.txt index f7bc6261cd..45ff191ad1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,9 +172,9 @@ endif() # build interfaces for other languages option(ENABLE_SWIG "Build AMICI swig library?" ON) -#if(ENABLE_SWIG) -# add_subdirectory(swig) -#endif() +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() option(ENABLE_PYTHON "Create Python module?" ON) if(ENABLE_PYTHON) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ff74eb4a1..0f619ed794 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,17 +7,18 @@ We are happy about contributions to AMICI in any form (new functionality, docume When making code changes: * Check if you agree to release your contribution under the conditions provided in `LICENSE` -* Start a new branch from `master` +* Start a new branch from `develop` * Implement your changes -* Submit a pull request +* Submit a pull request to the `develop` branch * Make sure your code is documented appropriately * Run `mtoc/makeDocumentation.m` to check completeness of your documentation * Make sure your code is compatible with C++11, `gcc` and `clang` * when adding new functionality, please also provide test cases (see `tests/cpputest/`) * Write meaningful commit messages -* Run all tests to ensure nothing got broken +* Run all tests to ensure nothing was broken * Run `tests/cpputest/wrapTestModels.m` followed by CI tests `scripts/buildAll.sh && scripts/run-cpputest.sh` * Run `tests/testModels.m` + * Run `make python-tests` in `build` * When all tests are passing and you think your code is ready to merge, request a code review ## Adding/Updating tests diff --git a/matlab/@amimodel/compileAndLinkModel.m b/matlab/@amimodel/compileAndLinkModel.m index 4a345ee655..553b645918 100644 --- a/matlab/@amimodel/compileAndLinkModel.m +++ b/matlab/@amimodel/compileAndLinkModel.m @@ -331,7 +331,7 @@ function updateFileHash(fileFolder,hashFolder,filename) function versionstring = getCompilerVersionString() [~,systemreturn] = system([mex.getCompilerConfigurations('c++').Details.CompilerExecutable ' --version']); - newlinePos = strfind(systemreturn,newline); + newlinePos = strfind(systemreturn, sprintf('\n')); str = systemreturn(1:(newlinePos(1)-1)); str = regexprep(str,'[\(\)]',''); str = regexprep(str,'[\s\.\-]','_'); diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 7a7ed6f414..8d7767249f 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,41 +1,9 @@ find_package(PythonInterp 3.6 REQUIRED) -# Configure setup.py and copy to output directory -set(AMICI_VERSION "@AMICI_VERSION@") # to be replaced later -configure_file(${PROJECT_SOURCE_DIR}/python/amici/setup.template.py ${CMAKE_CURRENT_BINARY_DIR}/setup.template.py) - -# Copy further amici-python-module files to binary_dir -add_custom_target(python-module-files - DEPENDS always_rebuild - COMMENT "Preparing python module directory" - COMMAND ${CMAKE_COMMAND} -D SRC=${CMAKE_CURRENT_BINARY_DIR}/setup.py - -D DST=${CMAKE_CURRENT_BINARY_DIR}/setup.py - -P ${PROJECT_SOURCE_DIR}/cmake/configureVersion.cmake - COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/amici - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/amici - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/python/amici ${CMAKE_CURRENT_BINARY_DIR}/amici - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/amici/src - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/amici/include - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/swig ${CMAKE_CURRENT_BINARY_DIR}/amici/swig - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/ThirdParty ${CMAKE_CURRENT_BINARY_DIR}/amici/ThirdParty - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/setup.template.py ${CMAKE_CURRENT_BINARY_DIR}/amici/setup.template.py - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/README.md ${CMAKE_CURRENT_BINARY_DIR}/ - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/libamici.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/ThirdParty/sundials/build/lib/libsundials_nvecserial.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/ThirdParty/sundials/build/lib/libsundials_cvodes.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/ThirdParty/sundials/build/lib/libsundials_idas.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/ThirdParty/SuiteSparse/KLU/Lib/libklu.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/ThirdParty/SuiteSparse/COLAMD/Lib/libcolamd.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/ThirdParty/SuiteSparse/BTF/Lib/libbtf.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/ThirdParty/SuiteSparse/AMD/Lib/libamd.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/ThirdParty/SuiteSparse/SuiteSparse_config/libsuitesparseconfig.a" ${CMAKE_CURRENT_BINARY_DIR}/amici/libs/ - ) - add_custom_target(install-python COMMENT "Installing AMICI base python package" - DEPENDS python-module-files - COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY_OUT} install --prefix= --user) + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/sdist + COMMAND ${PYTHON_EXECUTABLE} setup.py install --prefix= --user) # Create python wheel @@ -44,19 +12,20 @@ add_custom_target(install-python # build_py stage add_custom_target(python-wheel COMMENT "Creating wheel for AMICI base python package" - DEPENDS python-module-files + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/sdist COMMAND ${PYTHON_EXECUTABLE} setup.py build_ext COMMAND ${PYTHON_EXECUTABLE} setup.py bdist_wheel --dist-dir=${CMAKE_CURRENT_BINARY_DIR} ) + add_custom_target(python-sdist COMMENT "Creating sdist for AMICI base python package" - COMMAND ${PYTHON_EXECUTABLE} setup.py sdist --dist-dir=${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/sdist + COMMAND ${PYTHON_EXECUTABLE} setup.py sdist --dist-dir=${CMAKE_CURRENT_BINARY_DIR} ) + add_custom_command( OUTPUT always_rebuild COMMAND cmake -E echo ) - diff --git a/python/amici/ode_export.py b/python/amici/ode_export.py index a5c71e6e6d..3e4df4cd47 100644 --- a/python/amici/ode_export.py +++ b/python/amici/ode_export.py @@ -1109,7 +1109,7 @@ def _computeEquation(self, name): dx0_fixedParametersdx = \ self.eq('x0_fixedParameters').jacobian(self.sym('x')) - if not dx0_fixedParametersdx.is_zero: + if dx0_fixedParametersdx.is_zero is not True: for ip in range(self._eqs[name].shape[1]): self._eqs[name][:,ip] += \ dx0_fixedParametersdx \ @@ -1206,8 +1206,11 @@ def _derivative(self, eq, var, name=None): else: eq = self.eq(eq) - if min(eq.shape) and min(self.sym(var).shape): - self._eqs[name] = eq.jacobian(self.sym(var)) + sym_var = self.sym(var) + + if min(eq.shape) and min(sym_var.shape) \ + and eq.is_zero is not True and sym_var.is_zero is not True: + self._eqs[name] = eq.jacobian(sym_var) else: self._eqs[name] = sp.zeros(eq.shape[0], self.sym(var).shape[0]) @@ -1264,10 +1267,14 @@ def _totalDerivative(self, name, eq, chainvar, var, variables[var]['sym'] = self.eq(varname) self._eqs[name] = \ - variables['dydz']['sym'] \ - + variables['dydx']['sym'] * variables['dxdz']['sym'] - + copy.deepcopy(variables['dydz']['sym']) + # Save time for for large models if one multiplicand is zero, + # which is not checked for by sympy + if variables['dydx']['sym'].is_zero is not True \ + and variables['dxdz']['sym'].is_zero is not True: + self._eqs[name] += variables['dydx']['sym'] * \ + variables['dxdz']['sym'] def _multiplication(self, name, x, y, @@ -1617,6 +1624,10 @@ def _writeFunctionFile(self, function): if 'sparse' in self.functions[function] and \ self.functions[function]['sparse']: symbol = self.model.sparseeq(function) + elif not self.allow_reinit_fixpar_initcond \ + and function == 'sx0_fixedParameters': + # Not required. Will create empty function body. + symbol = sp.Matrix() else: symbol = self.model.eq(function) diff --git a/python/amici/sbml_import.py b/python/amici/sbml_import.py index 124dff7ec1..31d2d2905b 100644 --- a/python/amici/sbml_import.py +++ b/python/amici/sbml_import.py @@ -1,6 +1,6 @@ +#!/usr/bin/env python3 """ @package amici.sbml_import The python sbml import module for python """ -#!/usr/bin/env python3 import sympy as sp import libsbml as sbml @@ -31,15 +31,15 @@ class SbmlImporter: Attributes: - check_validity: indicates whether the validity of the SBML document - should be checked @type bool + show_sbml_warnings: indicates whether libSBML warnings should be + displayed @type bool symbols: dict carrying symbolic definitions @type dict SBMLreader: the libSBML sbml reader [!not storing this will result in a segfault!] - sbml_doc: document carrying the sbml defintion [!not storing this + sbml_doc: document carrying the sbml definition [!not storing this will result in a segfault!] sbml: sbml definition [!not storing this will result in a segfault!] @@ -62,25 +62,25 @@ class SbmlImporter: compartmentSymbols: compartment ids @type sympy.Matrix - compartmentVolume: numeric/symbnolic compartment volumes @type + compartmentVolume: numeric/symbolic compartment volumes @type sympy.Matrix - stoichiometricMatrix: stoichiometrix matrix of the model @type + stoichiometricMatrix: stoichiometric matrix of the model @type sympy.Matrix fluxVector: reaction kinetic laws @type sympy.Matrix """ - def __init__(self, SBMLFile, check_validity=True): + def __init__(self, SBMLFile, show_sbml_warnings=False): """Create a new Model instance. Arguments: SBMLFile: Path to SBML file where the model is specified @type string - check_validity: Flag indicating whether the validity of the SBML - document should be checked @type bool + show_sbml_warnings: indicates whether libSBML warnings should be + displayed @type bool Returns: SbmlImporter instance with attached SBML document @@ -89,7 +89,7 @@ def __init__(self, SBMLFile, check_validity=True): """ - self.check_validity = check_validity + self.show_sbml_warnings = show_sbml_warnings self.loadSBMLFile(SBMLFile) @@ -123,10 +123,11 @@ def loadSBMLFile(self, SBMLFile): self.SBMLreader = sbml.SBMLReader() self.sbml_doc = self.SBMLreader.readSBML(SBMLFile) - self.checkLibSBMLErrors() - # If any of the above calls produces an error, this will be added to - # the SBMLError log in the sbml document. Thus, it is sufficient to - # check the error log just once after all conversion/validation calls. + + # Ensure we got a valid SBML model, otherwise further processing + # might lead to undefined results + self.sbml_doc.validateSBML() + checkLibSBMLErrors(self.sbml_doc, self.show_sbml_warnings) # apply several model simplifications that make our life substantially # easier @@ -139,45 +140,13 @@ def loadSBMLFile(self, SBMLFile): getDefaultProperties() self.sbml_doc.convert(convertConfig) - if self.check_validity: - self.sbml_doc.validateSBML() - # If any of the above calls produces an error, this will be added to # the SBMLError log in the sbml document. Thus, it is sufficient to # check the error log just once after all conversion/validation calls. - self.checkLibSBMLErrors() + checkLibSBMLErrors(self.sbml_doc, self.show_sbml_warnings) self.sbml = self.sbml_doc.getModel() - def checkLibSBMLErrors(self): - """Checks the error log in the current self.sbml_doc - - Arguments: - - Returns: - - Raises: - raises SBMLException if errors with severity ERROR or FATAL have - occured - - """ - num_warning = self.sbml_doc.getNumErrors(sbml.LIBSBML_SEV_WARNING) - num_error = self.sbml_doc.getNumErrors(sbml.LIBSBML_SEV_ERROR) - num_fatal = self.sbml_doc.getNumErrors(sbml.LIBSBML_SEV_FATAL) - if num_warning + num_error + num_fatal: - for iError in range(0, self.sbml_doc.getNumErrors()): - error = self.sbml_doc.getError(iError) - # we ignore any info messages for now - if error.getSeverity() >= sbml.LIBSBML_SEV_WARNING: - category = error.getCategoryAsString() - severity = error.getSeverityAsString() - error_message = error.getMessage() - print(f'libSBML {severity} ({category}): {error_message}') - if num_error + num_fatal: - raise SBMLException( - 'SBML Document failed to load (see error messages above)' - ) - def sbml2amici(self, modelName, output_dir=None, @@ -766,11 +735,13 @@ def processObservables(self, observables, sigmas): if sigmas is None: sigmas = {} - elif len(set(sigmas.keys()) - set(observables.keys())): - # Ensure no non-existing observableIds have been specified (no problem here, but usually an upstream bug) - raise ValueError(f'Sigma provided for an unknown observableId: {set(sigmas.keys()) - set(observables.keys())}') - - + else: + # Ensure no non-existing observableIds have been specified + # (no problem here, but usually an upstream bug) + unknown_observables = set(sigmas.keys()) - set(observables.keys()) + if unknown_observables: + raise ValueError('Sigma provided for an unknown observableId: ' + + str(unknown_observables)) speciesSyms = self.symbols['species']['identifier'] @@ -1101,3 +1072,38 @@ def l2s(inputs): """ return [str(inp) for inp in inputs] + + +def checkLibSBMLErrors(sbml_doc, show_warnings=False): + """Checks the error log in the current self.sbml_doc + + Arguments: + sbml_doc: SBML document @type libsbml.SBMLDocument + show_warnings: display SBML warnings @type bool + + Returns: + + Raises: + raises SBMLException if errors with severity ERROR or FATAL have + occurred + """ + num_warning = sbml_doc.getNumErrors(sbml.LIBSBML_SEV_WARNING) + num_error = sbml_doc.getNumErrors(sbml.LIBSBML_SEV_ERROR) + num_fatal = sbml_doc.getNumErrors(sbml.LIBSBML_SEV_FATAL) + + if num_warning + num_error + num_fatal: + for iError in range(0, sbml_doc.getNumErrors()): + error = sbml_doc.getError(iError) + # we ignore any info messages for now + if error.getSeverity() >= sbml.LIBSBML_SEV_ERROR \ + or (show_warnings and + error.getSeverity() >= sbml.LIBSBML_SEV_WARNING): + category = error.getCategoryAsString() + severity = error.getSeverityAsString() + error_message = error.getMessage() + print(f'libSBML {severity} ({category}): {error_message}') + + if num_error + num_fatal: + raise SBMLException( + 'SBML Document failed to load (see error messages above)' + ) diff --git a/python/examples/example_presimulation/model_presimulation.ipynb b/python/examples/example_presimulation/model_presimulation.ipynb index 261695c249..7d1f740317 100644 --- a/python/examples/example_presimulation/model_presimulation.ipynb +++ b/python/examples/example_presimulation/model_presimulation.ipynb @@ -93,178 +93,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to time, the units of time should be consistent with the global time units of the model. In models where the 'timeUnits' attribute has not been declared, libSBML does not yet have the functionality to verify accurately the consistency of the units in such expressions. \n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to extent, the units of extent should be consistent with the global extent units of the model. In models where the 'extentUnits' attribute has not been declared, libSBML does not yet have the functionality to verify accurately the consistency of the units in such expressions. \n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'default' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a Compartment object having a 'spatialDimensions' attribute value of '3' has not been set, then the unit of measurement associated with the compartment's size is determined by the value of the enclosing Model object's 'volumeUnits' attribute. If neither the Compartment object's 'units' nor the enclosing Model object's 'volumeUnits' attributes are set, the unit of compartment size is undefined.\n", - "Reference: L3V2 Section 4.5.4\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the '__s0' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'substanceUnits' in a Species object has not been set, then the unit of measurement associated with the species' quantity is determined by the value of the enclosing Model object's 'substanceUnits' attribute. If neither the Species object's 'substanceUnits' attribute nor the enclosing Model object's 'substanceUnits' attribute are set, then the unit of that species' quantity is undefined.\n", - "Reference: L3V2 Section 4.6.5\n", - " The with id '__s0' does not have a substanceUnits attribute, nor does its enclosing .\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the '__s1' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'substanceUnits' in a Species object has not been set, then the unit of measurement associated with the species' quantity is determined by the value of the enclosing Model object's 'substanceUnits' attribute. If neither the Species object's 'substanceUnits' attribute nor the enclosing Model object's 'substanceUnits' attribute are set, then the unit of that species' quantity is undefined.\n", - "Reference: L3V2 Section 4.6.5\n", - " The with id '__s1' does not have a substanceUnits attribute, nor does its enclosing .\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the '__s2' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'substanceUnits' in a Species object has not been set, then the unit of measurement associated with the species' quantity is determined by the value of the enclosing Model object's 'substanceUnits' attribute. If neither the Species object's 'substanceUnits' attribute nor the enclosing Model object's 'substanceUnits' attribute are set, then the unit of that species' quantity is undefined.\n", - "Reference: L3V2 Section 4.6.5\n", - " The with id '__s2' does not have a substanceUnits attribute, nor does its enclosing .\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the '__s3' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'substanceUnits' in a Species object has not been set, then the unit of measurement associated with the species' quantity is determined by the value of the enclosing Model object's 'substanceUnits' attribute. If neither the Species object's 'substanceUnits' attribute nor the enclosing Model object's 'substanceUnits' attribute are set, then the unit of that species' quantity is undefined.\n", - "Reference: L3V2 Section 4.6.5\n", - " The with id '__s3' does not have a substanceUnits attribute, nor does its enclosing .\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the '__s4' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'substanceUnits' in a Species object has not been set, then the unit of measurement associated with the species' quantity is determined by the value of the enclosing Model object's 'substanceUnits' attribute. If neither the Species object's 'substanceUnits' attribute nor the enclosing Model object's 'substanceUnits' attribute are set, then the unit of that species' quantity is undefined.\n", - "Reference: L3V2 Section 4.6.5\n", - " The with id '__s4' does not have a substanceUnits attribute, nor does its enclosing .\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the '__s5' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'substanceUnits' in a Species object has not been set, then the unit of measurement associated with the species' quantity is determined by the value of the enclosing Model object's 'substanceUnits' attribute. If neither the Species object's 'substanceUnits' attribute nor the enclosing Model object's 'substanceUnits' attribute are set, then the unit of that species' quantity is undefined.\n", - "Reference: L3V2 Section 4.6.5\n", - " The with id '__s5' does not have a substanceUnits attribute, nor does its enclosing .\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'PROT_0' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id 'PROT_0' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'DRUG_0' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id 'DRUG_0' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'kon_prot_drug' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id 'kon_prot_drug' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'koff_prot_drug' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id 'koff_prot_drug' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'KIN_0' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id 'KIN_0' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'kon_prot_kin' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id 'kon_prot_kin' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'kphospho_prot_kin' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id 'kphospho_prot_kin' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the 'kdephospho_prot' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id 'kdephospho_prot' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression refers to a compartment, species or parameter, it is necessary to know the units of the object to establish unit consistency. In models where the units of an object have not been declared, libSBML does not yet have the functionality to accurately verify the consistency of the units in mathematical expressions referring to that object. \n", - " The units of the '__obs0' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): If the attribute 'units' on a given Parameter object has not been set, then the unit of measurement associated with that parameter's value is undefined.\n", - "Reference: L3V2 Section 4.7.3\n", - " The with id '__obs0' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression contains literal numbers or parameters whose units have not been declared, it is not possible to verify accurately the consistency of the units in the expression. \n", - " The units of the expression 'initProt(PROT_0)' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression contains literal numbers or parameters whose units have not been declared, it is not possible to verify accurately the consistency of the units in the expression. \n", - " The units of the expression 'initDrug(DRUG_0)' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression contains literal numbers or parameters whose units have not been declared, it is not possible to verify accurately the consistency of the units in the expression. \n", - " The units of the expression 'initKin(KIN_0)' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression contains literal numbers or parameters whose units have not been declared, it is not possible to verify accurately the consistency of the units in the expression. \n", - " The units of the expression '__s5 / (__s0 + __s3 + __s4 + __s5)' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression contains literal numbers or parameters whose units have not been declared, it is not possible to verify accurately the consistency of the units in the expression. \n", - " The units of the expression '__s0 * __s1 * kon_prot_drug - __s3 * koff_prot_drug' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression contains literal numbers or parameters whose units have not been declared, it is not possible to verify accurately the consistency of the units in the expression. \n", - " The units of the expression '__s0 * __s2 * kon_prot_kin' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression contains literal numbers or parameters whose units have not been declared, it is not possible to verify accurately the consistency of the units in the expression. \n", - " The units of the expression '__s4 * kphospho_prot_kin' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (SBML unit consistency): In situations where a mathematical expression contains literal numbers or parameters whose units have not been declared, it is not possible to verify accurately the consistency of the units in the expression. \n", - " The units of the expression '__s5 * kdephospho_prot' cannot be fully checked. Unit consistency reported as either no errors or further unit errors related to this object may not be accurate.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id 'PROT_0' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id 'DRUG_0' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id 'kon_prot_drug' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id 'koff_prot_drug' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id 'KIN_0' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id 'kon_prot_kin' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id 'kphospho_prot_kin' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id 'kdephospho_prot' does not have a 'units' attribute.\n", - "\n", - "libSBML Warning (Modeling practice): As a principle of best modeling practice, the units of a should be declared rather than be left undefined. Doing so improves the ability of software to check the consistency of units and helps make it easier to detect potential errors in models.\n", - " The with the id '__obs0' does not have a 'units' attribute.\n", "\n" ] } ], "source": [ "# Create an SbmlImporter instance for our SBML model\n", - "sbml_importer = amici.SbmlImporter(sbml_file,check_validity=False)" + "sbml_importer = amici.SbmlImporter(sbml_file)" ] }, { diff --git a/python/sdist/setup.py b/python/sdist/setup.py index 5623e7e7c8..3151b7fe3a 100644 --- a/python/sdist/setup.py +++ b/python/sdist/setup.py @@ -37,6 +37,10 @@ generateSwigInterfaceFiles, ) +# Python version check. We need >= 3.6 due to e.g. f-strings +if sys.version_info < (3, 6): + sys.exit('amici requires at least Python version 3.6') + # Extra compiler flags cxx_flags = [] amici_module_linker_flags = [] @@ -268,8 +272,8 @@ def main(): ], packages=find_packages(), package_dir={'amici': 'amici'}, - install_requires=['sympy', 'python-libsbml', 'h5py', 'pandas'], - python_requires='>=3', + install_requires=['sympy', 'python-libsbml', 'h5py', 'pandas', 'setuptools>=40.6.3'], + python_requires='>=3.6', package_data={ 'amici': ['amici/include/amici/*', 'src/*template*', diff --git a/python/sdist/version.txt b/python/sdist/version.txt new file mode 120000 index 0000000000..7fa4c866fa --- /dev/null +++ b/python/sdist/version.txt @@ -0,0 +1 @@ +../../version.txt \ No newline at end of file diff --git a/scripts/run-doxygen.sh b/scripts/run-doxygen.sh index b1bc213d28..1c9d579c90 100755 --- a/scripts/run-doxygen.sh +++ b/scripts/run-doxygen.sh @@ -71,6 +71,10 @@ cp ./refman.pdf ${AMICI_PATH}/AMICI_guide.pdf grep -v "warning: Unexpected html tag found within context" ${DOXY_WARNING_FILE} > ${DOXY_WARNING_FILE}_tmp mv ${DOXY_WARNING_FILE}_tmp ${DOXY_WARNING_FILE} +# suppress doxygen warnings about multiple param sections +grep -v "iple @param documentation sections" ${DOXY_WARNING_FILE} > ${DOXY_WARNING_FILE}_tmp +mv ${DOXY_WARNING_FILE}_tmp ${DOXY_WARNING_FILE} + # check if warnings log was created if [ -f ${DOXY_WARNING_FILE} ]; then # check if warnings log is empty diff --git a/src/model.cpp b/src/model.cpp index 0b639f6f3f..966062180f 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -301,6 +301,8 @@ void Model::setParameterScale(ParameterScaling pscale) { } void Model::setParameterScale(std::vector const& pscale) { + if(pscale.size() != this->originalParameters.size()) + throw AmiException("Dimension mismatch. Size of parameter scaling does not match number of model parameters."); this->pscale = pscale; scaleParameters(unscaledParameters, this->pscale, originalParameters); } diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt index 2f933e56e5..52ddd90994 100644 --- a/swig/CMakeLists.txt +++ b/swig/CMakeLists.txt @@ -21,13 +21,3 @@ set(AMICI_INTERFACE_LIST # Add target to show files in IDE add_custom_target(swigInterface SOURCES ${AMICI_INTERFACE_LIST}) - -## Add subdirectories for each language if desired -if(ENABLE_PYTHON) - if(NOT(${CMAKE_VERSION} VERSION_LESS 3.8)) - add_subdirectory(python) - else() - message(WARNING "Unable to build SWIG interface, upgrade CMake to >=3.8.") - endif() -endif() - diff --git a/swig/amici.i b/swig/amici.i index 1bdbaa5242..66591b76b7 100644 --- a/swig/amici.i +++ b/swig/amici.i @@ -93,10 +93,30 @@ using namespace amici; %include "amici/amici.h" // Expose vectors -%template(ScalingVector) std::vector; %template(ExpDataPtrVector) std::vector; +// Convert integer values to enum class +// defeats the purpose of enum class, but didn't find a better way to allow for +// vectors of enum class types in python +%{ +namespace amici { +std::vector parameterScalingFromIntVector(std::vector const& intVec) { + std::vector result(intVec.size()); + for (int i = 0; i < (int) result.size(); ++i) { + result[i] = static_cast(intVec[i]); + } + return result; +} +}; // namespace amici +%} +namespace amici { + std::vector parameterScalingFromIntVector(std::vector const& intVec); +} +%template(ParameterScalingVector) std::vector; + + +// Add function to check if amici was compiled with OpenMP %{ namespace amici { /** AMICI extension was compiled with OpenMP? */ diff --git a/swig/python/CMakeLists.txt b/swig/python/CMakeLists.txt deleted file mode 100644 index 97e74f9fec..0000000000 --- a/swig/python/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -# -# Build AMICI python interface -# - -cmake_minimum_required(VERSION 3.8) # swig_add_library - -# Find Python interpreter, libs and headers -find_package(PythonInterp 3.6 REQUIRED)# TODO to setup.py -find_package(PythonLibs 3.6 REQUIRED) -include_directories( - ${PYTHON_INCLUDE_PATH} - ${CMAKE_SOURCE_DIR}/include - ${SUITESPARSE_INCLUDE_DIRS} - ${SUNDIALS_INCLUDE_DIRS} - ${HDF5_INCLUDE_DIRS} - ) - -set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/amici) -#set(CMAKE_SWIG_FLAGS "") - -set_source_files_properties( - ${AMICI_SRC_LIST} ${CMAKE_SOURCE_DIR}/swig/amici.i - PROPERTIES CPLUSPLUS ON - ) - -SWIG_ADD_LIBRARY( - amici - LANGUAGE python - SOURCES ${CMAKE_SOURCE_DIR}/swig/amici.i - ) - -#SWIG_LINK_LIBRARIES(amici -# ${PYTHON_LIBRARIES} -# ${AMICI_DIR}/build/libamici${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${SUNDIALS_LIB_DIR}/libsundials_nvecserial${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${SUNDIALS_LIB_DIR}/libsundials_cvodes${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${SUNDIALS_LIB_DIR}/libsundials_idas${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${SUITESPARSE_DIR}/KLU/Lib/libklu${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${SUITESPARSE_DIR}/COLAMD/Lib/libcolamd${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${SUITESPARSE_DIR}/BTF/Lib/libbtf${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${SUITESPARSE_DIR}/AMD/Lib/libamd${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${SUITESPARSE_DIR}/SuiteSparse_config/libsuitesparseconfig${CMAKE_STATIC_LIBRARY_SUFFIX} -# ${HDF5_HL_LIBRARIES} -# ${HDF5_C_LIBRARIES} -# ${HDF5_CXX_LIBRARIES} -# ${BLAS_LIBRARIES} -# -ldl -lz -lm) - -# put library into python package -# (SWIG_ADD_LIBRARY directory options don't work in current cmake version) -set_target_properties(_amici - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/amici" - ) - -#SET(PYTHON_INSTALL_FILES -# ${CMAKE_CURRENT_BINARY_DIR}/amici.py -# $) diff --git a/tests/SBMLTest.m b/tests/SBMLTest.m index 73c7fb2323..a3e3c1f783 100644 --- a/tests/SBMLTest.m +++ b/tests/SBMLTest.m @@ -1,3 +1,5 @@ +% Run SBML tests from sbml-semantic-test-cases + function runSBMLTests exedir = fileparts(mfilename('fullpath')); cd(exedir); @@ -9,7 +11,7 @@ if(~exist(fullfile(pwd,'SBMLresults',[testid '-results.csv']))) try runSBMLTest(iTest,fid); - catch error + catch error fprintf(fid,['Test ' testid ' failed: ' error.message '\n']);; end end @@ -104,4 +106,4 @@ function runSBMLTest(iTest,fid) end fclose(fid); -end \ No newline at end of file +end diff --git a/tests/cpputest/unittests/tests1.cpp b/tests/cpputest/unittests/tests1.cpp index e178c47c25..4654d20ce0 100644 --- a/tests/cpputest/unittests/tests1.cpp +++ b/tests/cpputest/unittests/tests1.cpp @@ -84,6 +84,16 @@ TEST(model, testScalingLog10) { DOUBLES_EQUAL(std::log10(p[0]), model.getParameters()[0], 1e-16); } +TEST(model, testParameterScalingLengthMismatch) { + // too short + auto pscale = std::vector(p.size() - 1, ParameterScaling::log10); + CHECK_THROWS(AmiException, model.setParameterScale(pscale)); + + // too long + pscale = std::vector(p.size() + 1, ParameterScaling::log10); + CHECK_THROWS(AmiException, model.setParameterScale(pscale)); +} + TEST(model, testSetTimepoints) { CHECK_THROWS(AmiException,model.setTimepoints(std::vector{0.0,1.0,0.5})) } diff --git a/tests/example.py b/tests/generateTestConfig/example.py similarity index 100% rename from tests/example.py rename to tests/generateTestConfig/example.py diff --git a/tests/example_dirac.py b/tests/generateTestConfig/example_dirac.py similarity index 100% rename from tests/example_dirac.py rename to tests/generateTestConfig/example_dirac.py diff --git a/tests/example_events.py b/tests/generateTestConfig/example_events.py similarity index 100% rename from tests/example_events.py rename to tests/generateTestConfig/example_events.py diff --git a/tests/example_jakstat.py b/tests/generateTestConfig/example_jakstat.py similarity index 100% rename from tests/example_jakstat.py rename to tests/generateTestConfig/example_jakstat.py diff --git a/tests/example_nested_events.py b/tests/generateTestConfig/example_nested_events.py similarity index 100% rename from tests/example_nested_events.py rename to tests/generateTestConfig/example_nested_events.py diff --git a/tests/example_neuron.py b/tests/generateTestConfig/example_neuron.py similarity index 100% rename from tests/example_neuron.py rename to tests/generateTestConfig/example_neuron.py diff --git a/tests/example_robertson.py b/tests/generateTestConfig/example_robertson.py similarity index 100% rename from tests/example_robertson.py rename to tests/generateTestConfig/example_robertson.py diff --git a/tests/example_steadystate.py b/tests/generateTestConfig/example_steadystate.py similarity index 100% rename from tests/example_steadystate.py rename to tests/generateTestConfig/example_steadystate.py diff --git a/tests/generateTestConfigurationForExamples.sh b/tests/generateTestConfigurationForExamples.sh index c8dd8ec2f9..c30a2fdd4d 100755 --- a/tests/generateTestConfigurationForExamples.sh +++ b/tests/generateTestConfigurationForExamples.sh @@ -1,11 +1,17 @@ #!/bin/bash +# Generate AMICI configuration for test models + +# AMICI root directory AMICI_PATH="`dirname \"$BASH_SOURCE\"`" AMICI_PATH="`( cd \"$AMICI_PATH/..\" && pwd )`" -cd ${AMICI_PATH}/tests +# File with test configuration +TEST_FILE="${AMICI_PATH}/tests/cpputest/testOptions.h5" -TEST_FILE="cpputest/testOptions.h5" +# Delete old config rm ${TEST_FILE} + +cd ${AMICI_PATH}/tests/generateTestConfig ./example_dirac.py ${TEST_FILE} ./example_events.py ${TEST_FILE} ./example_jakstat.py ${TEST_FILE} @@ -13,4 +19,3 @@ rm ${TEST_FILE} ./example_neuron.py ${TEST_FILE} ./example_robertson.py ${TEST_FILE} ./example_steadystate.py ${TEST_FILE} - diff --git a/tests/testCoverage.py b/tests/testCoverage.py index 0345c6aa32..024b1d7286 100755 --- a/tests/testCoverage.py +++ b/tests/testCoverage.py @@ -28,6 +28,7 @@ import testPandas import testPYSB import testCPP +import testMisc # build the testSuite from testModels and testSBML suite = unittest.TestSuite() @@ -36,6 +37,7 @@ suite.addTest(testPandas.TestAmiciPandasImportExport()) suite.addTest(testPYSB.TestAmiciPYSBModel()) suite.addTest(testCPP.TestAmiciCPP()) +suite.addTest(testMisc.TestAmiciMisc()) testRunner = unittest.TextTestRunner(verbosity=0) result = testRunner.run(suite) @@ -44,4 +46,4 @@ cov.xml_report(outfile='coverage_py.xml') # propagate failure -sys.exit(not result.wasSuccessful()) \ No newline at end of file +sys.exit(not result.wasSuccessful()) diff --git a/tests/testMisc.py b/tests/testMisc.py new file mode 100755 index 0000000000..8f9e6445c9 --- /dev/null +++ b/tests/testMisc.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +"""Miscellaneous AMICI Python interface tests""" + +import amici +import unittest + + +class TestAmiciMisc(unittest.TestCase): + """TestCase class various AMICI Python interface functions""" + + def runTest(self): + self.test_parameterScalingFromIntVector() + + def test_parameterScalingFromIntVector(self): + """Ensure we can generate a ParameterScaling vector from Python""" + scale_vector = amici.parameterScalingFromIntVector( + [ + amici.ParameterScaling_log10, + amici.ParameterScaling_ln, + amici.ParameterScaling_none + ]) + assert scale_vector[0] == amici.ParameterScaling_log10 + assert scale_vector[1] == amici.ParameterScaling_ln + assert scale_vector[2] == amici.ParameterScaling_none + + +if __name__ == '__main__': + suite = unittest.TestSuite() + suite.addTest(TestAmiciMisc()) + unittest.main() diff --git a/tests/testModels.m b/tests/testModels.m index c3ba99c0a7..3c431b602d 100644 --- a/tests/testModels.m +++ b/tests/testModels.m @@ -1,19 +1,20 @@ +% Run AMICI Matlab tests using pre-generated models and test setup + function testModels() - % disable specific warnings for these tests, some tests are supposed % to produce warnings warningreset = warning; warning('off','AMICI:mex:simulation') warning('off','AMICI:mex:CVODES:CVode:TOO_MUCH_WORK') - + ignoredTests = {'/model_jakstat_adjoint/sensiadjointemptysensind', ... '/model_jakstat_adjoint/sensiforwardemptysensind'}; - + cd(fileparts(mfilename('fullpath'))) addpath(genpath('cpputest')); wrapTestModels() cd(fileparts(mfilename('fullpath'))) - + hdf5file = fullfile(fileparts(mfilename('fullpath')),'cpputest','expectedResults.h5'); info = h5info(hdf5file); @@ -29,17 +30,17 @@ function testModels() if(ismember(info.Groups(imodel).Groups(itest).Name, ignoredTests)) continue end - + [results,options,data,t,theta,kappa] = readDataFromHDF5(info.Groups(imodel).Groups(itest),hdf5file); sol = getResults(info.Groups(imodel).Name(2:end),options,data,t,theta,kappa); compareResults(sol,results); end end - + warning(warningreset); - + %% begin nested functions - + function sol = getResults(modelname,options,data,t,theta,kappa) theta = options.theta; options = rmfield(options,'theta'); @@ -55,13 +56,13 @@ function testModels() end sol = feval(['simulate_' modelname],t,theta,kappa,ami_data,ami_options); end - + function compareResults(sol,results) if(results.status<0) assert(sol.status<0) return end - + for ifield = transpose(fieldnames(sol)) if(strcmp(ifield{1},'diagnosis')) for jfield = transpose(fieldnames(sol.diagnosis)) @@ -86,7 +87,7 @@ function compareResults(sol,results) end end end - + function checkAgreement(sol,results,fieldname,atol,rtol) if(~isfield(results,fieldname)) assert(isempty(sol.(fieldname))) @@ -113,7 +114,7 @@ function checkAgreement(sol,results,fieldname,atol,rtol) assert(all(abs(expected - actual) <= atol) || all(abs((expected - actual) ./ (rtol + abs(expected))) <= rtol)); end end - + function [results,options,data,t,theta,kappa] = readDataFromHDF5(groups,hdf5file); data = []; t = []; @@ -139,9 +140,9 @@ function checkAgreement(sol,results,fieldname,atol,rtol) end end end - - - + + + function matlab = cpp2matlab(cpp) dims = size(cpp); if(sum(dims>1)>1 || length(dims)>2) @@ -158,7 +159,7 @@ function checkAgreement(sol,results,fieldname,atol,rtol) end matlab = double(matlab); end - + function s = hdf2struct(group,hdf5path,hdf5file) s = struct; if(~isempty(group.Attributes)) diff --git a/tests/testPandas.py b/tests/testPandas.py index 1c53f9257c..c0fdb4a55e 100755 --- a/tests/testPandas.py +++ b/tests/testPandas.py @@ -119,4 +119,3 @@ def tests_presimulation(self): suite = unittest.TestSuite() suite.addTest(TestAmiciPandasImportExport()) unittest.main() - \ No newline at end of file diff --git a/version.txt b/version.txt index 6f4eebdf6f..100435be13 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.8.1 +0.8.2