Skip to content

Commit 3a7c28e

Browse files
authored
Release 0.11.22
Merge pull request #1601 from AMICI-dev/release/0.12.0
2 parents 82d2cbb + 2c83043 commit 3a7c28e

File tree

11 files changed

+466
-2175
lines changed

11 files changed

+466
-2175
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
## v0.X Series
44

5+
### v0.11.22 (2021-12-02)
6+
7+
* **Require sympy>=1.9,pysb>=1.13.1** by @FFroehlich, @dweindl
8+
in https://github.com/AMICI-dev/AMICI/pull/1599
9+
* Fixed sympy deprecation warning by @dweindl in
10+
https://github.com/AMICI-dev/AMICI/pull/1600
11+
* Updated Windows installation instructions for Python>=3.8 by @dweindl
12+
in https://github.com/AMICI-dev/AMICI/pull/1597
13+
* Fixed plot labels by @dweindl in https://github.com/AMICI-dev/AMICI/pull/1598
14+
15+
**Full Changelog**:
16+
https://github.com/AMICI-dev/AMICI/compare/v0.11.21...v0.11.22
17+
518
### v0.11.21 (2021-11-21)
619

720
Fixes:

documentation/python_installation.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,18 @@ by MSVC (see Visual Studio above). ``KERNEL32.dll`` is part of Windows and in
266266
``C:\Windows\System32``. The ``api-ms-win-crt-XXX-l1-1-0.dll`` are needed by
267267
``openblas.dll`` and are part of the Windows Universal C Runtime.
268268
269+
.. note::
270+
271+
Since Python 3.8, the library directory needs to be set as follows:
272+
273+
.. code-block:: python
274+
275+
import os
276+
# directory containing `openblas.dll`
277+
os.add_dll_directory("C:\\BLAS\\bin")
278+
import amici
279+
280+
Adding it to ``PATH`` will not work.
269281
270282
Further topics
271283
++++++++++++++

include/amici/solver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ class Solver {
5151
/** Type of what is passed to Sundials solvers as user_data */
5252
using user_data_type = std::pair<Model *, Solver const*>;
5353

54+
/**
55+
* @brief Default constructor
56+
*/
5457
Solver() = default;
5558

5659
/**

include/amici/symbolic_functions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace amici {
55

66
double log(double x);
77
double dirac(double x);
8-
double heaviside(double x);
8+
double heaviside(double x, double x0);
99

1010
double min(double a, double b, double c);
1111
double Dmin(int id, double a, double b, double c);

python/amici/ode_export.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -845,11 +845,9 @@ def smart_is_zero_matrix(x: Union[sp.MutableDenseMatrix,
845845
"""
846846

847847
if isinstance(x, sp.MutableDenseMatrix):
848-
nonzero = any(xx.is_zero is not True for xx in x._mat)
849-
else:
850-
nonzero = x.nnz() > 0
848+
return all(xx.is_zero is True for xx in x.flat())
851849

852-
return not nonzero
850+
return x.nnz() == 0
853851

854852

855853
class ODEModel:
@@ -1626,7 +1624,7 @@ def parse_events(self) -> None:
16261624
expr.set_val(self._process_heavisides(expr.get_val(), roots))
16271625

16281626
# remove all possible Heavisides from roots, which may arise from
1629-
# the substitution of `'w'` in `_collect_heaviside_roots`
1627+
# the substitution of `'w'` in `_get_unique_root`
16301628
for root in roots:
16311629
root.set_val(self._process_heavisides(root.get_val(), roots))
16321630

@@ -2354,6 +2352,14 @@ def _get_unique_root(
23542352
unique identifier for root, or `None` if the root is not
23552353
time-dependent
23562354
"""
2355+
# substitute 'w' expressions into root expressions now, to avoid
2356+
# rewriting '{model_name}_root.cpp' and '{model_name}_stau.cpp' headers
2357+
# to include 'w.h'
2358+
w_sorted = toposort_symbols(dict(zip(
2359+
[expr.get_id() for expr in self._expressions],
2360+
[expr.get_val() for expr in self._expressions],
2361+
)))
2362+
root_found = root_found.subs(w_sorted)
23572363

23582364
if not self._expr_is_time_dependent(root_found):
23592365
return None
@@ -2395,18 +2401,6 @@ def _collect_heaviside_roots(
23952401
elif arg.has(sp.Heaviside):
23962402
root_funs.extend(self._collect_heaviside_roots(arg.args))
23972403

2398-
# substitute 'w' expressions into root expressions now, to avoid
2399-
# rewriting '{model_name}_root.cpp' and '{model_name}_stau.cpp' headers
2400-
# to include 'w.h'
2401-
w_sorted = toposort_symbols(dict(zip(
2402-
[expr.get_id() for expr in self._expressions],
2403-
[expr.get_val() for expr in self._expressions],
2404-
)))
2405-
root_funs = [
2406-
r.subs(w_sorted)
2407-
for r in root_funs
2408-
]
2409-
24102404
return root_funs
24112405

24122406
def _process_heavisides(

python/amici/plotting.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from matplotlib.axes import Axes
1010
from typing import Optional, Iterable
1111

12+
1213
def plotStateTrajectories(
1314
rdata: ReturnDataView,
1415
state_indices: Optional[Iterable[int]] = None,
@@ -27,7 +28,7 @@ def plotStateTrajectories(
2728
2829
:param ax:
2930
matplotlib Axes instance to plot into
30-
31+
3132
:param model:
3233
amici model instance
3334
"""
@@ -37,18 +38,18 @@ def plotStateTrajectories(
3738
state_indices = range(rdata['x'].shape[1])
3839
for ix in state_indices:
3940
if model is None:
40-
label = f'x_{ix}'
41-
elif model.getStateNames()[ix] != '':
41+
label = f'$x_{{{ix}}}$'
42+
elif model.getStateNames()[ix]:
4243
label = model.getStateNames()[ix]
4344
else:
4445
label = model.getStateIds()[ix]
45-
ax.plot(rdata['t'], rdata['x'][:, ix], label = label)
46-
ax.set_xlabel('$t$ (s)')
47-
ax.set_ylabel('$x_i(t)$ (mmol/ml)')
46+
ax.plot(rdata['t'], rdata['x'][:, ix], label=label)
47+
ax.set_xlabel('$t$')
48+
ax.set_ylabel('$x(t)$')
4849
ax.legend()
4950
ax.set_title('State trajectories')
50-
51-
51+
52+
5253
def plotObservableTrajectories(
5354
rdata: ReturnDataView,
5455
observable_indices: Optional[Iterable[int]] = None,
@@ -77,13 +78,13 @@ def plotObservableTrajectories(
7778
observable_indices = range(rdata['y'].shape[1])
7879
for iy in observable_indices:
7980
if model is None:
80-
label = f'y_{iy}'
81-
elif model.getObservableNames()[iy] != '':
81+
label = f'$y_{{{iy}}}$'
82+
elif model.getObservableNames()[iy]:
8283
label = model.getObservableNames()[iy]
8384
else:
8485
label = model.getObservableIds()[iy]
85-
ax.plot(rdata['t'], rdata['y'][:, iy], label = label)
86-
ax.set_xlabel('$t$ (s)')
87-
ax.set_ylabel('$y_i(t)$ (AU)')
86+
ax.plot(rdata['t'], rdata['y'][:, iy], label=label)
87+
ax.set_xlabel('$t$')
88+
ax.set_ylabel('$y(t)$')
8889
ax.legend()
89-
ax.set_title('Observables')
90+
ax.set_title('Observable trajectories')

0 commit comments

Comments
 (0)