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.
Files changed (229) hide show
  1. myokit/__init__.py +9 -36
  2. myokit/__main__.py +76 -142
  3. myokit/_aux.py +62 -16
  4. myokit/_bin/example.mmt +1 -2
  5. myokit/_bin/install-win/menu.json +7 -7
  6. myokit/_config.py +22 -31
  7. myokit/_datablock.py +30 -74
  8. myokit/_datalog.py +49 -72
  9. myokit/_err.py +25 -24
  10. myokit/_expressions.py +50 -68
  11. myokit/_io.py +15 -27
  12. myokit/_model_api.py +453 -249
  13. myokit/_myokit_version.py +1 -5
  14. myokit/_parsing.py +38 -44
  15. myokit/_progress.py +5 -8
  16. myokit/_protocol.py +99 -9
  17. myokit/_sim/__init__.py +7 -24
  18. myokit/_sim/cable.c +6 -8
  19. myokit/_sim/cable.py +6 -8
  20. myokit/_sim/cmodel.h +125 -70
  21. myokit/_sim/cmodel.py +12 -14
  22. myokit/_sim/compiler.py +1 -4
  23. myokit/_sim/cvodessim.c +196 -118
  24. myokit/_sim/cvodessim.py +130 -103
  25. myokit/_sim/differential.hpp +4 -4
  26. myokit/_sim/fiber_tissue.c +4 -8
  27. myokit/_sim/fiber_tissue.py +11 -13
  28. myokit/_sim/jacobian.cpp +2 -2
  29. myokit/_sim/jacobian.py +11 -8
  30. myokit/_sim/mcl.h +53 -55
  31. myokit/_sim/opencl.py +21 -27
  32. myokit/_sim/openclsim.c +3 -7
  33. myokit/_sim/openclsim.cl +3 -3
  34. myokit/_sim/openclsim.py +49 -40
  35. myokit/_sim/pacing.h +36 -16
  36. myokit/_sim/rhs.c +6 -13
  37. myokit/_sim/rhs.py +5 -14
  38. myokit/_sim/sundials.py +1 -4
  39. myokit/_system.py +10 -16
  40. myokit/_unit.py +4 -13
  41. myokit/float.py +0 -3
  42. myokit/formats/__init__.py +8 -10
  43. myokit/formats/ansic/__init__.py +0 -3
  44. myokit/formats/ansic/_ewriter.py +2 -4
  45. myokit/formats/ansic/_exporter.py +1 -4
  46. myokit/formats/ansic/template/cable.c +4 -4
  47. myokit/formats/ansic/template/euler.c +5 -5
  48. myokit/formats/ansic/template/sim.c +6 -6
  49. myokit/formats/axon/__init__.py +1 -3
  50. myokit/formats/axon/_abf.py +12 -17
  51. myokit/formats/axon/_atf.py +5 -6
  52. myokit/formats/axon/_importer.py +0 -3
  53. myokit/formats/cellml/__init__.py +0 -3
  54. myokit/formats/cellml/_ewriter.py +3 -6
  55. myokit/formats/cellml/_exporter.py +3 -6
  56. myokit/formats/cellml/_importer.py +1 -4
  57. myokit/formats/cellml/v1/__init__.py +0 -4
  58. myokit/formats/cellml/v1/_api.py +8 -11
  59. myokit/formats/cellml/v1/_parser.py +2 -5
  60. myokit/formats/cellml/v1/_writer.py +2 -11
  61. myokit/formats/cellml/v2/__init__.py +0 -3
  62. myokit/formats/cellml/v2/_api.py +8 -17
  63. myokit/formats/cellml/v2/_parser.py +2 -5
  64. myokit/formats/cellml/v2/_writer.py +1 -4
  65. myokit/formats/channelml/__init__.py +0 -3
  66. myokit/formats/channelml/_importer.py +11 -21
  67. myokit/formats/cpp/__init__.py +1 -3
  68. myokit/formats/cpp/_ewriter.py +0 -3
  69. myokit/formats/cuda/__init__.py +0 -3
  70. myokit/formats/cuda/_ewriter.py +2 -4
  71. myokit/formats/cuda/_exporter.py +0 -3
  72. myokit/formats/cuda/template/kernel.cu +8 -5
  73. myokit/formats/easyml/__init__.py +0 -3
  74. myokit/formats/easyml/_ewriter.py +9 -11
  75. myokit/formats/easyml/_exporter.py +2 -5
  76. myokit/formats/html/__init__.py +0 -3
  77. myokit/formats/html/_exporter.py +0 -3
  78. myokit/formats/html/_flatten.py +5 -21
  79. myokit/formats/latex/__init__.py +0 -3
  80. myokit/formats/latex/_ewriter.py +1 -4
  81. myokit/formats/latex/_exporter.py +4 -6
  82. myokit/formats/mathml/__init__.py +0 -3
  83. myokit/formats/mathml/_ewriter.py +2 -11
  84. myokit/formats/mathml/_parser.py +4 -6
  85. myokit/formats/matlab/__init__.py +0 -3
  86. myokit/formats/matlab/_ewriter.py +1 -4
  87. myokit/formats/matlab/_exporter.py +2 -5
  88. myokit/formats/matlab/template/main.m +3 -2
  89. myokit/formats/opencl/__init__.py +0 -3
  90. myokit/formats/opencl/_ewriter.py +2 -4
  91. myokit/formats/opencl/_exporter.py +2 -5
  92. myokit/formats/opencl/template/cable.c +10 -10
  93. myokit/formats/opencl/template/kernel.cl +1 -1
  94. myokit/formats/opencl/template/minilog.py +1 -1
  95. myokit/formats/python/__init__.py +0 -3
  96. myokit/formats/python/_ewriter.py +2 -5
  97. myokit/formats/python/_exporter.py +0 -3
  98. myokit/formats/python/template/sim.py +14 -14
  99. myokit/formats/sbml/__init__.py +0 -3
  100. myokit/formats/sbml/_api.py +50 -44
  101. myokit/formats/sbml/_importer.py +1 -4
  102. myokit/formats/sbml/_parser.py +2 -5
  103. myokit/formats/stan/__init__.py +0 -3
  104. myokit/formats/stan/_ewriter.py +2 -4
  105. myokit/formats/stan/_exporter.py +2 -5
  106. myokit/formats/stan/template/cell.stan +3 -3
  107. myokit/formats/sympy/__init__.py +0 -3
  108. myokit/formats/sympy/_ereader.py +1 -4
  109. myokit/formats/sympy/_ewriter.py +2 -5
  110. myokit/formats/wcp/__init__.py +0 -3
  111. myokit/formats/wcp/_wcp.py +2 -8
  112. myokit/formats/xml/__init__.py +0 -3
  113. myokit/formats/xml/_exporter.py +0 -3
  114. myokit/formats/xml/_split.py +0 -3
  115. myokit/gui/__init__.py +80 -246
  116. myokit/gui/datablock_viewer.py +103 -86
  117. myokit/gui/datalog_viewer.py +214 -66
  118. myokit/gui/explorer.py +15 -21
  119. myokit/gui/ide.py +171 -144
  120. myokit/gui/progress.py +9 -9
  121. myokit/gui/source.py +406 -375
  122. myokit/gui/vargrapher.py +2 -12
  123. myokit/lib/deps.py +12 -13
  124. myokit/lib/guess.py +3 -4
  125. myokit/lib/hh.py +20 -18
  126. myokit/lib/markov.py +21 -20
  127. myokit/lib/multi.py +1 -3
  128. myokit/lib/plots.py +20 -9
  129. myokit/pacing.py +0 -3
  130. myokit/pype.py +7 -18
  131. myokit/tests/__init__.py +3 -6
  132. myokit/tests/ansic_event_based_pacing.py +1 -4
  133. myokit/tests/ansic_fixed_form_pacing.py +3 -6
  134. myokit/tests/data/beeler-1977-model-compare-b.mmt +2 -2
  135. myokit/tests/data/clancy-1999-fitting.mmt +1 -0
  136. myokit/tests/test_aux.py +13 -28
  137. myokit/tests/test_cellml_v1_api.py +4 -19
  138. myokit/tests/test_cellml_v1_parser.py +0 -15
  139. myokit/tests/test_cellml_v1_writer.py +0 -9
  140. myokit/tests/test_cellml_v2_api.py +4 -19
  141. myokit/tests/test_cellml_v2_parser.py +0 -15
  142. myokit/tests/test_cellml_v2_writer.py +0 -9
  143. myokit/tests/test_cmodel.py +16 -22
  144. myokit/tests/test_compiler_detection.py +1 -11
  145. myokit/tests/test_component.py +108 -56
  146. myokit/tests/test_config.py +34 -67
  147. myokit/tests/test_datablock.py +1 -9
  148. myokit/tests/test_datalog.py +19 -24
  149. myokit/tests/test_dependency_checking.py +8 -23
  150. myokit/tests/test_expressions.py +0 -9
  151. myokit/tests/test_float.py +1 -5
  152. myokit/tests/test_formats.py +0 -9
  153. myokit/tests/test_formats_axon.py +1 -9
  154. myokit/tests/test_formats_cellml.py +0 -15
  155. myokit/tests/test_formats_channelml.py +0 -15
  156. myokit/tests/test_formats_easyml.py +0 -14
  157. myokit/tests/test_formats_exporters.py +1 -16
  158. myokit/tests/test_formats_expression_writers.py +1 -17
  159. myokit/tests/test_formats_html.py +0 -3
  160. myokit/tests/test_formats_importers.py +1 -16
  161. myokit/tests/test_formats_mathml_content.py +0 -9
  162. myokit/tests/test_formats_mathml_presentation.py +0 -9
  163. myokit/tests/test_formats_opencl.py +0 -10
  164. myokit/tests/test_formats_sbml.py +0 -15
  165. myokit/tests/test_formats_sympy.py +0 -9
  166. myokit/tests/test_formats_wcp.py +1 -3
  167. myokit/tests/test_io.py +27 -27
  168. myokit/tests/test_jacobian_calculator.py +6 -14
  169. myokit/tests/test_jacobian_tracer.py +0 -9
  170. myokit/tests/test_lib_deps.py +0 -9
  171. myokit/tests/test_lib_guess.py +0 -9
  172. myokit/tests/test_lib_hh.py +18 -12
  173. myokit/tests/test_lib_markov.py +21 -13
  174. myokit/tests/test_lib_multi.py +0 -9
  175. myokit/tests/test_lib_plots.py +13 -8
  176. myokit/tests/test_meta.py +0 -3
  177. myokit/tests/test_model.py +390 -96
  178. myokit/tests/test_model_building.py +44 -96
  179. myokit/tests/test_opencl_info.py +5 -14
  180. myokit/tests/test_pacing_factory.py +0 -3
  181. myokit/tests/test_pacing_system_c.py +1 -23
  182. myokit/tests/test_pacing_system_py.py +0 -9
  183. myokit/tests/test_parsing.py +139 -56
  184. myokit/tests/test_progress_reporters.py +0 -3
  185. myokit/tests/test_protocol.py +0 -9
  186. myokit/tests/test_protocol_floating_point.py +1 -10
  187. myokit/tests/test_protocol_time_series.py +82 -0
  188. myokit/tests/test_pype.py +0 -9
  189. myokit/tests/test_quantity.py +0 -9
  190. myokit/tests/test_rhs_benchmarker.py +1 -9
  191. myokit/tests/test_sbml_api.py +27 -42
  192. myokit/tests/test_sbml_parser.py +4 -19
  193. myokit/tests/test_simulation_1d.py +45 -25
  194. myokit/tests/test_simulation_cvodes.py +321 -55
  195. myokit/tests/test_simulation_cvodes_from_disk.py +0 -3
  196. myokit/tests/test_simulation_fiber_tissue.py +39 -12
  197. myokit/tests/test_simulation_log_interval.py +1 -431
  198. myokit/tests/test_simulation_opencl.py +69 -48
  199. myokit/tests/test_simulation_opencl_log_interval.py +1 -3
  200. myokit/tests/test_simulation_opencl_vs_cvode.py +1 -10
  201. myokit/tests/test_simulation_opencl_vs_sim1d.py +1 -10
  202. myokit/tests/test_system_info.py +1 -11
  203. myokit/tests/test_tools.py +0 -9
  204. myokit/tests/test_unit.py +1 -10
  205. myokit/tests/test_user_functions.py +0 -10
  206. myokit/tests/test_variable.py +231 -27
  207. myokit/tools.py +5 -21
  208. myokit/units.py +5 -3
  209. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/METADATA +12 -15
  210. myokit-1.35.0.dist-info/RECORD +391 -0
  211. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/WHEEL +1 -1
  212. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/entry_points.txt +0 -1
  213. myokit/_exec_new.py +0 -15
  214. myokit/_exec_old.py +0 -15
  215. myokit/_sim/cvodesim.c +0 -1551
  216. myokit/_sim/cvodesim.py +0 -674
  217. myokit/_sim/icsim.cpp +0 -563
  218. myokit/_sim/icsim.py +0 -363
  219. myokit/_sim/psim.cpp +0 -656
  220. myokit/_sim/psim.py +0 -493
  221. myokit/lib/common.py +0 -1094
  222. myokit/tests/test_lib_common.py +0 -130
  223. myokit/tests/test_simulation_cvode.py +0 -612
  224. myokit/tests/test_simulation_ic.py +0 -108
  225. myokit/tests/test_simulation_p.py +0 -223
  226. myokit-1.33.9.dist-info/RECORD +0 -403
  227. /myokit/formats/opencl/template/{test → test.sh} +0 -0
  228. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/LICENSE.txt +0 -0
  229. {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
 
@@ -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(), basestring)
22
+ self.assertIsInstance(myokit.system(), str)
33
23
  with myokit.tools.capture():
34
24
  myokit.system(live_printing=True)
35
25
 
@@ -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 behaviour:
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
 
@@ -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
- from __future__ import absolute_import, division
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
- # Unit testing in Python 2 and 3
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.assertTrue(g.state_value() != 10)
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.indice)
289
- self.assertRaises(Exception, v.state_value)
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.indice(), 0)
298
- self.assertEqual(v.state_value(), 3)
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.indice)
308
- self.assertRaises(Exception, v.state_value)
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 test_set_state_value(self):
642
- # Test :meth:`Variable.set_state_value()`.
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.state_value(), 10)
652
- v.set_state_value(12)
653
- self.assertEqual(v.state_value(), 12)
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.set_state_value, 3)
786
+ Exception, 'Only state variables', v.set_initial_value, 3)
659
787
  self.assertRaisesRegex(
660
- Exception, 'Only state variables', w.set_state_value, 3)
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.NonLiteralValueError, v.set_state_value, w.lhs())
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
- from __future__ import absolute_import, division
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(object):
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(object):
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')