From a3b0caccff0ec38c8611fc13a2bd3114e22024e2 Mon Sep 17 00:00:00 2001 From: Polina Lakrisenko Date: Tue, 1 Feb 2022 14:06:52 +0100 Subject: [PATCH 01/22] Doc: fix typo (#1645) --- src/steadystateproblem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/steadystateproblem.cpp b/src/steadystateproblem.cpp index 9ae6d7bd41..2c23abdaf1 100644 --- a/src/steadystateproblem.cpp +++ b/src/steadystateproblem.cpp @@ -284,7 +284,7 @@ void SteadystateProblem::getQuadratureByLinSolve(NewtonSolver *newtonSolver, /* compute integral over xB and write to xQ */ newtonSolver->prepareLinearSystemB(0, -1); newtonSolver->solveLinearSystem(xQ_); - /* Compute the quadrature as the inner product xQ * dxotdp */ + /* Compute the quadrature as the inner product xQ * dxdotdp */ computeQBfromQ(model, xQ_, xQB_); /* set flag that quadratures is available (for processing in rdata) */ hasQuadrature_ = true; @@ -695,7 +695,7 @@ std::unique_ptr SteadystateProblem::createSteadystateSimSolver( void SteadystateProblem::computeQBfromQ(Model *model, const AmiVector &yQ, AmiVector &yQB) const { - /* Compute the quadrature as the inner product: yQB = dxotdp * yQ */ + /* Compute the quadrature as the inner product: yQB = dxdotdp * yQ */ /* set to zero first, as multiplication adds to existing value */ yQB.zero(); From e92cad4443b7baa7958d6a53df7630fcf46ff91c Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Tue, 1 Feb 2022 17:47:50 +0100 Subject: [PATCH 02/22] SBML import: Fix special function parsing inside pow() (#1647) Fixes #1646 --- python/amici/import_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/amici/import_utils.py b/python/amici/import_utils.py index bf1a3947bc..a4695cb8f8 100644 --- a/python/amici/import_utils.py +++ b/python/amici/import_utils.py @@ -356,7 +356,7 @@ def _parse_special_functions(sym: sp.Expr, toplevel: bool = True) -> sp.Expr: if sym.__class__.__name__ == 'plus' and not sym.args: return sp.Float(0.0) - if isinstance(sym, (sp.Function, sp.Mul, sp.Add)): + if isinstance(sym, (sp.Function, sp.Mul, sp.Add, sp.Pow)): sym._args = args elif toplevel and isinstance(sym, BooleanAtom): From f7c005d098dd57374d3b900e93760f3fcdc0815b Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Tue, 1 Feb 2022 23:26:58 +0100 Subject: [PATCH 03/22] Change Model::setStateIsNonNegative logic (#1648) Previously `model.setStateIsNonNegative(model.getStateIsNonNegative())` failed if conservation laws were enabled. That feels unintuitive. Now it works. --- src/model.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/model.cpp b/src/model.cpp index e73171c1a7..cfd12c17e3 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -609,7 +609,11 @@ std::vector const &Model::getStateIsNonNegative() const { } void Model::setStateIsNonNegative(std::vector const &nonNegative) { - if (nx_solver != nx_rdata) { + auto any_state_non_negative = std::any_of(nonNegative.begin(), + nonNegative.end(), + [](bool x) { return x; }); + + if (any_state_non_negative && nx_solver != nx_rdata) { throw AmiException("Non-negative states are not supported with" " conservation laws enabled"); } @@ -619,9 +623,7 @@ void Model::setStateIsNonNegative(std::vector const &nonNegative) { state_is_non_negative_.size(), nx_rdata); } state_is_non_negative_ = nonNegative; - any_state_non_negative_ = - std::any_of(state_is_non_negative_.begin(), state_is_non_negative_.end(), - [](bool x) { return x; }); + any_state_non_negative_ = any_state_non_negative; } void Model::setAllStatesNonNegative() { From 4d65631bc69eb44c62398c5cff008bfbc9faed70 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 2 Feb 2022 17:02:38 +0100 Subject: [PATCH 04/22] Update valgrind suppressions (#1651) --- python/tests/valgrind-python.supp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/tests/valgrind-python.supp b/python/tests/valgrind-python.supp index 2b115b2486..0cfb67e1d8 100644 --- a/python/tests/valgrind-python.supp +++ b/python/tests/valgrind-python.supp @@ -262,7 +262,7 @@ } { - + _PyUnicodeWriter_WriteSubstring Memcheck:Cond ... fun:_PyUnicodeWriter_WriteSubstring @@ -447,9 +447,7 @@ other Memcheck:Cond ... - obj:/usr/bin/python3.? fun:PyDict_SetItem - obj:/usr/bin/python3.? ... } From 72abd12d958b060cc1fb5041a5d28ef4c5453070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Wed, 2 Feb 2022 13:49:49 -0500 Subject: [PATCH 05/22] fix using x_pos in all model functions (#1650) * fix using x_pos in all model functions * Update model.cpp * fixup * fixup * copy xpos when applying delta x --- include/amici/model.h | 15 ++++++ src/model.cpp | 113 ++++++++++++++++++++++++++---------------- 2 files changed, 86 insertions(+), 42 deletions(-) diff --git a/include/amici/model.h b/include/amici/model.h index 7ba3ff17a6..7de98177e8 100644 --- a/include/amici/model.h +++ b/include/amici/model.h @@ -1723,6 +1723,21 @@ class Model : public AbstractModel, public ModelDimensions { * stateIsNonNegative */ const_N_Vector computeX_pos(const_N_Vector x); + + /** + * @brief Compute non-negative state vector. + * + * Compute non-negative state vector according to stateIsNonNegative. + * If anyStateNonNegative is set to `false`, i.e., all entries in + * stateIsNonNegative are `false`, this function directly returns `x`, + * otherwise all entries of x are copied in to `amici::Model::x_pos_tmp_` + * and negative values are replaced by `0` where applicable. + * + * @param x State vector possibly containing negative values + * @return State vector with negative values replaced by `0` according to + * stateIsNonNegative + */ + const realtype *computeX_pos(AmiVector const& x); /** All variables necessary for function evaluation */ ModelState state_; diff --git a/src/model.cpp b/src/model.cpp index cfd12c17e3..2e1a557992 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -790,9 +790,10 @@ void Model::requireSensitivitiesForAllParameters() { initializeVectors(); } -void Model::getExpression(gsl::span w, const realtype t, const AmiVector &x) +void Model::getExpression(gsl::span w, const realtype t, + const AmiVector &x) { - fw(t, x.data()); + fw(t, computeX_pos(x)); writeSlice(derived_state_.w_, w); } @@ -922,9 +923,9 @@ void Model::getEventSensitivity(gsl::span sz, const int ie, const realtype t, const AmiVector &x, const AmiVectorArray &sx) { for (int ip = 0; ip < nplist(); ip++) { - fsz(&sz[ip * nz], ie, t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), state_.h.data(), sx.data(ip), - plist(ip)); + fsz(&sz[ip * nz], ie, t, computeX_pos(x), + state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.h.data(), sx.data(ip), plist(ip)); } } @@ -949,8 +950,9 @@ void Model::getEventRegularizationSensitivity(gsl::span srz, const AmiVector &x, const AmiVectorArray &sx) { for (int ip = 0; ip < nplist(); ip++) { - fsrz(&srz[ip * nz], ie, t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), state_.h.data(), sx.data(ip), + fsrz(&srz[ip * nz], ie, t, computeX_pos(x), + state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.h.data(), sx.data(ip), plist(ip)); } } @@ -1072,8 +1074,9 @@ void Model::getEventTimeSensitivity(std::vector &stau, std::fill(stau.begin(), stau.end(), 0.0); for (int ip = 0; ip < nplist(); ip++) { - fstau(&stau.at(ip), t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), state_.h.data(), sx.data(ip), + fstau(&stau.at(ip), t, computeX_pos(x), + state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.h.data(), sx.data(ip), plist(ip), ie); } } @@ -1081,20 +1084,23 @@ void Model::getEventTimeSensitivity(std::vector &stau, void Model::addStateEventUpdate(AmiVector &x, const int ie, const realtype t, const AmiVector &xdot, const AmiVector &xdot_old) { - + derived_state_.deltax_.assign(nx_solver, 0.0); + + std::copy_n(computeX_pos(x), nx_solver, x.data()); // compute update - fdeltax(derived_state_.deltax_.data(), t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), state_.h.data(), ie, xdot.data(), - xdot_old.data()); + fdeltax(derived_state_.deltax_.data(), t, x.data(), + state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.h.data(), ie, xdot.data(), xdot_old.data()); if (always_check_finite_) { app->checkFinite(derived_state_.deltax_, "deltax"); } // update - amici_daxpy(nx_solver, 1.0, derived_state_.deltax_.data(), 1, x.data(), 1); + amici_daxpy(nx_solver, 1.0, derived_state_.deltax_.data(), 1, x.data(), + 1); } void Model::addStateSensitivityEventUpdate(AmiVectorArray &sx, const int ie, @@ -1111,7 +1117,8 @@ void Model::addStateSensitivityEventUpdate(AmiVectorArray &sx, const int ie, // compute update fdeltasx(derived_state_.deltasx_.data(), t, x_old.data(), - state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.unscaledParameters.data(), + state_.fixedParameters.data(), state_.h.data(), derived_state_.w_.data(), plist(ip), ie, xdot.data(), xdot_old.data(), sx.data(ip), &stau.at(ip)); @@ -1132,7 +1139,7 @@ void Model::addAdjointStateEventUpdate(AmiVector &xB, const int ie, derived_state_.deltaxB_.assign(nx_solver, 0.0); // compute update - fdeltaxB(derived_state_.deltaxB_.data(), t, x.data(), + fdeltaxB(derived_state_.deltaxB_.data(), t, computeX_pos(x), state_.unscaledParameters.data(), state_.fixedParameters.data(), state_.h.data(), ie, xdot.data(), xdot_old.data(), xB.data()); @@ -1154,7 +1161,8 @@ void Model::addAdjointQuadratureEventUpdate( for (int ip = 0; ip < nplist(); ip++) { derived_state_.deltaqB_.assign(nJ, 0.0); - fdeltaqB(derived_state_.deltaqB_.data(), t, x.data(), state_.unscaledParameters.data(), + fdeltaqB(derived_state_.deltaqB_.data(), t, computeX_pos(x), + state_.unscaledParameters.data(), state_.fixedParameters.data(), state_.h.data(), plist(ip), ie, xdot.data(), xdot_old.data(), xB.data()); @@ -1217,11 +1225,13 @@ void Model::fx0(AmiVector &x) { void Model::fx0_fixedParameters(AmiVector &x) { if (!getReinitializeFixedParameterInitialStates()) return; + /* we transform to the unreduced states x_rdata and then apply x0_fixedparameters to (i) enable updates to states that were removed from conservation laws and (ii) be able to correctly compute total abundances after updating the state variables */ - fx_rdata(derived_state_.x_rdata_.data(), x.data(), state_.total_cl.data()); + fx_rdata(derived_state_.x_rdata_.data(), computeX_pos(x), + state_.total_cl.data()); fx0_fixedParameters(derived_state_.x_rdata_.data(), simulation_parameters_.tstart_, state_.unscaledParameters.data(), @@ -1242,7 +1252,7 @@ void Model::fsx0(AmiVectorArray &sx, const AmiVector &x) { std::fill(derived_state_.sx_rdata_.begin(), derived_state_.sx_rdata_.end(), 0.0); fsx0(derived_state_.sx_rdata_.data(), simulation_parameters_.tstart_, - x.data(), state_.unscaledParameters.data(), + computeX_pos(x), state_.unscaledParameters.data(), state_.fixedParameters.data(), plist(ip)); fsx_solver(sx.data(ip), derived_state_.sx_rdata_.data()); fstotal_cl(stcl, derived_state_.sx_rdata_.data(), plist(ip)); @@ -1258,7 +1268,8 @@ void Model::fsx0_fixedParameters(AmiVectorArray &sx, const AmiVector &x) { stcl = &state_.stotal_cl.at(plist(ip) * ncl()); fsx_rdata(derived_state_.sx_rdata_.data(), sx.data(ip), stcl, plist(ip)); fsx0_fixedParameters(derived_state_.sx_rdata_.data(), - simulation_parameters_.tstart_, x.data(), + simulation_parameters_.tstart_, + computeX_pos(x), state_.unscaledParameters.data(), state_.fixedParameters.data(), plist(ip), @@ -1271,7 +1282,7 @@ void Model::fsx0_fixedParameters(AmiVectorArray &sx, const AmiVector &x) { void Model::fsdx0() {} void Model::fx_rdata(AmiVector &x_rdata, const AmiVector &x) { - fx_rdata(x_rdata.data(), x.data(), state_.total_cl.data()); + fx_rdata(x_rdata.data(), computeX_pos(x), state_.total_cl.data()); if (always_check_finite_) checkFinite(x_rdata.getVector(), "x_rdata"); } @@ -1336,12 +1347,14 @@ void Model::initializeVectors() { void Model::fy(const realtype t, const AmiVector &x) { if (!ny) return; + + auto x_pos = computeX_pos(x); derived_state_.y_.assign(ny, 0.0); - fw(t, x.data()); - fy(derived_state_.y_.data(), t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), + fw(t, x_pos); + fy(derived_state_.y_.data(), t, x_pos, + state_.unscaledParameters.data(), state_.fixedParameters.data(), state_.h.data(), derived_state_.w_.data()); if (always_check_finite_) { @@ -1352,20 +1365,22 @@ void Model::fy(const realtype t, const AmiVector &x) { void Model::fdydp(const realtype t, const AmiVector &x) { if (!ny) return; + + auto x_pos = computeX_pos(x); derived_state_.dydp_.assign(ny * nplist(), 0.0); - fw(t, x.data()); - fdwdp(t, x.data()); + fw(t, x_pos); + fdwdp(t, x_pos); /* get dydp slice (ny) for current time and parameter */ for (int ip = 0; ip < nplist(); ip++) if (pythonGenerated) { - fdydp(&derived_state_.dydp_.at(ip * ny), t, x.data(), + fdydp(&derived_state_.dydp_.at(ip * ny), t, x_pos, state_.unscaledParameters.data(), state_.fixedParameters.data(), state_.h.data(), plist(ip), derived_state_.w_.data(), state_.stotal_cl.data()); } else { - fdydp(&derived_state_.dydp_.at(ip * ny), t, x.data(), + fdydp(&derived_state_.dydp_.at(ip * ny), t, x_pos, state_.unscaledParameters.data(), state_.fixedParameters.data(), state_.h.data(), plist(ip), derived_state_.w_.data(), derived_state_.dwdp_.data()); @@ -1379,14 +1394,17 @@ void Model::fdydp(const realtype t, const AmiVector &x) { void Model::fdydx(const realtype t, const AmiVector &x) { if (!ny) return; + + auto x_pos = computeX_pos(x); derived_state_.dydx_.assign(ny * nx_solver, 0.0); - fw(t, x.data()); - fdwdx(t, x.data()); - fdydx(derived_state_.dydx_.data(), t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), state_.h.data(), - derived_state_.w_.data(), derived_state_.dwdx_.data()); + fw(t, x_pos); + fdwdx(t, x_pos); + fdydx(derived_state_.dydx_.data(), t, x_pos, + state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.h.data(), derived_state_.w_.data(), + derived_state_.dwdx_.data()); if (always_check_finite_) { app->checkFinite(derived_state_.dydx_, "dydx"); @@ -1612,8 +1630,9 @@ void Model::fz(const int ie, const realtype t, const AmiVector &x) { derived_state_.z_.assign(nz, 0.0); - fz(derived_state_.z_.data(), ie, t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), state_.h.data()); + fz(derived_state_.z_.data(), ie, t, computeX_pos(x), + state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.h.data()); } void Model::fdzdp(const int ie, const realtype t, const AmiVector &x) { @@ -1623,7 +1642,7 @@ void Model::fdzdp(const int ie, const realtype t, const AmiVector &x) { derived_state_.dzdp_.assign(nz * nplist(), 0.0); for (int ip = 0; ip < nplist(); ip++) { - fdzdp(derived_state_.dzdp_.data(), ie, t, x.data(), + fdzdp(derived_state_.dzdp_.data(), ie, t, computeX_pos(x), state_.unscaledParameters.data(), state_.fixedParameters.data(), state_.h.data(), plist(ip)); } @@ -1639,8 +1658,9 @@ void Model::fdzdx(const int ie, const realtype t, const AmiVector &x) { derived_state_.dzdx_.assign(nz * nx_solver, 0.0); - fdzdx(derived_state_.dzdx_.data(), ie, t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), state_.h.data()); + fdzdx(derived_state_.dzdx_.data(), ie, t, computeX_pos(x), + state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.h.data()); if (always_check_finite_) { app->checkFinite(derived_state_.dzdx_, "dzdx"); @@ -1651,7 +1671,7 @@ void Model::frz(const int ie, const realtype t, const AmiVector &x) { derived_state_.rz_.assign(nz, 0.0); - frz(derived_state_.rz_.data(), ie, t, x.data(), + frz(derived_state_.rz_.data(), ie, t, computeX_pos(x), state_.unscaledParameters.data(), state_.fixedParameters.data(), state_.h.data()); } @@ -1663,7 +1683,7 @@ void Model::fdrzdp(const int ie, const realtype t, const AmiVector &x) { derived_state_.drzdp_.assign(nz * nplist(), 0.0); for (int ip = 0; ip < nplist(); ip++) { - fdrzdp(derived_state_.drzdp_.data(), ie, t, x.data(), + fdrzdp(derived_state_.drzdp_.data(), ie, t, computeX_pos(x), state_.unscaledParameters.data(), state_.fixedParameters.data(), state_.h.data(), plist(ip)); } @@ -1679,8 +1699,9 @@ void Model::fdrzdx(const int ie, const realtype t, const AmiVector &x) { derived_state_.drzdx_.assign(nz * nx_solver, 0.0); - fdrzdx(derived_state_.drzdx_.data(), ie, t, x.data(), state_.unscaledParameters.data(), - state_.fixedParameters.data(), state_.h.data()); + fdrzdx(derived_state_.drzdx_.data(), ie, t, computeX_pos(x), + state_.unscaledParameters.data(), state_.fixedParameters.data(), + state_.h.data()); if (always_check_finite_) { app->checkFinite(derived_state_.drzdx_, "drzdx"); @@ -2103,6 +2124,14 @@ const_N_Vector Model::computeX_pos(const_N_Vector x) { return x; } +const realtype *Model::computeX_pos(AmiVector const& x) { + if (any_state_non_negative_) { + computeX_pos(x.getNVector()); + return derived_state_.x_pos_tmp_.data(); + } + return x.data(); +} + void Model::setReinitializationStateIdxs(std::vector const& idxs) { for(auto idx: idxs) { From ee6c1ef5eb22b1ab8b03498326b708ea4c3b84a8 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 2 Feb 2022 22:23:57 +0100 Subject: [PATCH 06/22] Fix DOI links in refence list (#1653) --- documentation/amici_refs.bib | 16 ++++++++-------- documentation/references.md | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/documentation/amici_refs.bib b/documentation/amici_refs.bib index ded97337cd..6a0b18243f 100644 --- a/documentation/amici_refs.bib +++ b/documentation/amici_refs.bib @@ -587,7 +587,7 @@ @Article{GerosaChi2020 issn = {2405-4712}, abstract = {Summary Targeted inhibition of oncogenic pathways can be highly effective in halting the rapid growth of tumors but often leads to the emergence of slowly dividing persister cells, which constitute a reservoir for the selection of drug-resistant clones. In BRAFV600E melanomas, RAF and MEK inhibitors efficiently block oncogenic signaling, but persister cells emerge. Here, we show that persister cells escape drug-induced cell-cycle arrest via brief, sporadic ERK pulses generated by transmembrane receptors and growth factors operating in an autocrine/paracrine manner. Quantitative proteomics and computational modeling show that ERK pulsing is enabled by rewiring of mitogen-activated protein kinase (MAPK) signaling: from an oncogenic BRAFV600E monomer-driven configuration that is drug sensitive to a receptor-driven configuration that involves Ras-GTP and RAF dimers and is highly resistant to RAF and MEK inhibitors. Altogether, this work shows that pulsatile MAPK activation by factors in the microenvironment generates a persistent population of melanoma cells that rewires MAPK signaling to sustain non-genetic drug resistance.}, - doi = {https://doi.org/10.1016/j.cels.2020.10.002}, + doi = {10.1016/j.cels.2020.10.002}, keywords = {systems pharmacology, targeted therapy, non-genetic drug resistance, signaling plasticity, cancer persistence, BRAF melanoma, MAPK pathway, kinetic modeling, kinase inhibitors}, timestamp = {2020-11-09}, url = {http://www.sciencedirect.com/science/article/pii/S2405471220303707}, @@ -602,7 +602,7 @@ @Article{StenEli2020 pages = {116827}, volume = {215}, abstract = {The neurovascular coupling (NVC) connects neuronal activity to hemodynamic responses in the brain. This connection is the basis for the interpretation of functional magnetic resonance imaging data. Despite the central role of this coupling, we lack detailed knowledge about cell-specific contributions and our knowledge about NVC is mainly based on animal experiments performed during anesthesia. Anesthetics are known to affect neuronal excitability, but how this affects the vessel diameters is not known. Due to the high complexity of NVC data, mathematical modeling is needed for a meaningful analysis. However, neither the relevant neuronal subtypes nor the effects of anesthetics are covered by current models. Here, we present a mathematical model including GABAergic interneurons and pyramidal neurons, as well as the effect of an anesthetic agent. The model is consistent with data from optogenetic experiments from both awake and anesthetized animals, and it correctly predicts data from experiments with different pharmacological modulators. The analysis suggests that no downstream anesthetic effects are necessary if one of the GABAergic interneuron signaling pathways include a Michaelis-Menten expression. This is the first example of a quantitative model that includes both the cell-specific contributions and the effect of an anesthetic agent on the NVC.}, - doi = {https://doi.org/10.1016/j.neuroimage.2020.116827}, + doi = {10.1016/j.neuroimage.2020.116827}, keywords = {Functional hyperemia, Mathematical modeling, Cerebral hemodynamics, Systems biology, Functional magnetic resonance imaging (fMRI), Blood oxygen level dependent (BOLD) response}, timestamp = {2020-11-09}, url = {http://www.sciencedirect.com/science/article/pii/S1053811920303141}, @@ -665,7 +665,7 @@ @Article{PittGom2018 pages = {72 - 75}, volume = {51}, abstract = {Many biological systems exhibit oscillations in relation to key physiological or cellular functions, such as circadian rhythms, mitosis and DNA synthesis. Mathematical modelling provides a powerful approach to analysing these biosystems. Applying parameter estimation methods to calibrate these models can prove a very challenging task in practice, due to the presence of local solutions, lack of identifiability, and risk of overfitting. This paper presents a comparison of three state-of-the-art methods: frequentist, Bayesian and set-membership estimation. We use the Fitzhugh-Nagumo model with synthetic data as a case study. The computational performance and robustness of these methods is discussed, with a particular focus on their predictive capability using cross-validation.}, - doi = {https://doi.org/10.1016/j.ifacol.2018.09.040}, + doi = {10.1016/j.ifacol.2018.09.040}, keywords = {biological oscillators, model calibration, regularisation, overfitting, identifiability, frequentist estimation, Bayesian estimation, set-membership estimation}, timestamp = {2020-11-09}, url = {http://www.sciencedirect.com/science/article/pii/S2405896318316999}, @@ -734,7 +734,7 @@ @Article{RaimundezDud2021 pages = {100439}, volume = {34}, abstract = {Epidemiological models are widely used to analyze the spread of diseases such as the global COVID-19 pandemic caused by SARS-CoV-2. However, all models are based on simplifying assumptions and often on sparse data. This limits the reliability of parameter estimates and predictions. In this manuscript, we demonstrate the relevance of these limitations and the pitfalls associated with the use of overly simplistic models. We considered the data for the early phase of the COVID-19 outbreak in Wuhan, China, as an example, and perform parameter estimation, uncertainty analysis and model selection for a range of established epidemiological models. Amongst others, we employ Markov chain Monte Carlo sampling, parameter and prediction profile calculation algorithms. Our results show that parameter estimates and predictions obtained for several established models on the basis of reported case numbers can be subject to substantial uncertainty. More importantly, estimates were often unrealistic and the confidence/credibility intervals did not cover plausible values of critical parameters obtained using different approaches. These findings suggest, amongst others, that standard compartmental models can be overly simplistic and that the reported case numbers provide often insufficient information for obtaining reliable and realistic parameter values, and for forecasting the evolution of epidemics.}, - doi = {https://doi.org/10.1016/j.epidem.2021.100439}, + doi = {10.1016/j.epidem.2021.100439}, keywords = {Compartment model, SEIRD, Parameter estimation, Model selection, Uncertainty analysis}, timestamp = {2021-02-19}, url = {https://www.sciencedirect.com/science/article/pii/S1755436521000037}, @@ -749,7 +749,7 @@ @Article{vanRosmalenSmi2021 pages = {74-84}, volume = {64}, abstract = {Constraint-based, genome-scale metabolic models are an essential tool to guide metabolic engineering. However, they lack the detail and time dimension that kinetic models with enzyme dynamics offer. Model reduction can be used to bridge the gap between the two methods and allow for the integration of kinetic models into the Design-Built-Test-Learn cycle. Here we show that these reduced size models can be representative of the dynamics of the original model and demonstrate the automated generation and parameterisation of such models. Using these minimal models of metabolism could allow for further exploration of dynamic responses in metabolic networks.}, - doi = {https://doi.org/10.1016/j.ymben.2021.01.008}, + doi = {10.1016/j.ymben.2021.01.008}, keywords = {Metabolic engineering, DBTL cycle, Model reduction, Model optimisation, Model-driven design, Synthetic biology}, url = {https://www.sciencedirect.com/science/article/pii/S1096717621000161}, } @@ -830,7 +830,7 @@ @Article{BastBuc2021 volume = {24}, abstract = {Summary Classically, hematopoietic stem cell (HSC) differentiation is assumed to occur via progenitor compartments of decreasing plasticity and increasing maturity in a specific, hierarchical manner. The classical hierarchy has been challenged in the past by alternative differentiation pathways. We abstracted experimental evidence into 10 differentiation hierarchies, each comprising 7 cell type compartments. By fitting ordinary differential equation models with realistic waiting time distributions to time-resolved data of differentiating HSCs from 10 healthy human donors, we identified plausible lineage hierarchies and rejected others. We found that, for most donors, the classical model of hematopoiesis is preferred. Surprisingly, multipotent lymphoid progenitor differentiation into granulocyte-monocyte progenitors is plausible in 90% of samples. An in silico analysis confirmed that, even for strong noise, the classical model can be identified robustly. Our computational approach infers differentiation hierarchies in a personalized fashion and can be used to gain insights into kinetic alterations of diseased hematopoiesis.}, - doi = {https://doi.org/10.1016/j.isci.2021.102120}, + doi = {10.1016/j.isci.2021.102120}, keywords = {stem cells research, in silico biology, systems biology}, url = {https://www.sciencedirect.com/science/article/pii/S2589004221000882}, } @@ -902,7 +902,7 @@ @Article{GudinaAli2021 SARS-CoV-2 spread in Ethiopia has been highly dynamic among hospital worker and urban communities. We can speculate that the greatest wave of SARS-CoV-2 infections is currently evolving in rural Ethiopia, and thus requires focused attention regarding health-care burden and disease prevention. Funding Bavarian State Ministry of Sciences, Research, and the Arts; Germany Ministry of Education and Research; EU Horizon 2020 programme; Deutsche Forschungsgemeinschaft; and Volkswagenstiftung.}, - doi = {https://doi.org/10.1016/S2214-109X(21)00386-7}, + doi = {10.1016/S2214-109X(21)00386-7}, url = {https://www.sciencedirect.com/science/article/pii/S2214109X21003867}, } @@ -994,7 +994,7 @@ @Article{AdlungSta2021 volume = {36}, abstract = {Summary Survival or apoptosis is a binary decision in individual cells. However, at the cell-population level, a graded increase in survival of colony-forming unit-erythroid (CFU-E) cells is observed upon stimulation with erythropoietin (Epo). To identify components of Janus kinase 2/signal transducer and activator of transcription 5 (JAK2/STAT5) signal transduction that contribute to the graded population response, we extended a cell-population-level model calibrated with experimental data to study the behavior in single cells. The single-cell model shows that the high cell-to-cell variability in nuclear phosphorylated STAT5 is caused by variability in the amount of Epo receptor (EpoR):JAK2 complexes and of SHP1, as well as the extent of nuclear import because of the large variance in the cytoplasmic volume of CFU-E cells. 24–118 pSTAT5 molecules in the nucleus for 120 min are sufficient to ensure cell survival. Thus, variability in membrane-associated processes is sufficient to convert a switch-like behavior at the single-cell level to a graded population-level response.}, - doi = {https://doi.org/10.1016/j.celrep.2021.109507}, + doi = {10.1016/j.celrep.2021.109507}, keywords = {single-cell modeling, JAK/STAT, signal transduction, Epo, heterogeneity, cell fate decision, apoptosis, CFU-E cells, transcription factor, mathematical modeling}, url = {https://www.sciencedirect.com/science/article/pii/S2211124721009372}, } diff --git a/documentation/references.md b/documentation/references.md index 4eb30a5013..7c559496c0 100644 --- a/documentation/references.md +++ b/documentation/references.md @@ -16,10 +16,10 @@ If you applied AMICI in your work and your publication is missing, please let us

2021

-

Adlung, Lorenz, Paul Stapor, Christian Tönsing, Leonard Schmiester, Luisa E. Schwarzmüller, Lena Postawa, Dantong Wang, et al. 2021. “Cell-to-Cell Variability in Jak2/Stat5 Pathway Components and Cytoplasmic Volumes Defines Survival Threshold in Erythroid Progenitor Cells.” Cell Reports 36 (6): 109507. https://doi.org/https://doi.org/10.1016/j.celrep.2021.109507.

+

Adlung, Lorenz, Paul Stapor, Christian Tönsing, Leonard Schmiester, Luisa E. Schwarzmüller, Lena Postawa, Dantong Wang, et al. 2021. “Cell-to-Cell Variability in Jak2/Stat5 Pathway Components and Cytoplasmic Volumes Defines Survival Threshold in Erythroid Progenitor Cells.” Cell Reports 36 (6): 109507. https://doi.org/10.1016/j.celrep.2021.109507.

-

Bast, Lisa, Michèle C. Buck, Judith S. Hecker, Robert A. J. Oostendorp, Katharina S. Götze, and Carsten Marr. 2021. “Computational Modeling of Stem and Progenitor Cell Kinetics Identifies Plausible Hematopoietic Lineage Hierarchies.” iScience 24 (2): 102120. https://doi.org/https://doi.org/10.1016/j.isci.2021.102120.

+

Bast, Lisa, Michèle C. Buck, Judith S. Hecker, Robert A. J. Oostendorp, Katharina S. Götze, and Carsten Marr. 2021. “Computational Modeling of Stem and Progenitor Cell Kinetics Identifies Plausible Hematopoietic Lineage Hierarchies.” iScience 24 (2): 102120. https://doi.org/10.1016/j.isci.2021.102120.

Contento, Lorenzo, Noemi Castelletti, Elba Raimúndez, Ronan Le Gleut, Yannik Schälte, Paul Stapor, Ludwig Christian Hinske, et al. 2021. “Integrative Modelling of Reported Case Numbers and Seroprevalence Reveals Time-Dependent Test Efficiency and Infection Rates.” medRxiv. https://doi.org/10.1101/2021.10.01.21263052.

@@ -34,13 +34,13 @@ If you applied AMICI in your work and your publication is missing, please let us

Gaspari, Erika. 2021. “Model-Driven Design of Mycoplasma as a Vaccine Chassis.” PhD thesis, Wageningen: Wageningen University. https://doi.org/10.18174/539593.

-

Gudina, Esayas Kebede, Solomon Ali, Eyob Girma, Addisu Gize, Birhanemeskel Tegene, Gadissa Bedada Hundie, Wondewosen Tsegaye Sime, et al. 2021. “Seroepidemiology and model-based prediction of SARS-CoV-2 in Ethiopia: longitudinal cohort study among front-line hospital workers and communities.” The Lancet Global Health 9 (11): e1517–e1527. https://doi.org/https://doi.org/10.1016/S2214-109X(21)00386-7.

+

Gudina, Esayas Kebede, Solomon Ali, Eyob Girma, Addisu Gize, Birhanemeskel Tegene, Gadissa Bedada Hundie, Wondewosen Tsegaye Sime, et al. 2021. “Seroepidemiology and model-based prediction of SARS-CoV-2 in Ethiopia: longitudinal cohort study among front-line hospital workers and communities.” The Lancet Global Health 9 (11): e1517–e1527. https://doi.org/10.1016/S2214-109X(21)00386-7.

Maier, Corinna. 2021. “Bayesian Data Assimilation and Reinforcement Learning for Model-Informed Precision Dosing in Oncology.” Doctoralthesis, Universität Potsdam. https://doi.org/10.25932/publishup-51587.

-

Raimúndez, Elba, Erika Dudkin, Jakob Vanhoefer, Emad Alamoudi, Simon Merkt, Lara Fuhrmann, Fan Bai, and Jan Hasenauer. 2021. “COVID-19 Outbreak in Wuhan Demonstrates the Limitations of Publicly Available Case Numbers for Epidemiological Modeling.” Epidemics 34: 100439. https://doi.org/https://doi.org/10.1016/j.epidem.2021.100439.

+

Raimúndez, Elba, Erika Dudkin, Jakob Vanhoefer, Emad Alamoudi, Simon Merkt, Lara Fuhrmann, Fan Bai, and Jan Hasenauer. 2021. “COVID-19 Outbreak in Wuhan Demonstrates the Limitations of Publicly Available Case Numbers for Epidemiological Modeling.” Epidemics 34: 100439. https://doi.org/10.1016/j.epidem.2021.100439.

Schmiester, Leonard, Daniel Weindl, and Jan Hasenauer. 2021. “Efficient Gradient-Based Parameter Estimation for Dynamic Models Using Qualitative Data.” bioRxiv. https://doi.org/10.1101/2021.02.06.430039.

@@ -58,7 +58,7 @@ If you applied AMICI in your work and your publication is missing, please let us

Vanhoefer, Jakob, Marta R. A. Matos, Dilan Pathirana, Yannik Schälte, and Jan Hasenauer. 2021. “Yaml2sbml: Human-Readable and -Writable Specification of Ode Models and Their Conversion to Sbml.” Journal of Open Source Software 6 (61): 3215. https://doi.org/10.21105/joss.03215.

-

van Rosmalen, R. P., R. W. Smith, V. A. P. Martins dos Santos, C. Fleck, and M. Suarez-Diez. 2021. “Model Reduction of Genome-Scale Metabolic Models as a Basis for Targeted Kinetic Models.” Metabolic Engineering 64: 74–84. https://doi.org/https://doi.org/10.1016/j.ymben.2021.01.008.

+

van Rosmalen, R. P., R. W. Smith, V. A. P. Martins dos Santos, C. Fleck, and M. Suarez-Diez. 2021. “Model Reduction of Genome-Scale Metabolic Models as a Basis for Targeted Kinetic Models.” Metabolic Engineering 64: 74–84. https://doi.org/10.1016/j.ymben.2021.01.008.

Villaverde, Alejandro F, Dilan Pathirana, Fabian Fröhlich, Jan Hasenauer, and Julio R Banga. 2021. “A protocol for dynamic model calibration.” Briefings in Bioinformatics, October. https://doi.org/10.1093/bib/bbab387.

@@ -73,7 +73,7 @@ If you applied AMICI in your work and your publication is missing, please let us

Erdem, Cemal, Ethan M. Bensman, Arnab Mutsuddy, Michael M. Saint-Antoine, Mehdi Bouhaddou, Robert C. Blake, Will Dodd, et al. 2020. “A Simple and Efficient Pipeline for Construction, Merging, Expansion, and Simulation of Large-Scale, Single-Cell Mechanistic Models.” bioRxiv. https://doi.org/10.1101/2020.11.09.373407.

-

Gerosa, Luca, Christopher Chidley, Fabian Fröhlich, Gabriela Sanchez, Sang Kyun Lim, Jeremy Muhlich, Jia-Yun Chen, et al. 2020. “Receptor-Driven Erk Pulses Reconfigure Mapk Signaling and Enable Persistence of Drug-Adapted Braf-Mutant Melanoma Cells.” Cell Systems. https://doi.org/https://doi.org/10.1016/j.cels.2020.10.002.

+

Gerosa, Luca, Christopher Chidley, Fabian Fröhlich, Gabriela Sanchez, Sang Kyun Lim, Jeremy Muhlich, Jia-Yun Chen, et al. 2020. “Receptor-Driven Erk Pulses Reconfigure Mapk Signaling and Enable Persistence of Drug-Adapted Braf-Mutant Melanoma Cells.” Cell Systems. https://doi.org/10.1016/j.cels.2020.10.002.

Kuritz, Karsten, Alain R Bonny, João Pedro Fonseca, and Frank Allgöwer. 2020. “PDE-Constrained Optimization for Estimating Population Dynamics over Cell Cycle from Static Single Cell Measurements.” bioRxiv. https://doi.org/10.1101/2020.03.30.015909.

@@ -94,7 +94,7 @@ If you applied AMICI in your work and your publication is missing, please let us

Sten, Sebastian. 2020. “Mathematical Modeling of Neurovascular Coupling.” Linköping University Medical Dissertations. PhD thesis, Linköping UniversityLinköping UniversityLinköping University, Division of Diagnostics; Specialist Medicine, Faculty of Medicine; Health Sciences, Center for Medical Image Science; Visualization (CMIV); Linköping University, Division of Diagnostics; Specialist Medicine. https://doi.org/10.3384/diss.diva-167806.

-

Sten, Sebastian, Fredrik Elinder, Gunnar Cedersund, and Maria Engström. 2020. “A Quantitative Analysis of Cell-Specific Contributions and the Role of Anesthetics to the Neurovascular Coupling.” NeuroImage 215: 116827. https://doi.org/https://doi.org/10.1016/j.neuroimage.2020.116827.

+

Sten, Sebastian, Fredrik Elinder, Gunnar Cedersund, and Maria Engström. 2020. “A Quantitative Analysis of Cell-Specific Contributions and the Role of Anesthetics to the Neurovascular Coupling.” NeuroImage 215: 116827. https://doi.org/10.1016/j.neuroimage.2020.116827.

Tsipa, Argyro, Jake Alan Pitt, Julio R. Banga, and Athanasios Mantalaris. 2020. “A Dual-Parameter Identification Approach for Data-Based Predictive Modeling of Hybrid Gene Regulatory Network-Growth Kinetics in Pseudomonas Putida Mt-2.” Bioprocess and Biosystems Engineering 43 (9): 1671–88. https://doi.org/10.1007/s00449-020-02360-2.

@@ -163,7 +163,7 @@ If you applied AMICI in your work and your publication is missing, please let us

Loos, Carolin, Katharina Moeller, Fabian Fröhlich, Tim Hucho, and Jan Hasenauer. 2018. “A Hierarchical, Data-Driven Approach to Modeling Single-Cell Populations Predicts Latent Causes of Cell-to-Cell Variability.” Cell Systems 6 (5): 593–603. https://doi.org/10.1016/j.cels.2018.04.008.

-

Pitt, Jake Alan, Lucian Gomoescu, Constantinos C. Pantelides, Benoît Chachuat, and Julio R. Banga. 2018. “Critical Assessment of Parameter Estimation Methods in Models of Biological Oscillators.” IFAC-PapersOnLine 51 (19): 72–75. https://doi.org/https://doi.org/10.1016/j.ifacol.2018.09.040.

+

Pitt, Jake Alan, Lucian Gomoescu, Constantinos C. Pantelides, Benoît Chachuat, and Julio R. Banga. 2018. “Critical Assessment of Parameter Estimation Methods in Models of Biological Oscillators.” IFAC-PapersOnLine 51 (19): 72–75. https://doi.org/10.1016/j.ifacol.2018.09.040.

Schälte, Y., P. Stapor, and J. Hasenauer. 2018. “Evaluation of Derivative-Free Optimizers for Parameter Estimation in Systems Biology.” FAC-PapersOnLine 51 (19): 98–101. https://doi.org/10.1016/j.ifacol.2018.09.025.

From 4fc5e56c469fcc1de2cbc8a95796c19be36d3a00 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 2 Feb 2022 23:10:41 +0100 Subject: [PATCH 07/22] Update swig file (#1652) * Fix module docstring * Provide typemaps for function docstrings * use typing.TYPE_CHECKING --- swig/amici.i | 76 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/swig/amici.i b/swig/amici.i index f62845e62f..cfd3c29c9f 100644 --- a/swig/amici.i +++ b/swig/amici.i @@ -1,4 +1,56 @@ -%module amici +%define DOCSTRING +""" +Core C++ bindings +----------------- +This module encompasses the complete public C++ API of AMICI, which was +exposed via swig. All functions listed here are directly accessible in the +main amici package, i.e., :py:class:`amici.amici.ExpData` is available as +``amici.ExpData``. +Usage of functions and classes from the base ``amici`` package is +generally recommended as they often include convenience wrappers that avoid +common pitfalls when accessing C++ types from python and implement some +nonstandard type conversions. +""" +%enddef +%module (docstring=DOCSTRING) amici + +// typemaps for docstrings +%typemap(doctype) std::unique_ptr< amici::ExpData >::pointer "ExpData"; +%typemap(doctype) std::unique_ptr< amici::Solver > "SolverPtr"; +%typemap(doctype) std::vector< amici::realtype,std::allocator< amici::realtype > > "DoubleVector"; +%typemap(doctype) std::vector< double,std::allocator< double > > "DoubleVector"; +%typemap(doctype) std::vector< int,std::allocator< int > > "IntVector"; +%typemap(doctype) std::vector< amici::ParameterScaling,std::allocator< amici::ParameterScaling > > "ParameterScalingVector"; +%typemap(doctype) std::vector< std::string,std::allocator< std::string > > "StringVector"; +%typemap(doctype) std::vector< bool,std::allocator< bool > > "BoolVector"; +%typemap(doctype) std::map< std::string,amici::realtype,std::less< std::string >, std::allocator< std::pair< std::string const,amici::realtype > > > "StringDoubleMap"; +%typemap(doctype) std::vector< amici::ExpData *,std::allocator< amici::ExpData * > > "ExpDataPtrVector"; +%typemap(doctype) std::vector< std::unique_ptr< amici::ReturnData >,std::allocator< std::unique_ptr< amici::ReturnData > > > "Iterable[ReturnData]"; +%typemap(doctype) void "None"; +%typemap(doctype) std::unique_ptr< amici::Solver > "amici.Solver"; +%typemap(doctype) amici::InternalSensitivityMethod "amici.InternalSensitivityMethod"; +%typemap(doctype) amici::InterpolationType "amici.InterpolationType"; +%typemap(doctype) amici::LinearMultistepMethod "amici.LinearMultistepMethod"; +%typemap(doctype) amici::LinearSolver "amici.LinearSolver"; +%typemap(doctype) amici::Model * "amici.Model"; +%typemap(doctype) amici::Model const * "amici.Model"; +%typemap(doctype) amici::NewtonDampingFactorMode "amici.NewtonDampingFactorMode"; +%typemap(doctype) amici::NonlinearSolverIteration "amici.NonlinearSolverIteration"; +%typemap(doctype) amici::RDataReporting "amici.RDataReporting"; +%typemap(doctype) amici::SensitivityMethod "amici.SensitivityMethod"; +%typemap(doctype) amici::SensitivityOrder "amici.SensitivityOrder"; +%typemap(doctype) amici::Solver * "amici.Solver"; +%typemap(doctype) amici::SteadyStateSensitivityMode "amici.SteadyStateSensitivityMode"; +%typemap(doctype) amici::realtype "float"; +%typemap(doctype) DoubleVector "numpy.ndarray"; +%typemap(doctype) IntVector "List[int]"; +%typemap(doctype) std::pair< size_t,size_t > "Tuple[int, int]"; +%typemap(doctype) std::string "str"; +%typemap(doctype) std::string const & "str"; +%typemap(doctype) std::unique_ptr< amici::ExpData > "amici.ExpData"; +%typemap(doctype) std::unique_ptr< amici::ReturnData > "amici.ReturnData"; +%typemap(doctype) size_t "int"; + %include %exception { @@ -189,6 +241,7 @@ RDataReporting = enum('RDataReporting') %template(SteadyStateStatusVector) std::vector; +// Handle AMICI_DLL_DIRS environment variable %pythonbegin %{ import sys import os @@ -199,21 +252,10 @@ if sys.platform == 'win32': %} - -// add module docstring and import additional types for typehints +// import additional types for typehints %pythonbegin %{ -""" -Core C++ bindings ------------------ -This module encompasses the complete public C++ API of AMICI, which was -exposed via swig. All functions listed here are directly accessible in the -main amici package, i.e., :py:class:`amici.amici.ExpData` is available as -``amici.ExpData``. -Usage of functions and classes from the base ``amici`` package is -generally recommended as they often include convenience wrappers that avoid -common pitfalls when accessing C++ types from python and implement some -nonstandard type conversions. -""" - -from typing import Iterable +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from typing import Iterable, List, Tuple + import numpy %} From f81490966e90231b267d1936c3e7e31785d0540b Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 3 Feb 2022 16:39:15 +0100 Subject: [PATCH 08/22] Swig docstrings (#1654) Simplify sphinx conf.py --- documentation/conf.py | 17 ----------------- swig/amici.i | 10 ++++++++++ 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/documentation/conf.py b/documentation/conf.py index 3669c14f07..99dfa29b85 100644 --- a/documentation/conf.py +++ b/documentation/conf.py @@ -514,23 +514,6 @@ def process_docstring(app, what, name, obj, options, lines): ) return - if name == 'amici.amici.StringDoubleMap': - lines.append( - 'Swig-Generated class templating :class:`Dict` ' - '[:class:`str`, :class:`float`] to facilitate' - ' interfacing with C++ bindings.' - ) - return - - if name == 'amici.amici.ParameterScalingVector': - lines.append( - 'Swig-Generated class, which, in contrast to other Vector ' - 'classes, does not allow for simple interoperability with common ' - 'python types, but must be created using ' - ':func:`amici.amici.parameterScalingFromIntVector`' - ) - return - if len(name.split('.')) == 3 and name.split('.')[2] in \ ['ExpDataPtr', 'ReturnDataPtr', 'ModelPtr', 'SolverPtr']: cname = name.split('.')[2] diff --git a/swig/amici.i b/swig/amici.i index cfd3c29c9f..a754cd61b8 100644 --- a/swig/amici.i +++ b/swig/amici.i @@ -82,6 +82,9 @@ import_array(); %template(IntVector) std::vector; %template(BoolVector) std::vector; %template(StringVector) std::vector; +%feature("docstring") std::map +"Swig-Generated class templating :class:`Dict` +[:class:`str`, :class:`float`] to facilitate interfacing with C++ bindings."; %template(StringDoubleMap) std::map; // Let numpy access std::vector @@ -172,6 +175,11 @@ using namespace amici; // 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 +%feature("docstring") parameterScalingFromIntVector +"Swig-Generated class, which, in contrast to other Vector +classes, does not allow for simple interoperability with common +Python types, but must be created using +:func:`amici.amici.parameterScalingFromIntVector`"; %{ namespace amici { std::vector parameterScalingFromIntVector(std::vector const& intVec) { @@ -200,6 +208,8 @@ namespace amici { // Add function to check if amici was compiled with OpenMP +%feature("docstring") compiledWithOpenMP + "AMICI extension was compiled with OpenMP?"; %{ namespace amici { /** AMICI extension was compiled with OpenMP? */ From d6943adfac03c807df575139d0e603dd239b5357 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 4 Feb 2022 15:38:28 +0100 Subject: [PATCH 09/22] Fix special function parsing inside min() and max() (#1655) Fixes a bug where special functions occurring inside min() and max() would not be correctly parsed and import would fail. --- python/amici/import_utils.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/python/amici/import_utils.py b/python/amici/import_utils.py index a4695cb8f8..054b820467 100644 --- a/python/amici/import_utils.py +++ b/python/amici/import_utils.py @@ -335,12 +335,8 @@ def _parse_special_functions(sym: sp.Expr, toplevel: bool = True) -> sp.Expr: # c++ doesnt like mixing int and double for arguments of those # functions if sym.__class__.__name__ in ['min', 'max']: - args = tuple([ - sp.Float(arg) if arg.is_number else arg - for arg in sym.args - ]) - else: - args = sym.args + args = tuple(sp.Float(arg) if arg.is_number else arg + for arg in args) return fun_mappings[sym.__class__.__name__](*args) elif sym.__class__.__name__ == 'piecewise' \ From ea8229d8fd477c7ccc3628e6e6cf3b28b4a19751 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 4 Feb 2022 17:47:29 +0100 Subject: [PATCH 10/22] Outsource numpy requirement (#1657) Let's rely on https://github.com/scipy/oldest-supported-numpy instead of maintaining our own compatibility list. Fixes #1656 --- python/sdist/pyproject.toml | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/python/sdist/pyproject.toml b/python/sdist/pyproject.toml index 6b2b36a78d..82233ba352 100644 --- a/python/sdist/pyproject.toml +++ b/python/sdist/pyproject.toml @@ -2,18 +2,12 @@ requires = [ "setuptools>=40.6.3", "wheel", - # We pin numpy here to the lowest supported version to have - # ABI-compatibility with the numpy version in the runtime environment. - # There seems to be no easy way to require the numpy version from the - # runtime environment for the build requirement here. The only alternative - # would be pinning the setup.py numpy requirement to the same version as - # here, which we want to avoid. + # oldest-supported-numpy helps us to pin numpy here to the lowest supported + # version to have ABI-compatibility with the numpy version in the runtime + # environment. The undesirable alternative would be pinning the setup.py + # numpy requirement to the same version as here, which we want to avoid. # cf. discussion at https://github.com/numpy/numpy/issues/5888 - # See also: - # https://github.com/scipy/oldest-supported-numpy/blob/master/setup.cfg - # https://github.com/h5py/h5py/blob/master/setup.py - "numpy==1.17.5; python_version=='3.8'", - "numpy==1.19.3; python_version=='3.9'", - "numpy==1.21.4; python_version>='3.10'", + # (https://github.com/scipy/oldest-supported-numpy/) + "oldest-supported-numpy", ] build-backend = "setuptools.build_meta" From d532cdb97722a03f21a62cdd49b322e037574ddd Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 7 Feb 2022 18:20:52 +0100 Subject: [PATCH 11/22] Fix: 'sed: illegal option -- -' on OSX (#1658) Not sure why `--regexp-extended` was in there in the first place... --- cmake/version.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/version.cmake b/cmake/version.cmake index 3310c8467c..577594e8f8 100644 --- a/cmake/version.cmake +++ b/cmake/version.cmake @@ -1,6 +1,6 @@ find_package(Git) if(Git_FOUND) - execute_process(COMMAND sh -c "${GIT_EXECUTABLE} describe --abbrev=4 --dirty=-dirty --always --tags | cut -c 2- | tr -d '\n' | sed --regexp-extended s/-/./" + execute_process(COMMAND sh -c "${GIT_EXECUTABLE} describe --abbrev=4 --dirty=-dirty --always --tags | cut -c 2- | tr -d '\n' | sed s/-/./" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE PROJECT_VERSION_GIT ) From 1e19b67481adb745cbb91bf17e928f5820c902cc Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 7 Feb 2022 16:52:54 +0100 Subject: [PATCH 12/22] GHA: Fix apt warning 'WARNING: apt does not have a stable CLI interface. Use with caution in scripts.' --- .github/workflows/test_python_cplusplus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_python_cplusplus.yml b/.github/workflows/test_python_cplusplus.yml index d908c7a647..5e3cf97916 100644 --- a/.github/workflows/test_python_cplusplus.yml +++ b/.github/workflows/test_python_cplusplus.yml @@ -38,7 +38,7 @@ jobs: # TODO: add to ci image - name: Install sonarcloud tools run: | - sudo apt install nodejs curl unzip \ + sudo apt-get install nodejs curl unzip \ && curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip \ https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip \ && unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/ \ From d5480fdcbc9dde49b1871854eb7ece31b832ddaf Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 7 Feb 2022 17:17:38 +0100 Subject: [PATCH 13/22] GHA: Fix Sonarcloud warning by setting python versions > WARN: Your code is analyzed as compatible with python 2 and 3 by default. This will prevent the detection of issues specific to python 2 or python 3. You can get a more precise analysis by setting a python version in your configuration via the parameter "sonar.python.version" --- sonar-project.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/sonar-project.properties b/sonar-project.properties index f376ff3bda..81139fedc4 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -32,3 +32,4 @@ sonar.cfamily.cache.path=sonar_cache sonar.cpp.std=c++14 sonar.python.coverage.reportPaths=build/coverage_py.xml +sonar.python.version=3.8, 3.9, 3.10 From 4e7a55c55eaf57879fdc6bddc5a5ddfe2a085dd0 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 7 Feb 2022 17:29:33 +0100 Subject: [PATCH 14/22] GHA: Update sonar-scanner-cli to 4.6.2.2472 --- .github/workflows/test_python_cplusplus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_python_cplusplus.yml b/.github/workflows/test_python_cplusplus.yml index 5e3cf97916..cb8da194a1 100644 --- a/.github/workflows/test_python_cplusplus.yml +++ b/.github/workflows/test_python_cplusplus.yml @@ -29,7 +29,7 @@ jobs: - run: echo "BNGPATH=${GITHUB_WORKSPACE}/ThirdParty/BioNetGen-2.7.0" >> $GITHUB_ENV # sonar cloud - - run: echo "SONAR_SCANNER_VERSION=4.6.1.2450" >> $GITHUB_ENV + - run: echo "SONAR_SCANNER_VERSION=4.6.2.2472" >> $GITHUB_ENV - run: echo "SONAR_SCANNER_HOME=${HOME}/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux" >> $GITHUB_ENV - run: echo "SONAR_SCANNER_OPTS=-server" >> $GITHUB_ENV - run: echo "${SONAR_SCANNER_HOME}/bin" >> $GITHUB_PATH From 41f1aeeb60366f7ad412b2a516ae3112e72875f6 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 7 Feb 2022 22:25:50 +0100 Subject: [PATCH 15/22] Doc: Debugging AMICI extensions (#1659) Some information on how to potentially debug amici python extensions. --- documentation/debugging.rst | 65 +++++++++++++++++++++++++++++++++++ documentation/development.rst | 1 + 2 files changed, 66 insertions(+) create mode 100644 documentation/debugging.rst diff --git a/documentation/debugging.rst b/documentation/debugging.rst new file mode 100644 index 0000000000..a9386f4a12 --- /dev/null +++ b/documentation/debugging.rst @@ -0,0 +1,65 @@ +Debugging AMICI +=============== + +This document contains some information on how to debug any issues in AMICI, +in particular for C++ Python extensions. + +Caveman debugging / printf-debugging +------------------------------------ + +The simplest approach may often be adding some print-statements to the code, +as this does not require any special tools. + +Note that after each change of the C++ files, the AMICI extension *as well as +the model extension* (if any model functions are called), need to be +recompiled. +The simplest and safest approach would be re-installation of the amici package +and re-import of the model. As this can be very time-consuming, the following +shortcut is possible, assuming you are using a development installation +(``pip install -e ...``): + +.. code-block:: shell + + # rebuild the amici base extension, from within the amici root directory + # (note that this only recompiles the amici source files, NOT third-party + # dependencies such as sundials): + cd python/sdist/ + python setup.py build_ext --build-lib . + + # rebuild the model, from within the model package directory: + python setup.py build_ext --force --build-lib . + +Note: Be careful when working interactively, Python may not pick up any changes +in already imported modules. The safest is to start a new Python process after +any changes. + + +Using a proper debugger +----------------------- + +Debugging with with [gdb](https://www.sourceware.org/gdb/) is most convenient +with a minimal reproducible example that is directly invoked from gdb. +For example: + +.. code-block:: shell + + # start gdb + gdb --args python -m pytest ../tests/test_sbml_import.py::test_nosensi + + # inside gdb, set a meaningful breakpoint and launch: + break amici::runAmiciSimulation + run + # ... (see one of the many gdb tutorials) + +Alternative, gdb can attach to a running process by passing the ``--pid`` +argument. + +For many users, it may be more convenient to use gdb via some graphical user +interface as provided by various C++ IDEs. + +.. note:: + + For better debugging experience, but at the cost of runtime performance, + consider building the amici and model extension with environment variable + ``ENABLE_AMICI_DEBUGGING=TRUE``. This will include debugging symbols and + disable compiler optimizations. diff --git a/documentation/development.rst b/documentation/development.rst index 365da13c67..2b6bd563e8 100644 --- a/documentation/development.rst +++ b/documentation/development.rst @@ -158,3 +158,4 @@ Further topics Organization of the documentation code_review_guide CI + debugging From 58f9a14d0cdde3e971c9680e60f4a2acdbd1fed0 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Tue, 8 Feb 2022 10:23:22 +0100 Subject: [PATCH 16/22] Update CMake policies (#1665) * cmake_policy(SET CMP0078 NEW) Fixes #1660 * cmake: Remove obsolete cmake_policy(SET CMP0065 NEW) This is already implied by cmake_minimum_required(VERSION 3.8) * Regenerate matlab models --- CMakeLists.txt | 3 --- models/model_calvetti/CMakeLists.txt | 7 +++++-- models/model_calvetti/model_calvetti.h | 4 ++-- models/model_calvetti/swig/CMakeLists.txt | 6 +++--- models/model_dirac/CMakeLists.txt | 7 +++++-- models/model_dirac/model_dirac.h | 4 ++-- models/model_dirac/swig/CMakeLists.txt | 6 +++--- models/model_events/CMakeLists.txt | 7 +++++-- models/model_events/model_events.h | 4 ++-- models/model_events/swig/CMakeLists.txt | 6 +++--- models/model_jakstat_adjoint/CMakeLists.txt | 7 +++++-- models/model_jakstat_adjoint/model_jakstat_adjoint.h | 4 ++-- models/model_jakstat_adjoint/swig/CMakeLists.txt | 6 +++--- models/model_jakstat_adjoint_o2/CMakeLists.txt | 7 +++++-- models/model_jakstat_adjoint_o2/model_jakstat_adjoint_o2.h | 4 ++-- models/model_jakstat_adjoint_o2/swig/CMakeLists.txt | 6 +++--- models/model_nested_events/CMakeLists.txt | 7 +++++-- models/model_nested_events/model_nested_events.h | 4 ++-- models/model_nested_events/swig/CMakeLists.txt | 6 +++--- models/model_neuron/CMakeLists.txt | 7 +++++-- models/model_neuron/model_neuron.h | 4 ++-- models/model_neuron/swig/CMakeLists.txt | 6 +++--- models/model_neuron_o2/CMakeLists.txt | 7 +++++-- models/model_neuron_o2/model_neuron_o2.h | 4 ++-- models/model_neuron_o2/swig/CMakeLists.txt | 6 +++--- models/model_robertson/CMakeLists.txt | 7 +++++-- models/model_robertson/model_robertson.h | 4 ++-- models/model_robertson/swig/CMakeLists.txt | 6 +++--- models/model_steadystate/CMakeLists.txt | 7 +++++-- models/model_steadystate/model_steadystate.h | 4 ++-- models/model_steadystate/swig/CMakeLists.txt | 6 +++--- swig/CMakeLists_model.cmake | 6 +++--- 32 files changed, 103 insertions(+), 76 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ae3b9d90d..197a7f65b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,9 +3,6 @@ # cmake_minimum_required(VERSION 3.3) -if(POLICY CMP0065) - cmake_policy(SET CMP0065 NEW) -endif(POLICY CMP0065) if(POLICY CMP0077) cmake_policy(SET CMP0077 NEW) endif(POLICY CMP0077) diff --git a/models/model_calvetti/CMakeLists.txt b/models/model_calvetti/CMakeLists.txt index 4832c49537..92f8855945 100644 --- a/models/model_calvetti/CMakeLists.txt +++ b/models/model_calvetti/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_calvetti/model_calvetti.h b/models/model_calvetti/model_calvetti.h index 0a326de31e..27fad45d3e 100644 --- a/models/model_calvetti/model_calvetti.h +++ b/models/model_calvetti/model_calvetti.h @@ -1,6 +1,6 @@ #ifndef _amici_model_calvetti_h #define _amici_model_calvetti_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -67,7 +67,7 @@ class Model_model_calvetti : public amici::Model_DAE { amici::Model* clone() const override { return new Model_model_calvetti(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype cj, const realtype *dx, const realtype *w, const realtype *dwdx) override { JSparse_model_calvetti(JSparse, t, x, p, k, h, cj, dx, w, dwdx); diff --git a/models/model_calvetti/swig/CMakeLists.txt b/models/model_calvetti/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_calvetti/swig/CMakeLists.txt +++ b/models/model_calvetti/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_dirac/CMakeLists.txt b/models/model_dirac/CMakeLists.txt index 58c689a924..068563d6ae 100644 --- a/models/model_dirac/CMakeLists.txt +++ b/models/model_dirac/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_dirac/model_dirac.h b/models/model_dirac/model_dirac.h index 2eb5cdb4bd..481522b282 100644 --- a/models/model_dirac/model_dirac.h +++ b/models/model_dirac/model_dirac.h @@ -1,6 +1,6 @@ #ifndef _amici_model_dirac_h #define _amici_model_dirac_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -67,7 +67,7 @@ class Model_model_dirac : public amici::Model_ODE { amici::Model* clone() const override { return new Model_model_dirac(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { JSparse_model_dirac(JSparse, t, x, p, k, h, w, dwdx); diff --git a/models/model_dirac/swig/CMakeLists.txt b/models/model_dirac/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_dirac/swig/CMakeLists.txt +++ b/models/model_dirac/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_events/CMakeLists.txt b/models/model_events/CMakeLists.txt index 9ba9427067..314de61be1 100644 --- a/models/model_events/CMakeLists.txt +++ b/models/model_events/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_events/model_events.h b/models/model_events/model_events.h index 2cf13ace87..56e90327e4 100644 --- a/models/model_events/model_events.h +++ b/models/model_events/model_events.h @@ -1,6 +1,6 @@ #ifndef _amici_model_events_h #define _amici_model_events_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -81,7 +81,7 @@ class Model_model_events : public amici::Model_ODE { amici::Model* clone() const override { return new Model_model_events(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { JSparse_model_events(JSparse, t, x, p, k, h, w, dwdx); diff --git a/models/model_events/swig/CMakeLists.txt b/models/model_events/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_events/swig/CMakeLists.txt +++ b/models/model_events/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_jakstat_adjoint/CMakeLists.txt b/models/model_jakstat_adjoint/CMakeLists.txt index fe9f38b9ca..9e0f8693ec 100644 --- a/models/model_jakstat_adjoint/CMakeLists.txt +++ b/models/model_jakstat_adjoint/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_jakstat_adjoint/model_jakstat_adjoint.h b/models/model_jakstat_adjoint/model_jakstat_adjoint.h index ce4eb29b7b..418acbf2f5 100644 --- a/models/model_jakstat_adjoint/model_jakstat_adjoint.h +++ b/models/model_jakstat_adjoint/model_jakstat_adjoint.h @@ -1,6 +1,6 @@ #ifndef _amici_model_jakstat_adjoint_h #define _amici_model_jakstat_adjoint_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -70,7 +70,7 @@ class Model_model_jakstat_adjoint : public amici::Model_ODE { amici::Model* clone() const override { return new Model_model_jakstat_adjoint(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { JSparse_model_jakstat_adjoint(JSparse, t, x, p, k, h, w, dwdx); diff --git a/models/model_jakstat_adjoint/swig/CMakeLists.txt b/models/model_jakstat_adjoint/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_jakstat_adjoint/swig/CMakeLists.txt +++ b/models/model_jakstat_adjoint/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_jakstat_adjoint_o2/CMakeLists.txt b/models/model_jakstat_adjoint_o2/CMakeLists.txt index a37600c51c..76f52619ac 100644 --- a/models/model_jakstat_adjoint_o2/CMakeLists.txt +++ b/models/model_jakstat_adjoint_o2/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_jakstat_adjoint_o2/model_jakstat_adjoint_o2.h b/models/model_jakstat_adjoint_o2/model_jakstat_adjoint_o2.h index 273de3a97a..33a5beb306 100644 --- a/models/model_jakstat_adjoint_o2/model_jakstat_adjoint_o2.h +++ b/models/model_jakstat_adjoint_o2/model_jakstat_adjoint_o2.h @@ -1,6 +1,6 @@ #ifndef _amici_model_jakstat_adjoint_o2_h #define _amici_model_jakstat_adjoint_o2_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -70,7 +70,7 @@ class Model_model_jakstat_adjoint_o2 : public amici::Model_ODE { amici::Model* clone() const override { return new Model_model_jakstat_adjoint_o2(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { JSparse_model_jakstat_adjoint_o2(JSparse, t, x, p, k, h, w, dwdx); diff --git a/models/model_jakstat_adjoint_o2/swig/CMakeLists.txt b/models/model_jakstat_adjoint_o2/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_jakstat_adjoint_o2/swig/CMakeLists.txt +++ b/models/model_jakstat_adjoint_o2/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_nested_events/CMakeLists.txt b/models/model_nested_events/CMakeLists.txt index af4214b975..67e62cd7c8 100644 --- a/models/model_nested_events/CMakeLists.txt +++ b/models/model_nested_events/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_nested_events/model_nested_events.h b/models/model_nested_events/model_nested_events.h index ceab6cb1a7..8f85951440 100644 --- a/models/model_nested_events/model_nested_events.h +++ b/models/model_nested_events/model_nested_events.h @@ -1,6 +1,6 @@ #ifndef _amici_model_nested_events_h #define _amici_model_nested_events_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -70,7 +70,7 @@ class Model_model_nested_events : public amici::Model_ODE { amici::Model* clone() const override { return new Model_model_nested_events(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { JSparse_model_nested_events(JSparse, t, x, p, k, h, w, dwdx); diff --git a/models/model_nested_events/swig/CMakeLists.txt b/models/model_nested_events/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_nested_events/swig/CMakeLists.txt +++ b/models/model_nested_events/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_neuron/CMakeLists.txt b/models/model_neuron/CMakeLists.txt index 8af91c20a5..1dc56d5ffe 100644 --- a/models/model_neuron/CMakeLists.txt +++ b/models/model_neuron/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_neuron/model_neuron.h b/models/model_neuron/model_neuron.h index 3aaeb06a48..bd12dd9b5d 100644 --- a/models/model_neuron/model_neuron.h +++ b/models/model_neuron/model_neuron.h @@ -1,6 +1,6 @@ #ifndef _amici_model_neuron_h #define _amici_model_neuron_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -84,7 +84,7 @@ class Model_model_neuron : public amici::Model_ODE { amici::Model* clone() const override { return new Model_model_neuron(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { JSparse_model_neuron(JSparse, t, x, p, k, h, w, dwdx); diff --git a/models/model_neuron/swig/CMakeLists.txt b/models/model_neuron/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_neuron/swig/CMakeLists.txt +++ b/models/model_neuron/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_neuron_o2/CMakeLists.txt b/models/model_neuron_o2/CMakeLists.txt index 07eea135a0..ca9d1e1794 100644 --- a/models/model_neuron_o2/CMakeLists.txt +++ b/models/model_neuron_o2/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_neuron_o2/model_neuron_o2.h b/models/model_neuron_o2/model_neuron_o2.h index 79904d7714..d1d2fc1734 100644 --- a/models/model_neuron_o2/model_neuron_o2.h +++ b/models/model_neuron_o2/model_neuron_o2.h @@ -1,6 +1,6 @@ #ifndef _amici_model_neuron_o2_h #define _amici_model_neuron_o2_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -86,7 +86,7 @@ class Model_model_neuron_o2 : public amici::Model_ODE { amici::Model* clone() const override { return new Model_model_neuron_o2(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { JSparse_model_neuron_o2(JSparse, t, x, p, k, h, w, dwdx); diff --git a/models/model_neuron_o2/swig/CMakeLists.txt b/models/model_neuron_o2/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_neuron_o2/swig/CMakeLists.txt +++ b/models/model_neuron_o2/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_robertson/CMakeLists.txt b/models/model_robertson/CMakeLists.txt index 0c61375775..92be289a22 100644 --- a/models/model_robertson/CMakeLists.txt +++ b/models/model_robertson/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_robertson/model_robertson.h b/models/model_robertson/model_robertson.h index 9e3c40f297..a83d68d8d7 100644 --- a/models/model_robertson/model_robertson.h +++ b/models/model_robertson/model_robertson.h @@ -1,6 +1,6 @@ #ifndef _amici_model_robertson_h #define _amici_model_robertson_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -68,7 +68,7 @@ class Model_model_robertson : public amici::Model_DAE { amici::Model* clone() const override { return new Model_model_robertson(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype cj, const realtype *dx, const realtype *w, const realtype *dwdx) override { JSparse_model_robertson(JSparse, t, x, p, k, h, cj, dx, w, dwdx); diff --git a/models/model_robertson/swig/CMakeLists.txt b/models/model_robertson/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_robertson/swig/CMakeLists.txt +++ b/models/model_robertson/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/models/model_steadystate/CMakeLists.txt b/models/model_steadystate/CMakeLists.txt index 20d2f4b3db..b82e866169 100644 --- a/models/model_steadystate/CMakeLists.txt +++ b/models/model_steadystate/CMakeLists.txt @@ -18,10 +18,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(CheckCXXCompilerFlag) -set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() foreach(FLAG ${MY_CXX_FLAGS}) unset(CUR_FLAG_SUPPORTED CACHE) - CHECK_CXX_COMPILER_FLAG(${FLAG} CUR_FLAG_SUPPORTED) + CHECK_CXX_COMPILER_FLAG(-Werror ${FLAG} CUR_FLAG_SUPPORTED) if(${CUR_FLAG_SUPPORTED}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() diff --git a/models/model_steadystate/model_steadystate.h b/models/model_steadystate/model_steadystate.h index c009c86cab..0da7d77631 100644 --- a/models/model_steadystate/model_steadystate.h +++ b/models/model_steadystate/model_steadystate.h @@ -1,6 +1,6 @@ #ifndef _amici_model_steadystate_h #define _amici_model_steadystate_h -/* Generated by amiwrap (R2017b) 2bd39716102b9842354964196889d40d2eb2731c */ +/* Generated by amiwrap (R2017b) dc99fa1bcb04914008ba8ed39157513d443c3f43 */ #include #include #include "amici/defines.h" @@ -67,7 +67,7 @@ class Model_model_steadystate : public amici::Model_ODE { amici::Model* clone() const override { return new Model_model_steadystate(*this); }; - std::string getAmiciCommit() const override { return "2bd39716102b9842354964196889d40d2eb2731c"; }; + std::string getAmiciCommit() const override { return "dc99fa1bcb04914008ba8ed39157513d443c3f43"; }; void fJSparse(SUNMatrixContent_Sparse JSparse, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { JSparse_model_steadystate(JSparse, t, x, p, k, h, w, dwdx); diff --git a/models/model_steadystate/swig/CMakeLists.txt b/models/model_steadystate/swig/CMakeLists.txt index af0f64a76e..c2163cf173 100644 --- a/models/model_steadystate/swig/CMakeLists.txt +++ b/models/model_steadystate/swig/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) diff --git a/swig/CMakeLists_model.cmake b/swig/CMakeLists_model.cmake index af0f64a76e..c2163cf173 100644 --- a/swig/CMakeLists_model.cmake +++ b/swig/CMakeLists_model.cmake @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.8) # swig_add_library if(POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 NEW) endif(POLICY CMP0078) if(POLICY CMP0074) # Use package_ROOT environment variables @@ -32,12 +32,12 @@ set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) include_directories(${AMICI_INCLUDE_DIRS} ..) -swig_add_library(${PROJECT_NAME} +swig_add_library(${SWIG_LIBRARY_NAME} TYPE MODULE LANGUAGE python SOURCES ${PROJECT_NAME}.i) -swig_link_libraries(${PROJECT_NAME} +swig_link_libraries(${SWIG_LIBRARY_NAME} ${Python3_LIBRARIES} model) From e6ab2bc44a4dd0531df3253dc6d002660c291042 Mon Sep 17 00:00:00 2001 From: Polina Lakrisenko Date: Tue, 8 Feb 2022 14:09:08 +0100 Subject: [PATCH 17/22] Fix convergence check in Newton method (#1663) Fixes a bug where the Newton solver and potentially simulation would run longer than necessary (introduced in https://github.com/AMICI-dev/AMICI/pull/446 / edf7d5b8f56d69559bc3d1a009086c2f334a3c62). Also saves some memory (2 * nx_solver^2). > It seems that the value of `x_newton_` in `SteadystateProblem::applyNewtonsMethod`([applyNewtonsMethod](https://github.com/AMICI-dev/AMICI/blob/82d2cbb9d00ac9c3746b4e85c0fb1d6ebbff2863/src/steadystateproblem.cpp#L490)) doesn't change, but it's used to compute weighted root mean square of `xdot` and, therefore, is used to check convergence. As a result, convergence of Newton's method is achieved only due to `xdot_` becoming sufficiently small. For two models that require postequilibration I've observed simulations that finished with `posteq_status = [-4 1 0]`and `posteq_numstep = [0 0 0]`, i.e. Newton's method didn't converge, but the check here https://github.com/AMICI-dev/AMICI/blob/82d2cbb9d00ac9c3746b4e85c0fb1d6ebbff2863/src/steadystateproblem.cpp#L614 returned True and the simulation was considered successful with zero steps. Changing `x_newton_` to `x_` fixes the issue. * use x_ instead of x_newton_ for residuals computation * fix typos * Remove unused `SteadystateProblem::x_newton_` and `SteadystateProblem::rel_x_newton_` --- include/amici/solver.h | 2 +- include/amici/steadystateproblem.h | 4 ---- src/backwardproblem.cpp | 2 +- src/steadystateproblem.cpp | 9 ++++----- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/include/amici/solver.h b/include/amici/solver.h index 1c15a1afb3..3c39fd4789 100644 --- a/include/amici/solver.h +++ b/include/amici/solver.h @@ -632,7 +632,7 @@ class Solver { AmiVectorArray &sx, AmiVector &xQ) const; /** - * @brief write solution from forward simulation + * @brief write solution from backward simulation * @param t time * @param xB adjoint state * @param dxB adjoint derivative state diff --git a/include/amici/steadystateproblem.h b/include/amici/steadystateproblem.h index 550433e797..b59eeb404c 100644 --- a/include/amici/steadystateproblem.h +++ b/include/amici/steadystateproblem.h @@ -353,10 +353,6 @@ class SteadystateProblem { AmiVector ewt_; /** error weights for backward quadratures, dimension nplist() */ AmiVector ewtQB_; - /** container for relative error calculation? */ - AmiVector rel_x_newton_; - /** container for absolute error calculation? */ - AmiVector x_newton_; /** state vector */ AmiVector x_; /** old state vector */ diff --git a/src/backwardproblem.cpp b/src/backwardproblem.cpp index 495837ea1b..b9c7c7d43f 100644 --- a/src/backwardproblem.cpp +++ b/src/backwardproblem.cpp @@ -31,7 +31,7 @@ BackwardProblem::BackwardProblem(const ForwardProblem &fwd, root_idx_(fwd.getRootIndexes()), dJydx_(fwd.getDJydx()), dJzdx_(fwd.getDJzdx()) { - /* complement dJydx from postequilibration. This should overwrite + /* complement dJydx from postequilibration. This shouldn't overwrite * anything but only fill in previously 0 values, as only non-inf * timepoints are filled from fwd. */ diff --git a/src/steadystateproblem.cpp b/src/steadystateproblem.cpp index 2c23abdaf1..d7c3850e64 100644 --- a/src/steadystateproblem.cpp +++ b/src/steadystateproblem.cpp @@ -20,7 +20,6 @@ namespace amici { SteadystateProblem::SteadystateProblem(const Solver &solver, const Model &model) : delta_(model.nx_solver), ewt_(model.nx_solver), ewtQB_(model.nplist()), - rel_x_newton_(model.nx_solver), x_newton_(model.nx_solver), x_(model.nx_solver), x_old_(model.nx_solver), dx_(model.nx_solver), xdot_(model.nx_solver), xdot_old_(model.nx_solver), sx_(model.nx_solver, model.nplist()), sdx_(model.nx_solver, model.nplist()), @@ -505,11 +504,10 @@ void SteadystateProblem::applyNewtonsMethod(Model *model, /* Check for relative error, but make sure not to divide by 0! Ensure positivity of the state */ - x_newton_ = x_; x_old_ = x_; xdot_old_ = xdot_; - wrms_ = getWrmsNorm(x_newton_, xdot_, newtonSolver->atol_, + wrms_ = getWrmsNorm(x_, xdot_, newtonSolver->atol_, newtonSolver->rtol_, ewt_); bool converged = newton_retry ? false : wrms_ < RCONST(1.0); while (!converged && i_newtonstep < newtonSolver->max_steps) { @@ -530,7 +528,7 @@ void SteadystateProblem::applyNewtonsMethod(Model *model, /* Compute new xdot and residuals */ model->fxdot(t_, x_, dx_, xdot_); - realtype wrms_tmp = getWrmsNorm(x_newton_, xdot_, newtonSolver->atol_, + realtype wrms_tmp = getWrmsNorm(x_, xdot_, newtonSolver->atol_, newtonSolver->rtol_, ewt_); if (wrms_tmp < wrms_) { @@ -555,7 +553,7 @@ void SteadystateProblem::applyNewtonsMethod(Model *model, } if (recheck_convergence) { model->fxdot(t_, x_, dx_, xdot_); - wrms_ = getWrmsNorm(x_newton_, xdot_, newtonSolver->atol_, + wrms_ = getWrmsNorm(x_, xdot_, newtonSolver->atol_, newtonSolver->rtol_, ewt_); converged = wrms_ < RCONST(1.0); } @@ -611,6 +609,7 @@ void SteadystateProblem::runSteadystateSimulation(const Solver *solver, if (backward) sensitivityFlag = SensitivityMethod::adjoint; + /* If run after Newton's method checks again if it converged */ bool converged = checkConvergence(solver, model, sensitivityFlag); int sim_steps = 0; From 5032868d4cfdccc811229c83456a4c65cf5f5df4 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 7 Feb 2022 21:40:00 +0100 Subject: [PATCH 18/22] cmake: Remove stray set(ENABLE_SWIG) --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 197a7f65b2..cfaa6e4324 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,6 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") endif() endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(ENABLE_SWIG ON) # Compiler flags include(CheckCXXCompilerFlag) From 7728b150b663130280e1583f16801bbe7700a904 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 7 Feb 2022 21:54:19 +0100 Subject: [PATCH 19/22] cmake: Add AMICI_CXX_OPTIONS variable for libamici-specific compiler options --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cfaa6e4324..423b156773 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,8 @@ if(ENABLE_HDF5) endif() add_library(${PROJECT_NAME} ${AMICI_SRC_LIST}) +set(AMICI_CXX_OPTIONS "" CACHE STRING "C++ options for libamici (semicolon-separated)") +target_compile_options(${PROJECT_NAME} PRIVATE "${AMICI_CXX_OPTIONS}") add_dependencies(${PROJECT_NAME} version) file(GLOB PUBLIC_HEADERS include/amici/*.h) set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "${PUBLIC_HEADERS}") From ee1f445b4d7ce2b6416cf632229055f046a9be2e Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 7 Feb 2022 21:56:07 +0100 Subject: [PATCH 20/22] Use -Werror only for AMICI_CXX_OPTIONS, not CMAKE_CXX_FLAGS Closes #1661 --- scripts/buildAmici.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/buildAmici.sh b/scripts/buildAmici.sh index 735e05fd3b..2d40d3cb08 100755 --- a/scripts/buildAmici.sh +++ b/scripts/buildAmici.sh @@ -23,7 +23,7 @@ else fi ${cmake} \ - -DCMAKE_CXX_FLAGS="-Wall -Wextra -Werror" \ + -DAMICI_CXX_OPTIONS="-Wall;-Wextra;-Werror" \ -DCMAKE_BUILD_TYPE=$build_type \ -DPython3_EXECUTABLE="$(command -v python3)" .. From 38fb88dee4e23ffee5aacd1b40c93f0300093fc9 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 9 Feb 2022 10:19:06 +0100 Subject: [PATCH 21/22] doc: Fix some formatting issues and typos (#1667) and add cross-references. --- python/amici/ode_export.py | 204 ++++++++++++++++--------------------- python/amici/pandas.py | 10 +- 2 files changed, 91 insertions(+), 123 deletions(-) diff --git a/python/amici/ode_export.py b/python/amici/ode_export.py index 7e574203a9..48594f55c2 100644 --- a/python/amici/ode_export.py +++ b/python/amici/ode_export.py @@ -6,7 +6,7 @@ directly call any function from this module as this will be done by :py:func:`amici.pysb_import.pysb2amici`, :py:func:`amici.sbml_import.SbmlImporter.sbml2amici` and -:py:func:`amici.petab_import.import_model` +:py:func:`amici.petab_import.import_model`. """ import sympy as sp import numpy as np @@ -435,7 +435,7 @@ def set_val(self, val: sp.Expr): class State(ModelQuantity): """ A State variable defines an entity that evolves with time according to - the provided time derivative, abbreviated by `x` + the provided time derivative, abbreviated by ``x``. :ivar _conservation_law: algebraic formula that allows computation of this @@ -456,7 +456,7 @@ def __init__(self, dt: sp.Expr): """ Create a new State instance. Extends :meth:`ModelQuantity.__init__` - by dt + by ``dt`` :param identifier: unique identifier of the state @@ -477,9 +477,10 @@ def __init__(self, def set_conservation_law(self, law: sp.Expr) -> None: """ - Sets the conservation law of a state. If the a conservation law - is set, the respective state will be replaced by an algebraic - formula according to the respective conservation law. + Sets the conservation law of a state. + + If a conservation law is set, the respective state will be replaced by + an algebraic formula according to the respective conservation law. :param law: linear sum of states that if added to this state remain @@ -548,7 +549,7 @@ def __init__(self, class Observable(ModelQuantity): """ An Observable links model simulations to experimental measurements, - abbreviated by `y` + abbreviated by ``y``. :ivar _measurement_symbol: sympy symbol used in the objective function to represent @@ -600,7 +601,7 @@ class SigmaY(ModelQuantity): """ A Standard Deviation SigmaY rescales the distance between simulations and measurements when computing residuals or objective functions, - abbreviated by `sigmay` + abbreviated by ``sigmay``. """ def __init__(self, identifier: sp.Symbol, @@ -624,10 +625,10 @@ def __init__(self, class Expression(ModelQuantity): """ - An Expressions is a recurring elements in symbolic formulas. Specifying + An Expression is a recurring elements in symbolic formulas. Specifying this may yield more compact expression which may lead to substantially - shorter model compilation times, but may also reduce model simulation time, - abbreviated by `w` + shorter model compilation times, but may also reduce model simulation time. + Abbreviated by ``w``. """ def __init__(self, identifier: sp.Symbol, @@ -651,7 +652,7 @@ def __init__(self, class Parameter(ModelQuantity): """ A Parameter is a free variable in the model with respect to which - sensitivities may be computed, abbreviated by `p` + sensitivities may be computed, abbreviated by ``p``. """ def __init__(self, @@ -677,7 +678,7 @@ def __init__(self, class Constant(ModelQuantity): """ A Constant is a fixed variable in the model with respect to which - sensitivities cannot be computed, abbreviated by `k` + sensitivities cannot be computed, abbreviated by ``k``. """ def __init__(self, @@ -704,7 +705,7 @@ class LogLikelihood(ModelQuantity): A LogLikelihood defines the distance between measurements and experiments for a particular observable. The final LogLikelihood value in the simulation will be the sum of all specified LogLikelihood - instances evaluated at all timepoints, abbreviated by `Jy` + instances evaluated at all timepoints, abbreviated by ``Jy``. """ def __init__(self, @@ -719,7 +720,7 @@ def __init__(self, :param name: individual name of the LogLikelihood (does not need to be - unique) + unique) :param value: formula @@ -731,9 +732,9 @@ class Event(ModelQuantity): """ An Event defines either a SBML event or a root of the argument of a Heaviside function. The Heaviside functions will be tracked via the - vector `h` during simulation and are needed to inform the ODE solver about - a discontinuity in either the right hand side or the states themselves, - causing a reinitialization of the solver. + vector ``h`` during simulation and are needed to inform the ODE solver + about a discontinuity in either the right-hand side or the states + themselves, causing a reinitialization of the solver. """ def __init__(self, @@ -770,7 +771,7 @@ def __init__(self, def __eq__(self, other): """ Check equality of events at the level of trigger/root functions, as we - need to collect unique root functions for roots.cpp + need to collect unique root functions for ``roots.cpp`` """ return self.get_val() == other.get_val() @@ -850,9 +851,9 @@ def smart_is_zero_matrix(x: Union[sp.MutableDenseMatrix, class ODEModel: """ Defines an Ordinary Differential Equation as set of ModelQuantities. - This class provides general purpose interfaces to ompute arbitrary + This class provides general purpose interfaces to compute arbitrary symbolic derivatives that are necessary for model simulation or - sensitivity computation + sensitivity computation. :ivar _states: list of state variables @@ -909,11 +910,11 @@ class ODEModel: :ivar _colptrs: carries column pointers for sparsified variables. See - SUNMatrixContent_Sparse definition in + SUNMatrixContent_Sparse definition in ``sunmatrix/sunmatrix_sparse.h`` :ivar _rowvals: carries row values for sparsified variables. See - SUNMatrixContent_Sparse definition in + SUNMatrixContent_Sparse definition in ``sunmatrix/sunmatrix_sparse.h`` :ivar _equation_prototype: defines the attribute from which an equation should be generated via @@ -1053,8 +1054,7 @@ def import_from_sbml_importer( ) -> None: """ Imports a model specification from a - :class:`amici.sbml_import.SbmlImporter` - instance. + :class:`amici.sbml_import.SbmlImporter` instance. :param si: imported SBML model @@ -1224,26 +1224,27 @@ def add_conservation_law(self, abundance_expr: sp.Expr) -> None: """ Adds a new conservation law to the model. A conservation law is defined - by the conserved quantity T = sum_i(a_i * x_i), where a_i are - coefficients and x_i are different state variables. + by the conserved quantity :math:`T = \sum_i(a_i * x_i)`, where + :math:`a_i` are coefficients and :math:`x_i` are different state + variables. :param state: symbolic identifier of the state that should be replaced by - the conservation law (x_j) + the conservation law (:math:`x_j`) :param total_abundance: - symbolic identifier of the total abundance (T/a_j) + symbolic identifier of the total abundance (:math:`T/a_j`) :param state_expr: - symbolic algebraic formula that replaces the the state. This is - used to compute the numeric value of of `state` during simulations. - x_j = T/a_j - sum_i≠j(a_i * x_i)/a_j + symbolic algebraic formula that replaces the state. This is + used to compute the numeric value of ``state`` during simulations. + :math:`x_j = T/a_j - \sum_{i≠j}(a_i * x_i)/a_j` :param abundance_expr: symbolic algebraic formula that computes the value of the conserved quantity. This is used to update the numeric value for - `total_abundance` after (re-)initialization. - T/a_j = sum_i≠j(a_i * x_i)/a_j + x_j + ``total_abundance`` after (re-)initialization. + :math:`T/a_j = \sum_{i≠j}(a_i * x_i)/a_j + x_j` """ try: ix = [ @@ -1401,7 +1402,6 @@ def sparsesym(self, name: str, force_generate: bool = True) -> List[str]: :return: linearized Matrix containing the symbolic identifiers - """ if name not in sparse_functions: raise ValueError(f'{name} is not marked as sparse') @@ -1436,7 +1436,6 @@ def sparseeq(self, name) -> sp.Matrix: :return: linearized matrix containing the symbolic formulas - """ if name not in sparse_functions: raise ValueError(f'{name} is not marked as sparse') @@ -1455,7 +1454,6 @@ def colptrs(self, name: str) -> Union[List[sp.Number], :return: list containing the column pointers - """ if name not in sparse_functions: raise ValueError(f'{name} is not marked as sparse') @@ -1474,7 +1472,6 @@ def rowvals(self, name: str) -> Union[List[sp.Number], :return: list containing the row values - """ if name not in sparse_functions: raise ValueError(f'{name} is not marked as sparse') @@ -1492,7 +1489,6 @@ def val(self, name: str) -> List[float]: :return: list containing the numeric values - """ if name not in self._vals: self._generate_value(name) @@ -1515,7 +1511,7 @@ def name(self, name: str) -> List[str]: def free_symbols(self) -> Set[sp.Basic]: """ - Returns list of free symbols that appear in ODE rhs and initial + Returns list of free symbols that appear in ODE RHS and initial conditions. """ return set(chain.from_iterable( @@ -1529,7 +1525,6 @@ def _generate_symbol(self, name: str, *, from_sbml: bool = False) -> None: :param name: name of the symbolic variable - """ if name in self._variable_prototype: component = self._variable_prototype[name] @@ -1598,7 +1593,7 @@ def _generate_symbol(self, name: str, *, from_sbml: bool = False) -> None: def generate_basic_variables(self, *, from_sbml: bool = False) -> None: """ Generates the symbolic identifiers for all variables in - ODEModel.variable_prototype + ``ODEModel._variable_prototype`` :param from_sbml: whether the model is generated from SBML @@ -1615,12 +1610,12 @@ def generate_basic_variables(self, *, from_sbml: bool = False) -> None: def parse_events(self) -> None: """ - This functions checks the right hand side for roots of Heaviside + This function checks the right-hand side for roots of Heaviside functions or events, collects the roots, removes redundant roots, and replaces the formulae of the found roots by identifiers of AMICI's - Heaviside function implementation in the right hand side + Heaviside function implementation in the right-hand side """ - # Track all roots functions in the right hand side + # Track all roots functions in the right-hand side roots = copy.deepcopy(self._events) for state in self._states: state.set_dt(self._process_heavisides(state.get_dt(), roots)) @@ -1652,7 +1647,6 @@ def get_appearance_counts(self, idxs: List[int]) -> List[int]: :return: list of counts for the states ordered according to the provided indices - """ free_symbols_dt = list(itertools.chain.from_iterable( [ @@ -1685,7 +1679,6 @@ def _generate_sparse_symbol(self, name: str) -> None: :param name: name of the symbolic variable - """ matrix = self.eq(name) match_deriv = re.match(r'd([\w]+)d([a-z]+)', name) @@ -1725,11 +1718,10 @@ def _generate_sparse_symbol(self, name: str) -> None: def _compute_equation(self, name: str) -> None: """ - computes the symbolic formula for a symbolic variable + Computes the symbolic formula for a symbolic variable :param name: name of the symbolic variable - """ # replacement ensures that we don't have to adapt name in abstract # model and keep backwards compatibility with matlab @@ -1837,7 +1829,7 @@ 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 + # 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 = \ @@ -1948,10 +1940,8 @@ def sym_names(self) -> List[str]: """ Returns a list of names of generated symbolic variables - :return: list of names - """ return list(self._syms.keys()) @@ -1967,7 +1957,7 @@ def _derivative(self, eq: str, var: str, name: str = None) -> None: with respect to which the derivatives are to be computed :param name: - name of resulting symbolic variable, default is d{eq}d{var} + name of resulting symbolic variable, default is ``d{eq}d{var}`` """ if not name: name = f'd{eq}d{var}' @@ -2065,18 +2055,17 @@ def _total_derivative(self, name: str, eq: str, chainvars: List[str], :param var: name of the symbolic variable that defines the identifiers - whith respect to which the derivatives are to be computed + with respect to which the derivatives are to be computed :param dydx_name: defines the name of the symbolic variable that - defines the derivative of the `eq` with respect to `chainvar`, - default is d{eq}d{chainvar} + defines the derivative of the ``eq`` with respect to ``chainvar``, + default is ``d{eq}d{chainvar}`` :param dxdz_name: defines the name of the symbolic variable that - defines the derivative of the `chainvar` with respect to `var`, + defines the derivative of the ``chainvar`` with respect to ``var``, default is d{chainvar}d{var} - """ # compute total derivative according to chainrule # Dydz = dydx*dxdz + dydz @@ -2096,7 +2085,7 @@ def _total_derivative(self, name: str, eq: str, chainvars: List[str], dydx = self.sym_or_eq(name, dydx_name) dxdz = self.sym_or_eq(name, dxdz_name) - # Save time for for large models if one multiplicand is zero, + # Save time for large models if one multiplicand is zero, # which is not checked for by sympy if not smart_is_zero_matrix(dydx) and not \ smart_is_zero_matrix(dxdz): @@ -2122,7 +2111,6 @@ def sym_or_eq(self, name: str, varname: str) -> sp.Matrix: :return: the variable symbols if the variable is part of the signature and the variable equations otherwise. - """ # dwdx and dwdp will be dynamically computed and their ordering # within a column may differ from the initialization of symbols here, @@ -2141,7 +2129,7 @@ def _multiplication(self, name: str, x: str, y: str, Creates a new symbolic variable according to a multiplication :param name: - name of resulting symbolic variable, default is d{eq}d{var} + name of resulting symbolic variable, default is ``d{eq}d{var}`` :param x: name of the symbolic variable that defines the first factor @@ -2155,8 +2143,6 @@ def _multiplication(self, name: str, x: str, y: str, :param sign: defines the sign of the product, should be +1 or -1 - - """ if sign not in [-1, 1]: raise TypeError(f'sign must be +1 or -1, was {sign}') @@ -2182,7 +2168,6 @@ def _equation_from_component(self, name: str, component: str) -> None: :param component: name of the attribute - """ self._eqs[name] = sp.Matrix( [comp.get_val() for comp in getattr(self, component)] @@ -2207,7 +2192,6 @@ def _generate_value(self, name: str) -> None: :param name: name of resulting symbolic variable - """ if name in self._value_prototype: component = self._value_prototype[name] @@ -2224,7 +2208,6 @@ def _generate_name(self, name: str) -> None: :param name: name of resulting symbolic variable - """ if name in self._variable_prototype: component = self._variable_prototype[name] @@ -2247,7 +2230,6 @@ def state_has_fixed_parameter_initial_condition(self, ix: int) -> bool: :return: boolean indicating if any of the initial condition free variables is contained in the model constants - """ ic = self._states[ix].get_val() if not isinstance(ic, sp.Basic): @@ -2267,7 +2249,6 @@ def state_has_conservation_law(self, ix: int) -> bool: :return: boolean indicating if conservation_law is not None - """ return self._states[ix]._conservation_law is not None @@ -2280,7 +2261,6 @@ def state_is_constant(self, ix: int) -> bool: :return: boolean indicating if constant over time - """ return self._states[ix].get_dt() == 0.0 @@ -2295,7 +2275,6 @@ def conservation_law_has_multispecies(self, :return: boolean indicating if conservation_law is not None - """ state_set = set(self.sym('x_rdata')) n_species = len(state_set.intersection(tcl.get_val().free_symbols)) @@ -2341,7 +2320,7 @@ def _get_unique_root( list of already known root functions with identifier :returns: - unique identifier for root, or `None` if the root is not + unique identifier for root, or ``None`` if the root is not time-dependent """ # substitute 'w' expressions into root expressions now, to avoid @@ -2407,7 +2386,7 @@ def _process_heavisides( updated based on SUNDIALS root tracking. :param dxdt: - right hand side of state variable + right-hand side of state variable :param roots: list of known root functions with identifier @@ -2457,8 +2436,8 @@ class ODEExporter: used to avoid problems with state variables that may become negative due to numerical errors - compiler: distutils/setuptools compiler selection to build the - python extension + :ivar compiler: + distutils/setuptools compiler selection to build the Python extension :ivar functions: carries C++ function signatures and other specifications @@ -2505,8 +2484,8 @@ def __init__( see :meth:`amici.ode_export.ODEExporter.set_paths` :param verbose: - verbosity level for logging, True/False default to - logging.Error/logging.DEBUG + verbosity level for logging, ``True``/``False`` default to + :data:`logging.Error`/:data:`logging.DEBUG` :param assume_pow_positivity: if set to true, a special pow function is @@ -2519,8 +2498,9 @@ def __init__( :param allow_reinit_fixpar_initcond: see :class:`amici.ode_export.ODEExporter` - :param generate_sensitivity_code specifies whether code required for - sensitivity computation will be generated + :param generate_sensitivity_code: + specifies whether code required for sensitivity computation will be + generated :param model_name: name of the model to be used during code generation @@ -2553,8 +2533,6 @@ def generate_model_code(self) -> None: """ Generates the native C++ code for the loaded model and a Matlab script that can be run to compile a mex file from the C++ code - - """ with _monkeypatched(sp.Pow, '_eval_derivative', _custom_pow_eval_derivative): @@ -2567,8 +2545,6 @@ def generate_model_code(self) -> None: def compile_model(self) -> None: """ Compiles the generated code it into a simulatable module - - """ self._compile_c_code(compiler=self.compiler, verbose=self.verbose) @@ -2587,7 +2563,8 @@ def _prepare_model_folder(self) -> None: def _generate_c_code(self) -> None: """ - Create C++ code files for the model based on ODEExporter.model + Create C++ code files for the model based on + :attribute:`ODEExporter.model`. """ for func_name, func_info in self.functions.items(): if func_name in sensi_functions + sparse_sensi_functions and \ @@ -2635,9 +2612,7 @@ def _compile_c_code(self, :param compiler: distutils/setuptools compiler selection to build the python extension - """ - # setup.py assumes it is run from within the model directory module_dir = self.model_path script_args = [sys.executable, os.path.join(module_dir, 'setup.py')] @@ -2714,9 +2689,8 @@ def _write_index_files(self, name: str) -> None: Write index file for a symbolic array. :param name: - key in self.model._syms for which the respective file should + key in ``self.model._syms`` for which the respective file should be written - """ if name not in self.model.sym_names(): raise ValueError(f'Unknown symbolic array: {name}') @@ -2744,10 +2718,10 @@ def _write_index_files(self, name: str) -> None: def _write_function_file(self, function: str) -> None: """ Generate equations and write the C++ code for the function - `function`. + ``function``. :param function: - name of the function to be written (see self.functions) + name of the function to be written (see ``self.functions``) """ # first generate the equations to make sure we have everything we @@ -2851,10 +2825,10 @@ def _write_function_file(self, function: str) -> None: def _write_function_index(self, function: str, indextype: str) -> None: """ Generate equations and write the C++ code for the function - `function`. + ``function``. :param function: - name of the function to be written (see self.functions) + name of the function to be written (see ``self.functions``) :param indextype: type of index {'colptrs', 'rowvals'} @@ -2947,10 +2921,10 @@ def _get_function_body( equations: sp.Matrix ) -> List[str]: """ - Generate C++ code for body of function `function`. + Generate C++ code for body of function ``function``. :param function: - name of the function to be written (see self.functions) + name of the function to be written (see ``self.functions``) :param equations: symbolic definition of the function body @@ -3101,7 +3075,7 @@ def _get_function_body( def _write_wrapfunctions_cpp(self) -> None: """ - Write model-specific 'wrapper' file (wrapfunctions.cpp). + Write model-specific 'wrapper' file (``wrapfunctions.cpp``). """ template_data = {'MODELNAME': self.model_name} apply_template( @@ -3112,7 +3086,7 @@ def _write_wrapfunctions_cpp(self) -> None: def _write_wrapfunctions_header(self) -> None: """ - Write model-specific header file (wrapfunctions.h). + Write model-specific header file (``wrapfunctions.h``). """ template_data = {'MODELNAME': str(self.model_name)} apply_template( @@ -3283,7 +3257,7 @@ def _get_symbol_name_initializer_list(self, name: str) -> str: model entity :param name: - any key present in self.model._syms + any key present in ``self.model._syms`` :return: Template initializer list of names @@ -3301,7 +3275,7 @@ def _get_symbol_id_initializer_list(self, name: str) -> str: entity :param name: - any key present in self.model._syms + any key present in ``self.model._syms`` :return: Template initializer list of ids @@ -3314,10 +3288,7 @@ def _get_symbol_id_initializer_list(self, name: str) -> str: ) def _write_c_make_file(self): - """ - Write CMake CMakeLists.txt file for this model. - """ - + """Write CMake ``CMakeLists.txt`` file for this model.""" sources = [ f + ' ' for f in os.listdir(self.model_path) if f.endswith('.cpp') and f != 'main.cpp' @@ -3333,9 +3304,7 @@ def _write_c_make_file(self): ) def _write_swig_files(self) -> None: - """ - Write SWIG interface files for this model. - """ + """Write SWIG interface files for this model.""" if not os.path.exists(self.model_swig_path): os.makedirs(self.model_swig_path) template_data = {'MODELNAME': self.model_name} @@ -3349,7 +3318,7 @@ def _write_swig_files(self) -> None: def _write_module_setup(self) -> None: """ - Create a distutils setup.py file for compile the model module. + Create a setuptools ``setup.py`` file for compile the model module. """ template_data = {'MODELNAME': self.model_name, @@ -3377,7 +3346,7 @@ def set_paths(self, output_dir: Optional[str] = None) -> None: :param output_dir: relative or absolute path where the generated model code is to be placed. If ``None``, this will default to - `amici-{self.model_name}` in the current working directory. + ``amici-{self.model_name}`` in the current working directory. will be created if it does not exist. """ @@ -3395,7 +3364,6 @@ def set_name(self, model_name: str) -> None: :param model_name: name of the model (may only contain upper and lower case letters, digits and underscores, and must not start with a digit) - """ if not is_valid_identifier(model_name): raise ValueError( @@ -3408,11 +3376,11 @@ def set_name(self, model_name: str) -> None: class TemplateAmici(Template): """ - Template format used in AMICI (see string.template for more details). + Template format used in AMICI (see :class:`string.Template` for more + details). :cvar delimiter: delimiter that identifies template variables - """ delimiter = 'TPL_' @@ -3471,7 +3439,7 @@ def get_function_extern_declaration(fun: str, name: str) -> str: model name :return: - c++ function definition string + C++ function definition string """ f = functions[fun] return f'extern {f.return_type} {fun}_{name}({f.arguments});' @@ -3493,7 +3461,7 @@ def get_sunindex_extern_declaration(fun: str, name: str, index function {'colptrs', 'rowvals'} :return: - c++ function declaration string + C++ function declaration string """ index_arg = ', int index' if fun in multiobs_functions else '' return \ @@ -3504,7 +3472,7 @@ def get_sunindex_extern_declaration(fun: str, name: str, def get_model_override_implementation(fun: str, name: str, nobody: bool = False) -> str: """ - Constructs amici::Model::* override implementation for a given function + Constructs ``amici::Model::*`` override implementation for a given function :param fun: function name @@ -3516,7 +3484,7 @@ def get_model_override_implementation(fun: str, name: str, whether the function has a nontrivial implementation :return: - c++ function implementation string + C++ function implementation string """ impl = '{return_type} f{fun}({signature}) override {{' @@ -3542,7 +3510,7 @@ def get_sunindex_override_implementation(fun: str, name: str, indextype: str, nobody: bool = False) -> str: """ - Constructs the amici::Model:: function implementation for an index + Constructs the ``amici::Model`` function implementation for an index function of a given function :param fun: @@ -3558,7 +3526,7 @@ def get_sunindex_override_implementation(fun: str, name: str, whether the corresponding function has a nontrivial implementation :return: - c++ function implementation string + C++ function implementation string """ index_arg = ', int index' if fun in multiobs_functions else '' index_arg_eval = ', index' if fun in multiobs_functions else '' @@ -3684,7 +3652,7 @@ def symbol_with_assumptions(name: str): def cast_to_sym(value: Union[SupportsFloat, sp.Expr, BooleanAtom], input_name: str) -> sp.Expr: """ - Typecasts the value to sympy.Float if possible, and ensures the + Typecasts the value to :py:class:`sympy.Float` if possible, and ensures the value is a symbolic expression. :param value: @@ -3733,8 +3701,8 @@ def _monkeypatched(obj: object, name: str, patch: Any): def _custom_pow_eval_derivative(self, s): """ Custom Pow derivative that removes a removable singularity for - self.base == 0 and self.base.diff(s) == 0. This function is intended to - be monkeypatched into sp.Pow._eval_derivative. + ``self.base == 0`` and ``self.base.diff(s) == 0``. This function is + intended to be monkeypatched into :py:method:`sympy.Pow._eval_derivative`. :param self: sp.Pow class diff --git a/python/amici/pandas.py b/python/amici/pandas.py index 740e32d411..ad11278630 100644 --- a/python/amici/pandas.py +++ b/python/amici/pandas.py @@ -302,11 +302,11 @@ def getResidualsAsDataFrame(model: amici.Model, :param rdata_list: list of ReturnData instances corresponding to ExpData. May also be a - single ReturnData instance. + single ReturnData instance. :param by_id: bool, optional (default = False) - If True, ids are used as identifiers, otherwise the possibly more - descriptive names. + If True, ids are used as identifiers, otherwise the possibly more + descriptive names. :return: pandas DataFrame with conditions and residuals. @@ -609,8 +609,8 @@ def constructEdataFromDataFrame( :param by_id: Indicate whether in the arguments, column headers are based on ids or - names. This should correspond to the way `df` and `condition` was - created in the first place. + names. This should correspond to the way `df` and `condition` was + created in the first place. :return: ExpData instance. From e87bf7cce01ad99977e7e24ea101652da7dc050d Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 9 Feb 2022 12:48:24 +0100 Subject: [PATCH 22/22] Update changelog; bump version number --- CHANGELOG.md | 24 ++++++++++++++++++++++++ version.txt | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef6dcdbb45..5adefb5033 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,30 @@ ## v0.X Series +### v0.11.25 (2022-02-09) + +* Fixed a bug + where `Model::setStateIsNonNegative(Model::getStateIsNonNegative())` would + raise an exception in case conservation laws were enabled - by @dweindl + in https://github.com/AMICI-dev/AMICI/pull/1648 +* Fixed a bug where `Model::setStateIsNonNegative` would be ignored in certain + model expressions - by @FFroehlich + in https://github.com/AMICI-dev/AMICI/pull/1650 +* Fixed a bug where special function parsing inside `min()` and `max()` would + not be parsed correctly - by @dweindl + in https://github.com/AMICI-dev/AMICI/pull/1655 +* Fixed a numpy dependency issues for Mac+ARM systems - by @dweindl + in https://github.com/AMICI-dev/AMICI/pull/1657 +* Fixed convergence check in Newton method - by @plakrisenko + in https://github.com/AMICI-dev/AMICI/pull/1663 +* Add `AMICI_CXX_OPTIONS` to pass libamici-specific compiler options during + CMake-based builds - by @dweindl + in https://github.com/AMICI-dev/AMICI/pull/1664 +* Fixed various warnings and updated documentation - by @dweindl + +**Full Changelog**: +https://github.com/AMICI-dev/AMICI/compare/v0.11.24...v0.11.25 + ### v0.11.24 (2022-02-01) Features: diff --git a/version.txt b/version.txt index 55b335d444..7874d114d3 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.11.24 +0.11.25