myokit 1.33.9__py3-none-any.whl → 1.35.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- myokit/__init__.py +9 -36
- myokit/__main__.py +76 -142
- myokit/_aux.py +62 -16
- myokit/_bin/example.mmt +1 -2
- myokit/_bin/install-win/menu.json +7 -7
- myokit/_config.py +22 -31
- myokit/_datablock.py +30 -74
- myokit/_datalog.py +49 -72
- myokit/_err.py +25 -24
- myokit/_expressions.py +50 -68
- myokit/_io.py +15 -27
- myokit/_model_api.py +453 -249
- myokit/_myokit_version.py +1 -5
- myokit/_parsing.py +38 -44
- myokit/_progress.py +5 -8
- myokit/_protocol.py +99 -9
- myokit/_sim/__init__.py +7 -24
- myokit/_sim/cable.c +6 -8
- myokit/_sim/cable.py +6 -8
- myokit/_sim/cmodel.h +125 -70
- myokit/_sim/cmodel.py +12 -14
- myokit/_sim/compiler.py +1 -4
- myokit/_sim/cvodessim.c +196 -118
- myokit/_sim/cvodessim.py +130 -103
- myokit/_sim/differential.hpp +4 -4
- myokit/_sim/fiber_tissue.c +4 -8
- myokit/_sim/fiber_tissue.py +11 -13
- myokit/_sim/jacobian.cpp +2 -2
- myokit/_sim/jacobian.py +11 -8
- myokit/_sim/mcl.h +53 -55
- myokit/_sim/opencl.py +21 -27
- myokit/_sim/openclsim.c +3 -7
- myokit/_sim/openclsim.cl +3 -3
- myokit/_sim/openclsim.py +49 -40
- myokit/_sim/pacing.h +36 -16
- myokit/_sim/rhs.c +6 -13
- myokit/_sim/rhs.py +5 -14
- myokit/_sim/sundials.py +1 -4
- myokit/_system.py +10 -16
- myokit/_unit.py +4 -13
- myokit/float.py +0 -3
- myokit/formats/__init__.py +8 -10
- myokit/formats/ansic/__init__.py +0 -3
- myokit/formats/ansic/_ewriter.py +2 -4
- myokit/formats/ansic/_exporter.py +1 -4
- myokit/formats/ansic/template/cable.c +4 -4
- myokit/formats/ansic/template/euler.c +5 -5
- myokit/formats/ansic/template/sim.c +6 -6
- myokit/formats/axon/__init__.py +1 -3
- myokit/formats/axon/_abf.py +12 -17
- myokit/formats/axon/_atf.py +5 -6
- myokit/formats/axon/_importer.py +0 -3
- myokit/formats/cellml/__init__.py +0 -3
- myokit/formats/cellml/_ewriter.py +3 -6
- myokit/formats/cellml/_exporter.py +3 -6
- myokit/formats/cellml/_importer.py +1 -4
- myokit/formats/cellml/v1/__init__.py +0 -4
- myokit/formats/cellml/v1/_api.py +8 -11
- myokit/formats/cellml/v1/_parser.py +2 -5
- myokit/formats/cellml/v1/_writer.py +2 -11
- myokit/formats/cellml/v2/__init__.py +0 -3
- myokit/formats/cellml/v2/_api.py +8 -17
- myokit/formats/cellml/v2/_parser.py +2 -5
- myokit/formats/cellml/v2/_writer.py +1 -4
- myokit/formats/channelml/__init__.py +0 -3
- myokit/formats/channelml/_importer.py +11 -21
- myokit/formats/cpp/__init__.py +1 -3
- myokit/formats/cpp/_ewriter.py +0 -3
- myokit/formats/cuda/__init__.py +0 -3
- myokit/formats/cuda/_ewriter.py +2 -4
- myokit/formats/cuda/_exporter.py +0 -3
- myokit/formats/cuda/template/kernel.cu +8 -5
- myokit/formats/easyml/__init__.py +0 -3
- myokit/formats/easyml/_ewriter.py +9 -11
- myokit/formats/easyml/_exporter.py +2 -5
- myokit/formats/html/__init__.py +0 -3
- myokit/formats/html/_exporter.py +0 -3
- myokit/formats/html/_flatten.py +5 -21
- myokit/formats/latex/__init__.py +0 -3
- myokit/formats/latex/_ewriter.py +1 -4
- myokit/formats/latex/_exporter.py +4 -6
- myokit/formats/mathml/__init__.py +0 -3
- myokit/formats/mathml/_ewriter.py +2 -11
- myokit/formats/mathml/_parser.py +4 -6
- myokit/formats/matlab/__init__.py +0 -3
- myokit/formats/matlab/_ewriter.py +1 -4
- myokit/formats/matlab/_exporter.py +2 -5
- myokit/formats/matlab/template/main.m +3 -2
- myokit/formats/opencl/__init__.py +0 -3
- myokit/formats/opencl/_ewriter.py +2 -4
- myokit/formats/opencl/_exporter.py +2 -5
- myokit/formats/opencl/template/cable.c +10 -10
- myokit/formats/opencl/template/kernel.cl +1 -1
- myokit/formats/opencl/template/minilog.py +1 -1
- myokit/formats/python/__init__.py +0 -3
- myokit/formats/python/_ewriter.py +2 -5
- myokit/formats/python/_exporter.py +0 -3
- myokit/formats/python/template/sim.py +14 -14
- myokit/formats/sbml/__init__.py +0 -3
- myokit/formats/sbml/_api.py +50 -44
- myokit/formats/sbml/_importer.py +1 -4
- myokit/formats/sbml/_parser.py +2 -5
- myokit/formats/stan/__init__.py +0 -3
- myokit/formats/stan/_ewriter.py +2 -4
- myokit/formats/stan/_exporter.py +2 -5
- myokit/formats/stan/template/cell.stan +3 -3
- myokit/formats/sympy/__init__.py +0 -3
- myokit/formats/sympy/_ereader.py +1 -4
- myokit/formats/sympy/_ewriter.py +2 -5
- myokit/formats/wcp/__init__.py +0 -3
- myokit/formats/wcp/_wcp.py +2 -8
- myokit/formats/xml/__init__.py +0 -3
- myokit/formats/xml/_exporter.py +0 -3
- myokit/formats/xml/_split.py +0 -3
- myokit/gui/__init__.py +80 -246
- myokit/gui/datablock_viewer.py +103 -86
- myokit/gui/datalog_viewer.py +214 -66
- myokit/gui/explorer.py +15 -21
- myokit/gui/ide.py +171 -144
- myokit/gui/progress.py +9 -9
- myokit/gui/source.py +406 -375
- myokit/gui/vargrapher.py +2 -12
- myokit/lib/deps.py +12 -13
- myokit/lib/guess.py +3 -4
- myokit/lib/hh.py +20 -18
- myokit/lib/markov.py +21 -20
- myokit/lib/multi.py +1 -3
- myokit/lib/plots.py +20 -9
- myokit/pacing.py +0 -3
- myokit/pype.py +7 -18
- myokit/tests/__init__.py +3 -6
- myokit/tests/ansic_event_based_pacing.py +1 -4
- myokit/tests/ansic_fixed_form_pacing.py +3 -6
- myokit/tests/data/beeler-1977-model-compare-b.mmt +2 -2
- myokit/tests/data/clancy-1999-fitting.mmt +1 -0
- myokit/tests/test_aux.py +13 -28
- myokit/tests/test_cellml_v1_api.py +4 -19
- myokit/tests/test_cellml_v1_parser.py +0 -15
- myokit/tests/test_cellml_v1_writer.py +0 -9
- myokit/tests/test_cellml_v2_api.py +4 -19
- myokit/tests/test_cellml_v2_parser.py +0 -15
- myokit/tests/test_cellml_v2_writer.py +0 -9
- myokit/tests/test_cmodel.py +16 -22
- myokit/tests/test_compiler_detection.py +1 -11
- myokit/tests/test_component.py +108 -56
- myokit/tests/test_config.py +34 -67
- myokit/tests/test_datablock.py +1 -9
- myokit/tests/test_datalog.py +19 -24
- myokit/tests/test_dependency_checking.py +8 -23
- myokit/tests/test_expressions.py +0 -9
- myokit/tests/test_float.py +1 -5
- myokit/tests/test_formats.py +0 -9
- myokit/tests/test_formats_axon.py +1 -9
- myokit/tests/test_formats_cellml.py +0 -15
- myokit/tests/test_formats_channelml.py +0 -15
- myokit/tests/test_formats_easyml.py +0 -14
- myokit/tests/test_formats_exporters.py +1 -16
- myokit/tests/test_formats_expression_writers.py +1 -17
- myokit/tests/test_formats_html.py +0 -3
- myokit/tests/test_formats_importers.py +1 -16
- myokit/tests/test_formats_mathml_content.py +0 -9
- myokit/tests/test_formats_mathml_presentation.py +0 -9
- myokit/tests/test_formats_opencl.py +0 -10
- myokit/tests/test_formats_sbml.py +0 -15
- myokit/tests/test_formats_sympy.py +0 -9
- myokit/tests/test_formats_wcp.py +1 -3
- myokit/tests/test_io.py +27 -27
- myokit/tests/test_jacobian_calculator.py +6 -14
- myokit/tests/test_jacobian_tracer.py +0 -9
- myokit/tests/test_lib_deps.py +0 -9
- myokit/tests/test_lib_guess.py +0 -9
- myokit/tests/test_lib_hh.py +18 -12
- myokit/tests/test_lib_markov.py +21 -13
- myokit/tests/test_lib_multi.py +0 -9
- myokit/tests/test_lib_plots.py +13 -8
- myokit/tests/test_meta.py +0 -3
- myokit/tests/test_model.py +390 -96
- myokit/tests/test_model_building.py +44 -96
- myokit/tests/test_opencl_info.py +5 -14
- myokit/tests/test_pacing_factory.py +0 -3
- myokit/tests/test_pacing_system_c.py +1 -23
- myokit/tests/test_pacing_system_py.py +0 -9
- myokit/tests/test_parsing.py +139 -56
- myokit/tests/test_progress_reporters.py +0 -3
- myokit/tests/test_protocol.py +0 -9
- myokit/tests/test_protocol_floating_point.py +1 -10
- myokit/tests/test_protocol_time_series.py +82 -0
- myokit/tests/test_pype.py +0 -9
- myokit/tests/test_quantity.py +0 -9
- myokit/tests/test_rhs_benchmarker.py +1 -9
- myokit/tests/test_sbml_api.py +27 -42
- myokit/tests/test_sbml_parser.py +4 -19
- myokit/tests/test_simulation_1d.py +45 -25
- myokit/tests/test_simulation_cvodes.py +321 -55
- myokit/tests/test_simulation_cvodes_from_disk.py +0 -3
- myokit/tests/test_simulation_fiber_tissue.py +39 -12
- myokit/tests/test_simulation_log_interval.py +1 -431
- myokit/tests/test_simulation_opencl.py +69 -48
- myokit/tests/test_simulation_opencl_log_interval.py +1 -3
- myokit/tests/test_simulation_opencl_vs_cvode.py +1 -10
- myokit/tests/test_simulation_opencl_vs_sim1d.py +1 -10
- myokit/tests/test_system_info.py +1 -11
- myokit/tests/test_tools.py +0 -9
- myokit/tests/test_unit.py +1 -10
- myokit/tests/test_user_functions.py +0 -10
- myokit/tests/test_variable.py +231 -27
- myokit/tools.py +5 -21
- myokit/units.py +5 -3
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/METADATA +12 -15
- myokit-1.35.0.dist-info/RECORD +391 -0
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/WHEEL +1 -1
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/entry_points.txt +0 -1
- myokit/_exec_new.py +0 -15
- myokit/_exec_old.py +0 -15
- myokit/_sim/cvodesim.c +0 -1551
- myokit/_sim/cvodesim.py +0 -674
- myokit/_sim/icsim.cpp +0 -563
- myokit/_sim/icsim.py +0 -363
- myokit/_sim/psim.cpp +0 -656
- myokit/_sim/psim.py +0 -493
- myokit/lib/common.py +0 -1094
- myokit/tests/test_lib_common.py +0 -130
- myokit/tests/test_simulation_cvode.py +0 -612
- myokit/tests/test_simulation_ic.py +0 -108
- myokit/tests/test_simulation_p.py +0 -223
- myokit-1.33.9.dist-info/RECORD +0 -403
- /myokit/formats/opencl/template/{test → test.sh} +0 -0
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/LICENSE.txt +0 -0
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/top_level.txt +0 -0
|
@@ -5,11 +5,9 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
from __future__ import absolute_import, division
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
10
|
-
|
|
11
8
|
import os
|
|
12
9
|
import unittest
|
|
10
|
+
|
|
13
11
|
import numpy as np
|
|
14
12
|
|
|
15
13
|
import myokit
|
|
@@ -5,24 +5,15 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
from __future__ import absolute_import, division
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
10
|
-
|
|
11
8
|
import os
|
|
12
9
|
import unittest
|
|
10
|
+
|
|
13
11
|
import numpy as np
|
|
14
12
|
|
|
15
13
|
import myokit
|
|
16
14
|
|
|
17
15
|
from myokit.tests import OpenCL_DOUBLE_PRECISION, DIR_DATA
|
|
18
16
|
|
|
19
|
-
# Unit testing in Python 2 and 3
|
|
20
|
-
try:
|
|
21
|
-
unittest.TestCase.assertRaisesRegex
|
|
22
|
-
except AttributeError:
|
|
23
|
-
unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
|
|
24
|
-
|
|
25
|
-
|
|
26
17
|
# Show simulation output
|
|
27
18
|
debug = False
|
|
28
19
|
|
|
@@ -5,24 +5,15 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
from __future__ import absolute_import, division
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
10
|
-
|
|
11
8
|
import os
|
|
12
9
|
import unittest
|
|
10
|
+
|
|
13
11
|
import numpy as np
|
|
14
12
|
|
|
15
13
|
import myokit
|
|
16
14
|
|
|
17
15
|
from myokit.tests import OpenCL_DOUBLE_PRECISION, DIR_DATA
|
|
18
16
|
|
|
19
|
-
# Unit testing in Python 2 and 3
|
|
20
|
-
try:
|
|
21
|
-
unittest.TestCase.assertRaisesRegex
|
|
22
|
-
except AttributeError:
|
|
23
|
-
unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
|
|
24
|
-
|
|
25
|
-
|
|
26
17
|
# Show simulation output
|
|
27
18
|
debug = False
|
|
28
19
|
|
myokit/tests/test_system_info.py
CHANGED
|
@@ -5,21 +5,11 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
from __future__ import absolute_import, division
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
10
|
-
|
|
11
8
|
import unittest
|
|
12
9
|
|
|
13
10
|
import myokit
|
|
14
11
|
|
|
15
12
|
|
|
16
|
-
# Strings in Python2 and Python3
|
|
17
|
-
try:
|
|
18
|
-
basestring
|
|
19
|
-
except NameError: # pragma: no cover
|
|
20
|
-
basestring = str
|
|
21
|
-
|
|
22
|
-
|
|
23
13
|
class SystemInfoTest(unittest.TestCase):
|
|
24
14
|
"""
|
|
25
15
|
Tests the system info method.
|
|
@@ -29,7 +19,7 @@ class SystemInfoTest(unittest.TestCase):
|
|
|
29
19
|
import matplotlib
|
|
30
20
|
matplotlib.use('template')
|
|
31
21
|
|
|
32
|
-
self.assertIsInstance(myokit.system(),
|
|
22
|
+
self.assertIsInstance(myokit.system(), str)
|
|
33
23
|
with myokit.tools.capture():
|
|
34
24
|
myokit.system(live_printing=True)
|
|
35
25
|
|
myokit/tests/test_tools.py
CHANGED
|
@@ -5,9 +5,6 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
from __future__ import absolute_import, division
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
10
|
-
|
|
11
8
|
import os
|
|
12
9
|
import re
|
|
13
10
|
import sys
|
|
@@ -15,12 +12,6 @@ import threading
|
|
|
15
12
|
import time
|
|
16
13
|
import unittest
|
|
17
14
|
|
|
18
|
-
# Strings in Python2 and Python3
|
|
19
|
-
try:
|
|
20
|
-
basestring
|
|
21
|
-
except NameError: # pragma: no cover
|
|
22
|
-
basestring = str
|
|
23
|
-
|
|
24
15
|
import myokit
|
|
25
16
|
|
|
26
17
|
from myokit.tests import TemporaryDirectory
|
myokit/tests/test_unit.py
CHANGED
|
@@ -5,19 +5,10 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
from __future__ import absolute_import, division
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
10
|
-
|
|
11
8
|
import unittest
|
|
12
9
|
|
|
13
10
|
import myokit
|
|
14
11
|
|
|
15
|
-
# Unit testing in Python 2 and 3
|
|
16
|
-
try:
|
|
17
|
-
unittest.TestCase.assertRaisesRegex
|
|
18
|
-
except AttributeError:
|
|
19
|
-
unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
|
|
20
|
-
|
|
21
12
|
|
|
22
13
|
class MyokitUnitTest(unittest.TestCase):
|
|
23
14
|
|
|
@@ -79,7 +70,7 @@ class MyokitUnitTest(unittest.TestCase):
|
|
|
79
70
|
self.assertFalse(myokit.Unit.close(not_pF2, pF2))
|
|
80
71
|
self.assertFalse(myokit.Unit.close(pF2, not_pF2))
|
|
81
72
|
|
|
82
|
-
# The next test is not a requirement, but tests the current
|
|
73
|
+
# The next test is not a requirement, but tests the current behavior:
|
|
83
74
|
u = myokit.units.m * 1.000000001
|
|
84
75
|
self.assertTrue(myokit.Unit.close(u, myokit.units.m))
|
|
85
76
|
|
|
@@ -5,19 +5,9 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
from __future__ import absolute_import, division
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
10
|
-
|
|
11
8
|
import unittest
|
|
12
9
|
import myokit
|
|
13
10
|
|
|
14
|
-
# Unit testing in Python 2 and 3
|
|
15
|
-
try:
|
|
16
|
-
unittest.TestCase.assertRaisesRegex
|
|
17
|
-
except AttributeError:
|
|
18
|
-
unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
|
|
19
|
-
|
|
20
|
-
|
|
21
11
|
# Further testing in test_model.py
|
|
22
12
|
|
|
23
13
|
|
myokit/tests/test_variable.py
CHANGED
|
@@ -5,25 +5,20 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
8
|
+
import unittest
|
|
10
9
|
|
|
11
|
-
import myokit
|
|
12
10
|
import numpy as np
|
|
13
|
-
import unittest
|
|
14
11
|
|
|
12
|
+
import myokit
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
try:
|
|
18
|
-
unittest.TestCase.assertRaisesRegex
|
|
19
|
-
except AttributeError:
|
|
20
|
-
unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
|
|
14
|
+
from myokit.tests import WarningCollector
|
|
21
15
|
|
|
22
16
|
|
|
23
17
|
class VariableTest(unittest.TestCase):
|
|
24
18
|
"""
|
|
25
19
|
Tests parts of :class:`myokit.Variable`.
|
|
26
20
|
"""
|
|
21
|
+
|
|
27
22
|
def test_clamp(self):
|
|
28
23
|
# Tests clamping a variable to a fixed value
|
|
29
24
|
m = myokit.parse_model("""
|
|
@@ -92,7 +87,7 @@ class VariableTest(unittest.TestCase):
|
|
|
92
87
|
# Clamp simple state
|
|
93
88
|
g = m.get('z.g')
|
|
94
89
|
self.assertTrue(g.is_state())
|
|
95
|
-
self.
|
|
90
|
+
self.assertNotEqual(g.initial_value(True), 10)
|
|
96
91
|
self.assertEqual(g.unit(), myokit.units.m)
|
|
97
92
|
self.assertEqual(g.rhs().unit(), myokit.units.m / myokit.units.s)
|
|
98
93
|
self.assertEqual(m.count_states(), 3)
|
|
@@ -158,6 +153,7 @@ class VariableTest(unittest.TestCase):
|
|
|
158
153
|
m = myokit.parse_model("""
|
|
159
154
|
[[model]]
|
|
160
155
|
membrane.V = -83
|
|
156
|
+
membrane.w = 10
|
|
161
157
|
|
|
162
158
|
[env]
|
|
163
159
|
t = 0 [ms] bind time
|
|
@@ -168,6 +164,8 @@ class VariableTest(unittest.TestCase):
|
|
|
168
164
|
in [mV]
|
|
169
165
|
dotv = 5 [mV/ms] + dot(V)
|
|
170
166
|
in [mV/ms]
|
|
167
|
+
dot(w) = 0.1 [mg/ms]
|
|
168
|
+
in [mg]
|
|
171
169
|
|
|
172
170
|
[cell]
|
|
173
171
|
Cm = 0.123 [uF]
|
|
@@ -194,7 +192,7 @@ class VariableTest(unittest.TestCase):
|
|
|
194
192
|
v.convert_unit('mV')
|
|
195
193
|
self.assertEqual(code, m.code())
|
|
196
194
|
|
|
197
|
-
# Convert state
|
|
195
|
+
# Convert state (note: initial value is treated as PrefixMinus expr!)
|
|
198
196
|
vdot = v.rhs().eval()
|
|
199
197
|
self.assertNotEqual(v.unit(), myokit.units.V)
|
|
200
198
|
v.convert_unit('V')
|
|
@@ -205,6 +203,28 @@ class VariableTest(unittest.TestCase):
|
|
|
205
203
|
self.assertEqual(vdot, v.rhs().eval())
|
|
206
204
|
m.check_units(myokit.UNIT_STRICT)
|
|
207
205
|
|
|
206
|
+
# Check units of the initial value have been converted
|
|
207
|
+
self.assertEqual(v.initial_value(True), -0.083)
|
|
208
|
+
# Not sure if this one is desirable, but -83 is parsed as the
|
|
209
|
+
# expression -(83)
|
|
210
|
+
self.assertEqual(
|
|
211
|
+
v.initial_value(),
|
|
212
|
+
myokit.Multiply(
|
|
213
|
+
myokit.PrefixMinus(myokit.Number(83)),
|
|
214
|
+
myokit.Number(0.001, myokit.units.V / myokit.units.mV)))
|
|
215
|
+
|
|
216
|
+
# Convert state with number initial value
|
|
217
|
+
w = m.get('membrane.w')
|
|
218
|
+
wdot = w.rhs().eval()
|
|
219
|
+
w.convert_unit('ug')
|
|
220
|
+
self.assertEqual(w.unit(), myokit.units.g / 1e6)
|
|
221
|
+
self.assertEqual(wdot * 1000, w.rhs().eval())
|
|
222
|
+
m.check_units(myokit.UNIT_STRICT)
|
|
223
|
+
self.assertEqual(w.initial_value(True), 10000)
|
|
224
|
+
self.assertEqual(w.initial_value(), myokit.Number(10000))
|
|
225
|
+
#self.assertEqual(
|
|
226
|
+
# w.initial_value(), myokit.Number(10000, myokit.units.g / 1e6))
|
|
227
|
+
|
|
208
228
|
# Convert non-state
|
|
209
229
|
i = m.get('ina.i')
|
|
210
230
|
self.assertNotEqual(i.unit(), myokit.parse_unit('uA/uF'))
|
|
@@ -226,6 +246,72 @@ class VariableTest(unittest.TestCase):
|
|
|
226
246
|
self.assertEqual(vdot, v.rhs().eval())
|
|
227
247
|
m.check_units(myokit.UNIT_STRICT)
|
|
228
248
|
|
|
249
|
+
def test_index(self):
|
|
250
|
+
# Tests the index() method
|
|
251
|
+
|
|
252
|
+
m = myokit.Model()
|
|
253
|
+
c = m.add_component('c')
|
|
254
|
+
a = c.add_variable('a')
|
|
255
|
+
a.set_rhs(0)
|
|
256
|
+
a.promote(0)
|
|
257
|
+
b = c.add_variable('b')
|
|
258
|
+
b.set_rhs(0)
|
|
259
|
+
b.promote(0)
|
|
260
|
+
|
|
261
|
+
self.assertEqual(a.index(), 0)
|
|
262
|
+
self.assertEqual(b.index(), 1)
|
|
263
|
+
m.reorder_state((b, a))
|
|
264
|
+
self.assertEqual(a.index(), 1)
|
|
265
|
+
self.assertEqual(b.index(), 0)
|
|
266
|
+
|
|
267
|
+
# Test deprecated alias
|
|
268
|
+
with WarningCollector() as w:
|
|
269
|
+
self.assertEqual(a.indice(), 1)
|
|
270
|
+
self.assertIn('deprecated', w.text())
|
|
271
|
+
|
|
272
|
+
def test_initial_value(self):
|
|
273
|
+
# Tests :meth:`Variable.initial_value`.
|
|
274
|
+
|
|
275
|
+
m = myokit.parse_model('''
|
|
276
|
+
[[model]]
|
|
277
|
+
c.x = 2
|
|
278
|
+
|
|
279
|
+
[c]
|
|
280
|
+
t = 0 bind time
|
|
281
|
+
dot(x) = 0
|
|
282
|
+
p = 3
|
|
283
|
+
q = 4
|
|
284
|
+
''')
|
|
285
|
+
|
|
286
|
+
# Test expression version
|
|
287
|
+
x, p = m.get('c.x'), m.get('c.p')
|
|
288
|
+
p = m.get('c.p')
|
|
289
|
+
self.assertEqual(x.initial_value(), myokit.Number(2))
|
|
290
|
+
x.set_initial_value(3)
|
|
291
|
+
self.assertEqual(x.initial_value(), myokit.Number(3))
|
|
292
|
+
x.set_initial_value('3 [kg]')
|
|
293
|
+
self.assertEqual(x.initial_value(), myokit.Number(3, myokit.units.kg))
|
|
294
|
+
x.set_initial_value('sqrt(c.p) / log(c.p)')
|
|
295
|
+
self.assertEqual(x.initial_value(), myokit.Divide(
|
|
296
|
+
myokit.Sqrt(p.lhs()), myokit.Log(p.lhs())))
|
|
297
|
+
|
|
298
|
+
# Test float version
|
|
299
|
+
p.set_rhs(9)
|
|
300
|
+
x.set_initial_value('1 + sqrt(c.p)')
|
|
301
|
+
self.assertEqual(x.initial_value(True), 4)
|
|
302
|
+
|
|
303
|
+
# Test deprecated alias
|
|
304
|
+
with WarningCollector() as w:
|
|
305
|
+
self.assertEqual(x.state_value(), x.initial_value(True))
|
|
306
|
+
self.assertIn('deprecated', w.text())
|
|
307
|
+
|
|
308
|
+
# Test cycles are detected
|
|
309
|
+
p.set_rhs('1 - 2 * q')
|
|
310
|
+
m.get('c.q').set_rhs('7 * sqrt(p)')
|
|
311
|
+
x.initial_value() # No evaluation, so no error
|
|
312
|
+
self.assertRaises(
|
|
313
|
+
myokit.CyclicalDependencyError, x.initial_value, as_float=True)
|
|
314
|
+
|
|
229
315
|
def test_is_referenced(self):
|
|
230
316
|
# Test :meth:`Variable.is_referenced().
|
|
231
317
|
|
|
@@ -276,6 +362,8 @@ class VariableTest(unittest.TestCase):
|
|
|
276
362
|
|
|
277
363
|
m = myokit.Model()
|
|
278
364
|
c = m.add_component('c')
|
|
365
|
+
p = c.add_variable('p')
|
|
366
|
+
p.set_rhs(1)
|
|
279
367
|
v = c.add_variable('v')
|
|
280
368
|
v.set_rhs(3)
|
|
281
369
|
|
|
@@ -285,8 +373,8 @@ class VariableTest(unittest.TestCase):
|
|
|
285
373
|
self.assertFalse(v.is_state())
|
|
286
374
|
self.assertEqual(v.lhs(), myokit.Name(v))
|
|
287
375
|
self.assertRaises(Exception, v.demote)
|
|
288
|
-
self.assertRaises(Exception, v.
|
|
289
|
-
self.assertRaises(Exception, v.
|
|
376
|
+
self.assertRaises(Exception, v.index)
|
|
377
|
+
self.assertRaises(Exception, v.initial_value)
|
|
290
378
|
|
|
291
379
|
v.promote(3)
|
|
292
380
|
self.assertFalse(v.is_literal())
|
|
@@ -294,8 +382,8 @@ class VariableTest(unittest.TestCase):
|
|
|
294
382
|
self.assertFalse(v.is_intermediary())
|
|
295
383
|
self.assertTrue(v.is_state())
|
|
296
384
|
self.assertEqual(v.lhs(), myokit.Derivative(myokit.Name(v)))
|
|
297
|
-
self.assertEqual(v.
|
|
298
|
-
self.assertEqual(v.
|
|
385
|
+
self.assertEqual(v.index(), 0)
|
|
386
|
+
self.assertEqual(v.initial_value(), myokit.Number(3))
|
|
299
387
|
|
|
300
388
|
v.demote()
|
|
301
389
|
self.assertTrue(v.is_literal())
|
|
@@ -304,8 +392,8 @@ class VariableTest(unittest.TestCase):
|
|
|
304
392
|
self.assertFalse(v.is_state())
|
|
305
393
|
self.assertEqual(v.lhs(), myokit.Name(v))
|
|
306
394
|
self.assertRaises(Exception, v.demote)
|
|
307
|
-
self.assertRaises(Exception, v.
|
|
308
|
-
self.assertRaises(Exception, v.
|
|
395
|
+
self.assertRaises(Exception, v.index)
|
|
396
|
+
self.assertRaises(Exception, v.initial_value)
|
|
309
397
|
|
|
310
398
|
# Test errors
|
|
311
399
|
v.promote(3)
|
|
@@ -317,6 +405,19 @@ class VariableTest(unittest.TestCase):
|
|
|
317
405
|
self.assertRaisesRegex(
|
|
318
406
|
Exception, 'only be added to Components', w.promote, 4)
|
|
319
407
|
|
|
408
|
+
# Test that promote accepts expressions and strings
|
|
409
|
+
v.set_binding(None)
|
|
410
|
+
v.remove_variable(w)
|
|
411
|
+
v.promote(myokit.Number(3, myokit.units.kg))
|
|
412
|
+
self.assertEqual(v.initial_value(), myokit.Number(3, myokit.units.kg))
|
|
413
|
+
v.demote()
|
|
414
|
+
v.promote('1 + c.p')
|
|
415
|
+
self.assertEqual(v.initial_value().code(), '1 + c.p')
|
|
416
|
+
v.demote()
|
|
417
|
+
|
|
418
|
+
# Test that promote only works with global syntax references
|
|
419
|
+
self.assertRaisesRegex(myokit.ParseError, 'Unresolved', v.promote, 'p')
|
|
420
|
+
|
|
320
421
|
# Test we can't demote a variable with references to its derivative
|
|
321
422
|
m = myokit.Model()
|
|
322
423
|
c = m.add_component('c')
|
|
@@ -330,6 +431,15 @@ class VariableTest(unittest.TestCase):
|
|
|
330
431
|
y.set_rhs('1 + x')
|
|
331
432
|
x.demote()
|
|
332
433
|
|
|
434
|
+
# Test deprecated keyword argument
|
|
435
|
+
with WarningCollector() as w:
|
|
436
|
+
x.promote(state_value=3)
|
|
437
|
+
self.assertIn('deprecated', w.text())
|
|
438
|
+
self.assertEqual(x.initial_value(), myokit.Number(3))
|
|
439
|
+
x.demote()
|
|
440
|
+
self.assertRaisesRegex(
|
|
441
|
+
Exception, 'at the same time as', x.promote, 3, state_value=3)
|
|
442
|
+
|
|
333
443
|
def test_pyfunc(self):
|
|
334
444
|
# Test :meth:`Variable.pyfunc().
|
|
335
445
|
|
|
@@ -638,31 +748,72 @@ class VariableTest(unittest.TestCase):
|
|
|
638
748
|
self.assertEqual(v.name(), 'w')
|
|
639
749
|
self.assertEqual(v.qname(), 'c.w')
|
|
640
750
|
|
|
641
|
-
def
|
|
642
|
-
# Test :meth:`Variable.
|
|
751
|
+
def test_set_initial_value(self):
|
|
752
|
+
# Test :meth:`Variable.set_initial_value()`.
|
|
643
753
|
|
|
644
754
|
m = myokit.Model()
|
|
645
755
|
c = m.add_component('c')
|
|
756
|
+
t = c.add_variable('t')
|
|
757
|
+
t.set_rhs(0)
|
|
758
|
+
t.set_binding('time')
|
|
646
759
|
v = c.add_variable('v')
|
|
760
|
+
v.set_rhs(3)
|
|
647
761
|
w = c.add_variable('w')
|
|
762
|
+
w.set_rhs('1 + 2')
|
|
763
|
+
m.validate()
|
|
648
764
|
|
|
649
765
|
# Test basic functionality
|
|
650
766
|
v.promote(10)
|
|
651
|
-
self.assertEqual(v.
|
|
652
|
-
v.
|
|
653
|
-
self.assertEqual(v.
|
|
767
|
+
self.assertEqual(v.initial_value(), myokit.Number(10))
|
|
768
|
+
v.set_initial_value(myokit.Number(12, myokit.units.g))
|
|
769
|
+
self.assertEqual(v.initial_value(), myokit.Number(12, myokit.units.g))
|
|
770
|
+
|
|
771
|
+
# Test setting expressions
|
|
772
|
+
v.set_initial_value('1 + 11')
|
|
773
|
+
#self.assertEqual(v.initial_value(),
|
|
774
|
+
# myokit.Plus(myokit.Number(1), myokit.Number(11)))
|
|
775
|
+
v.set_initial_value('1 + c.w')
|
|
776
|
+
self.assertEqual(v.initial_value(),
|
|
777
|
+
myokit.Plus(myokit.Number(1), myokit.Name(w)))
|
|
778
|
+
|
|
779
|
+
# Strings must use global context
|
|
780
|
+
self.assertRaisesRegex(myokit.ParseError, 'No component specified for',
|
|
781
|
+
v.set_initial_value, '1 / w')
|
|
654
782
|
|
|
655
783
|
# Only states have this option
|
|
656
784
|
v.demote()
|
|
657
785
|
self.assertRaisesRegex(
|
|
658
|
-
Exception, 'Only state variables', v.
|
|
786
|
+
Exception, 'Only state variables', v.set_initial_value, 3)
|
|
659
787
|
self.assertRaisesRegex(
|
|
660
|
-
Exception, 'Only state variables', w.
|
|
661
|
-
|
|
662
|
-
# State values must be literals
|
|
788
|
+
Exception, 'Only state variables', w.set_initial_value, 3)
|
|
663
789
|
v.promote(3)
|
|
790
|
+
m.validate()
|
|
791
|
+
|
|
792
|
+
# Initial values must be constant, but this is only picked up in
|
|
793
|
+
# validation
|
|
794
|
+
w.promote(1)
|
|
795
|
+
v.set_initial_value(myokit.Name(w))
|
|
796
|
+
self.assertRaises(myokit.IntegrityError, m.validate)
|
|
797
|
+
w.demote()
|
|
798
|
+
m.validate()
|
|
799
|
+
|
|
800
|
+
# Nested variables may not be used, but this is only picked up when
|
|
801
|
+
# validating
|
|
802
|
+
x = v.add_variable('x')
|
|
803
|
+
x.set_rhs(1)
|
|
804
|
+
v.set_initial_value(x.lhs())
|
|
664
805
|
self.assertRaises(
|
|
665
|
-
myokit.
|
|
806
|
+
myokit.IllegalReferenceInInitialValueError, m.validate)
|
|
807
|
+
v.set_initial_value(x)
|
|
808
|
+
|
|
809
|
+
# InitialValue and PartialDerivative can not be used
|
|
810
|
+
v.set_initial_value(myokit.PartialDerivative(v.lhs(), x.lhs()))
|
|
811
|
+
|
|
812
|
+
# Deprecated alias
|
|
813
|
+
with WarningCollector() as w:
|
|
814
|
+
v.set_state_value(1)
|
|
815
|
+
self.assertIn('deprecated', w.text())
|
|
816
|
+
self.assertEqual(v.initial_value(), myokit.Number(1))
|
|
666
817
|
|
|
667
818
|
def test_set_unit(self):
|
|
668
819
|
# Test :meth:`Variable.set_unit()`.
|
|
@@ -745,6 +896,59 @@ class VariableTest(unittest.TestCase):
|
|
|
745
896
|
p.set_rhs('q == 3')
|
|
746
897
|
self.assertRaisesRegex(
|
|
747
898
|
myokit.IntegrityError, 'can not be a condition', p.validate)
|
|
899
|
+
p.set_rhs(3)
|
|
900
|
+
p.validate()
|
|
901
|
+
|
|
902
|
+
# Initial value can not reference nested variables
|
|
903
|
+
r = c.add_variable('r')
|
|
904
|
+
r1 = r.add_variable('r1')
|
|
905
|
+
r1.set_rhs(1)
|
|
906
|
+
r.set_rhs('1 + r1')
|
|
907
|
+
p.validate()
|
|
908
|
+
p.set_initial_value(myokit.Plus(myokit.Number(1), myokit.Name(r1)))
|
|
909
|
+
self.assertRaises(
|
|
910
|
+
myokit.IllegalReferenceInInitialValueError, p.validate)
|
|
911
|
+
|
|
912
|
+
# Initial value must be constant
|
|
913
|
+
p.set_initial_value('1 / c.q')
|
|
914
|
+
q.promote(3)
|
|
915
|
+
self.assertRaisesRegex(myokit.IntegrityError, 'not const', p.validate)
|
|
916
|
+
q.demote()
|
|
917
|
+
p.validate()
|
|
918
|
+
q.set_rhs('1 + c.p')
|
|
919
|
+
self.assertRaisesRegex(myokit.IntegrityError, 'not const', p.validate)
|
|
920
|
+
q.set_rhs(10)
|
|
921
|
+
p.validate()
|
|
922
|
+
q.set_binding('hello')
|
|
923
|
+
self.assertRaisesRegex(myokit.IntegrityError, 'not const', p.validate)
|
|
924
|
+
# Don't test everything, is_const() should work!
|
|
925
|
+
|
|
926
|
+
# Initial value cannot be a partial, init, or condition
|
|
927
|
+
p.set_initial_value(myokit.PartialDerivative(p.lhs(), q.lhs()))
|
|
928
|
+
self.assertRaisesRegex(
|
|
929
|
+
myokit.IntegrityError, 'Partial derivatives', p.validate)
|
|
930
|
+
p.set_initial_value(myokit.InitialValue(myokit.Name(p)))
|
|
931
|
+
self.assertRaisesRegex(
|
|
932
|
+
myokit.IntegrityError, 'Initial value', p.validate)
|
|
933
|
+
p.set_initial_value('c.q == 3')
|
|
934
|
+
self.assertRaisesRegex(
|
|
935
|
+
myokit.IntegrityError, 'can not be a condition', p.validate)
|
|
936
|
+
|
|
937
|
+
# Initial value cycles are caught in validation, don't cause loops
|
|
938
|
+
m = myokit.parse_model('''
|
|
939
|
+
[[model]]
|
|
940
|
+
x.x = 0
|
|
941
|
+
[x]
|
|
942
|
+
dot(x) = x
|
|
943
|
+
t = 0 bind time
|
|
944
|
+
''')
|
|
945
|
+
x = m.get('x.x')
|
|
946
|
+
x.set_initial_value('x.x')
|
|
947
|
+
self.assertRaisesRegex(myokit.IntegrityError, 'not const', m.validate)
|
|
948
|
+
x.set_initial_value(1)
|
|
949
|
+
m.validate()
|
|
950
|
+
x.set_initial_value('1 + 1 / x.x')
|
|
951
|
+
self.assertRaisesRegex(myokit.IntegrityError, 'not const', m.validate)
|
|
748
952
|
|
|
749
953
|
def test_value(self):
|
|
750
954
|
# Test :meth:`Variable.value()`.
|
myokit/tools.py
CHANGED
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
# This file is part of Myokit.
|
|
7
7
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
8
8
|
#
|
|
9
|
-
|
|
10
|
-
from __future__ import print_function, unicode_literals
|
|
11
|
-
|
|
9
|
+
import io
|
|
12
10
|
import os
|
|
13
11
|
import re
|
|
14
12
|
import shutil
|
|
@@ -18,18 +16,12 @@ import tempfile
|
|
|
18
16
|
import threading
|
|
19
17
|
import timeit
|
|
20
18
|
|
|
21
|
-
# StringIO in Python 2 and 3
|
|
22
|
-
try:
|
|
23
|
-
from cStringIO import StringIO
|
|
24
|
-
except ImportError: # pragma: no python 2 cover
|
|
25
|
-
from io import StringIO
|
|
26
|
-
|
|
27
19
|
|
|
28
20
|
# Natural sort regex
|
|
29
21
|
_natural_sort_regex = re.compile('([0-9]+)')
|
|
30
22
|
|
|
31
23
|
|
|
32
|
-
class Benchmarker
|
|
24
|
+
class Benchmarker:
|
|
33
25
|
"""
|
|
34
26
|
Allows benchmarking using the with statement.
|
|
35
27
|
|
|
@@ -97,7 +89,7 @@ class Benchmarker(object):
|
|
|
97
89
|
return timeit.default_timer() - self._start
|
|
98
90
|
|
|
99
91
|
|
|
100
|
-
class capture
|
|
92
|
+
class capture:
|
|
101
93
|
"""
|
|
102
94
|
Context manager that temporarily redirects the current standard output and
|
|
103
95
|
error streams, and captures anything that's written to them.
|
|
@@ -224,8 +216,8 @@ class capture(object):
|
|
|
224
216
|
# Redirect
|
|
225
217
|
if not self._fd:
|
|
226
218
|
# Create temporary output and error streams
|
|
227
|
-
self._tmp_out = StringIO()
|
|
228
|
-
self._tmp_err = StringIO()
|
|
219
|
+
self._tmp_out = io.StringIO()
|
|
220
|
+
self._tmp_err = io.StringIO()
|
|
229
221
|
|
|
230
222
|
# Redirect, attempting to flush first
|
|
231
223
|
try:
|
|
@@ -391,10 +383,6 @@ class capture(object):
|
|
|
391
383
|
return ''
|
|
392
384
|
text = self._txt_err
|
|
393
385
|
|
|
394
|
-
# In Python 2, the text needs to be decoded from ascii
|
|
395
|
-
if sys.hexversion < 0x03000000: # pragma: no python 3 cover
|
|
396
|
-
text = text.decode('ascii', 'ignore')
|
|
397
|
-
|
|
398
386
|
return text
|
|
399
387
|
|
|
400
388
|
def out(self):
|
|
@@ -406,10 +394,6 @@ class capture(object):
|
|
|
406
394
|
return ''
|
|
407
395
|
text = self._txt_out
|
|
408
396
|
|
|
409
|
-
# In Python 2, the text needs to be decoded from ascii
|
|
410
|
-
if sys.hexversion < 0x03000000: # pragma: no python 3 cover
|
|
411
|
-
text = text.decode('ascii', 'ignore')
|
|
412
|
-
|
|
413
397
|
return text
|
|
414
398
|
|
|
415
399
|
def text(self):
|
myokit/units.py
CHANGED
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
# This file is part of Myokit.
|
|
5
5
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
6
6
|
#
|
|
7
|
-
from __future__ import absolute_import, division
|
|
8
|
-
from __future__ import print_function, unicode_literals
|
|
9
|
-
|
|
10
7
|
import myokit
|
|
11
8
|
|
|
12
9
|
|
|
@@ -263,6 +260,7 @@ _rep('M')
|
|
|
263
260
|
_rep('mM')
|
|
264
261
|
_rep('mM^2')
|
|
265
262
|
_rep('mM^3')
|
|
263
|
+
_rep('mM^4')
|
|
266
264
|
_rep('uM')
|
|
267
265
|
_rep('1/mM/ms')
|
|
268
266
|
_rep('1/mM^2/ms')
|
|
@@ -284,6 +282,7 @@ _rep('S/F')
|
|
|
284
282
|
_rep('mS/uF')
|
|
285
283
|
_rep('mS/cm^2')
|
|
286
284
|
_rep('mS/mm^2')
|
|
285
|
+
_rep('L/F/s')
|
|
287
286
|
_rep('L/F/ms')
|
|
288
287
|
_rep('mA/cm^2')
|
|
289
288
|
# Capacitance
|
|
@@ -296,3 +295,6 @@ _rep('J/mol/K')
|
|
|
296
295
|
_rep('mJ/mol/K')
|
|
297
296
|
_rep('C/mol')
|
|
298
297
|
_rep('C/mmol')
|
|
298
|
+
_rep('J/K') # Boltzmann
|
|
299
|
+
_rep('J*s') # Planck
|
|
300
|
+
_rep('J*ms')
|