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
@@ -2,27 +2,15 @@
2
2
  #
3
3
  # Tests the model building API.
4
4
  #
5
+ # NOTE: THESE TESTS SHOULD SLOWLY BE MERGED INTO test_model, test_variable, etc
6
+ #
7
+ #
5
8
  # This file is part of Myokit.
6
9
  # See http://myokit.org for copyright, sharing, and licensing details.
7
10
  #
8
- from __future__ import absolute_import, division
9
- from __future__ import print_function, unicode_literals
10
-
11
11
  import myokit
12
12
  import unittest
13
13
 
14
- # Strings in Python 2 and 3
15
- try:
16
- basestring
17
- except NameError:
18
- basestring = str
19
-
20
- # Unit testing in Python 2 and 3
21
- try:
22
- unittest.TestCase.assertRaisesRegex
23
- except AttributeError:
24
- unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
25
-
26
14
  # Further model API tests are found in:
27
15
  # - test_dependency_checking.py
28
16
 
@@ -33,13 +21,23 @@ class ModelBuildTest(unittest.TestCase):
33
21
  # Create a model
34
22
  m = myokit.Model('LotkaVolterra')
35
23
 
36
- # Add the first component
24
+ # Add engine component
25
+ E = m.add_component('engine')
26
+ self.assertEqual(len(m), 1)
27
+ time = E.add_variable('time')
28
+ time.set_rhs(0)
29
+ self.assertIsNone(time.binding())
30
+ time.set_binding('time')
31
+ self.assertIsNotNone(time.binding())
32
+
33
+ # Add the first test component
37
34
  X = m.add_component('X')
35
+ self.assertNotEqual(E, X)
38
36
  self.assertEqual(X.qname(), 'X')
39
37
  self.assertEqual(X.parent(), m)
40
38
  self.assertIsInstance(X, myokit.Component)
41
39
  self.assertIn(X.qname(), m)
42
- self.assertEqual(len(m), 1)
40
+ self.assertEqual(len(m), 2)
43
41
 
44
42
  # Add variable a
45
43
  self.assertFalse(X.has_variable('a'))
@@ -111,7 +109,7 @@ class ModelBuildTest(unittest.TestCase):
111
109
  self.assertFalse(x.is_intermediary())
112
110
  self.assertFalse(x.is_constant())
113
111
  self.assertEqual(x.lhs(), myokit.Derivative(myokit.Name(x)))
114
- self.assertEqual(x.indice(), 0)
112
+ self.assertEqual(x.index(), 0)
115
113
 
116
114
  # Test demoting, promoting
117
115
  x.demote()
@@ -133,10 +131,32 @@ class ModelBuildTest(unittest.TestCase):
133
131
  self.assertFalse(x.is_constant())
134
132
  self.assertEqual(x.lhs(), myokit.Derivative(myokit.Name(x)))
135
133
 
134
+ # Set number initial value
135
+ x.demote()
136
+ x.promote(1)
137
+ self.assertEqual(x.initial_value(as_float=True), 1)
138
+
139
+ # Set constant expression initial value
140
+ x.set_initial_value(myokit.Name(b))
141
+ self.assertEqual(x.initial_value(as_float=True), 2)
142
+ self.assertEqual(x.initial_value(), myokit.Name(b))
143
+
144
+ # Non-constant expression initial value can be set, but isn't valid
145
+ m.validate()
146
+ b.promote()
147
+ self.assertRaisesRegex(
148
+ myokit.IntegrityError, 'not constant', m.validate)
149
+ b.demote()
150
+
151
+ # Set literal valued expression initial value
152
+ x.demote()
153
+ x.promote('1 + 2')
154
+ self.assertEqual(x.initial_value(as_float=True), 3)
155
+
136
156
  # Add second component, variables
137
157
  Y = m.add_component('Y')
138
158
  self.assertNotEqual(X, Y)
139
- self.assertEqual(len(m), 2)
159
+ self.assertEqual(len(m), 3)
140
160
  c = Y.add_variable('c')
141
161
  c.set_rhs(myokit.Minus(myokit.Name(a), myokit.Number(1)))
142
162
  d = Y.add_variable('d')
@@ -152,7 +172,7 @@ class ModelBuildTest(unittest.TestCase):
152
172
  myokit.Name(y)
153
173
  )
154
174
  ))
155
- x.set_state_value(10)
175
+ x.set_initial_value(10)
156
176
  self.assertEqual(x.rhs().code(), 'X.a * X.x - X.b * X.x * Y.y')
157
177
  y.set_rhs(myokit.Plus(
158
178
  myokit.Multiply(
@@ -163,14 +183,14 @@ class ModelBuildTest(unittest.TestCase):
163
183
  myokit.Name(y)
164
184
  )
165
185
  ))
166
- y.set_state_value(5)
186
+ y.set_initial_value(5)
167
187
  self.assertEqual(y.rhs().code(), '-Y.c * Y.y + Y.d * X.x * Y.y')
168
188
 
169
189
  # Add ano component, variables
170
190
  Z = m.add_component('Z')
171
191
  self.assertNotEqual(X, Z)
172
192
  self.assertNotEqual(Y, Z)
173
- self.assertEqual(len(m), 3)
193
+ self.assertEqual(len(m), 4)
174
194
  t = Z.add_variable('total')
175
195
  self.assertEqual(t.name(), 'total')
176
196
  self.assertEqual(t.qname(), 'Z.total')
@@ -185,18 +205,6 @@ class ModelBuildTest(unittest.TestCase):
185
205
  self.assertEqual(t.rhs().code(Y), 'X.x + y')
186
206
  self.assertEqual(t.rhs().code(Z), 'X.x + Y.y')
187
207
 
188
- # Add engine component
189
- E = m.add_component('engine')
190
- self.assertNotEqual(X, E)
191
- self.assertNotEqual(Y, E)
192
- self.assertNotEqual(Z, E)
193
- self.assertEqual(len(m), 4)
194
- time = E.add_variable('time')
195
- time.set_rhs(0)
196
- self.assertIsNone(time.binding())
197
- time.set_binding('time')
198
- self.assertIsNotNone(time.binding())
199
-
200
208
  # Check state
201
209
  state = [i for i in m.states()]
202
210
  self.assertEqual(len(state), 2)
@@ -277,10 +285,10 @@ class ModelBuildTest(unittest.TestCase):
277
285
 
278
286
  # Test dependency mapping
279
287
  def has(var, *dps):
280
- lst = vrs[m.get(var).lhs() if isinstance(var, basestring) else var]
288
+ lst = vrs[m.get(var).lhs() if isinstance(var, str) else var]
281
289
  self.assertEqual(len(lst), len(dps))
282
290
  for d in dps:
283
- d = m.get(d).lhs() if isinstance(d, basestring) else d
291
+ d = m.get(d).lhs() if isinstance(d, str) else d
284
292
  self.assertIn(d, lst)
285
293
 
286
294
  vrs = m.map_shallow_dependencies(omit_states=False)
@@ -355,16 +363,6 @@ class ModelBuildTest(unittest.TestCase):
355
363
  code2 = m.clone().code()
356
364
  self.assertEqual(code1, code2)
357
365
 
358
- def test_resolve(self):
359
- # Test if an error is raised when a variable can't be resolved.
360
-
361
- m = myokit.Model('Resolve')
362
- c = m.add_component('c')
363
- p = c.add_variable('p')
364
- q = c.add_variable('q')
365
- p.set_rhs('10 * q')
366
- self.assertRaises(myokit.ParseError, q.set_rhs, '10 * r')
367
-
368
366
  def test_scope(self):
369
367
  # Test if illegal references are detected.
370
368
 
@@ -436,56 +434,6 @@ class ModelBuildTest(unittest.TestCase):
436
434
  self.assertRaises(myokit.InvalidNameError, v1.add_variable, 'not')
437
435
  self.assertRaises(myokit.InvalidNameError, v1.add_variable, 'in')
438
436
 
439
- def test_unused_and_cycles(self):
440
- # Test unused variable and cycle detection.
441
-
442
- m = myokit.Model('LotkaVolterra')
443
- c0 = m.add_component('c0')
444
- t = c0.add_variable('time')
445
- t.set_rhs(myokit.Number(0))
446
- t.set_binding('time')
447
- c1 = m.add_component('c1')
448
- m.add_component('c2')
449
- c1_a = c1.add_variable('a')
450
- c1_b = c1.add_variable('b')
451
- c1_a.promote(1.0)
452
- c1_a.set_rhs(myokit.Multiply(myokit.Name(c1_a), myokit.Number(0.5)))
453
- c1_b.set_rhs(myokit.Multiply(myokit.Name(c1_a), myokit.Number(1.0)))
454
- # b is unused, test if found
455
- m.validate()
456
- w = m.warnings()
457
- self.assertEqual(len(w), 1)
458
- self.assertEqual(type(w[0]), myokit.UnusedVariableError)
459
- # b is used by c, c is unused, test if found
460
- c1_c = c1.add_variable('c')
461
- c1_c.set_rhs(myokit.Name(c1_b))
462
- m.validate()
463
- w = m.warnings()
464
- self.assertEqual(len(w), 2)
465
- self.assertEqual(type(w[0]), myokit.UnusedVariableError)
466
- self.assertEqual(type(w[1]), myokit.UnusedVariableError)
467
- # Test 1:1 cycle
468
- c1_b.set_rhs(myokit.Name(c1_b))
469
- self.assertRaises(myokit.CyclicalDependencyError, m.validate)
470
- # Test longer cycles
471
- c1_b.set_rhs(myokit.Multiply(myokit.Number(10), myokit.Name(c1_c)))
472
- self.assertRaises(myokit.CyclicalDependencyError, m.validate)
473
- # Reset
474
- c1_b.set_rhs(myokit.Multiply(myokit.Name(c1_a), myokit.Number(1.0)))
475
- m.validate()
476
- # Test cycle involving state variable
477
- c1_a.set_rhs(myokit.Name(c1_b))
478
- m.validate()
479
- c1_b.set_rhs(myokit.Multiply(myokit.Name(c1_a), myokit.Name(c1_b)))
480
- self.assertRaises(myokit.CyclicalDependencyError, m.validate)
481
- c1_b.set_rhs(myokit.Multiply(myokit.Name(c1_a), myokit.Name(c1_c)))
482
- c1_c.set_rhs(myokit.Multiply(myokit.Name(c1_a), myokit.Number(3)))
483
- m.validate()
484
- w = m.warnings()
485
- self.assertEqual(len(w), 0)
486
- c1_c.set_rhs(myokit.Multiply(myokit.Name(c1_a), myokit.Name(c1_b)))
487
- self.assertRaises(myokit.CyclicalDependencyError, m.validate)
488
-
489
437
 
490
438
  if __name__ == '__main__':
491
439
  unittest.main()
@@ -5,21 +5,12 @@
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
  from myokit.tests import TemporaryDirectory, OpenCL_FOUND
16
13
 
17
- # Strings in Python2 and Python3
18
- try:
19
- basestring
20
- except NameError:
21
- basestring = str
22
-
23
14
 
24
15
  @unittest.skipIf(not OpenCL_FOUND, 'OpenCL not found on this system.')
25
16
  class OpenCLTest(unittest.TestCase):
@@ -35,12 +26,12 @@ class OpenCLTest(unittest.TestCase):
35
26
  # Tests the method to query the current device
36
27
  self.assertIsInstance(
37
28
  myokit.OpenCL.current_info(), myokit.OpenCLPlatformInfo)
38
- self.assertIsInstance(myokit.OpenCL.current_info(True), basestring)
29
+ self.assertIsInstance(myokit.OpenCL.current_info(True), str)
39
30
 
40
31
  def test_info(self):
41
32
  # Tests the method to query the current device
42
33
  self.assertIsInstance(myokit.OpenCL.info(), myokit.OpenCLInfo)
43
- self.assertIsInstance(myokit.OpenCL.info(True), basestring)
34
+ self.assertIsInstance(myokit.OpenCL.info(True), str)
44
35
 
45
36
  def test_load_save_selection(self):
46
37
  # Tests the load_selection method
@@ -83,9 +74,9 @@ class OpenCLTest(unittest.TestCase):
83
74
  item = info[0]
84
75
  self.assertEqual(len(item), 3)
85
76
  platform, device, specs = item
86
- self.assertIsInstance(platform, basestring)
87
- self.assertIsInstance(device, basestring)
88
- self.assertIsInstance(specs, basestring)
77
+ self.assertIsInstance(platform, str)
78
+ self.assertIsInstance(device, str)
79
+ self.assertIsInstance(specs, str)
89
80
 
90
81
  def test_supported(self):
91
82
  # Tested as condition to get in, so must be true
@@ -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 unittest
12
9
 
13
10
  import myokit
@@ -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 unittest
12
9
  import numpy as np
13
10
 
@@ -16,12 +13,6 @@ import myokit
16
13
  from myokit.tests.ansic_event_based_pacing import AnsicEventBasedPacing
17
14
  from myokit.tests.ansic_fixed_form_pacing import AnsicFixedFormPacing
18
15
 
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
16
 
26
17
  class EventBasedPacingAnsicTest(unittest.TestCase):
27
18
  """
@@ -144,24 +135,11 @@ class FixedFormPacingAnsicTest(unittest.TestCase):
144
135
  import sys
145
136
  sys.exit(1)
146
137
 
147
- # Test input checking
148
- times = 1
149
- values = [1, 2]
150
- self.assertRaises(Exception, AnsicFixedFormPacing)
151
- self.assertRaises(Exception, AnsicFixedFormPacing, 1)
152
- self.assertRaises(Exception, AnsicFixedFormPacing, 1, 2)
153
- self.assertRaises(Exception, AnsicFixedFormPacing, [1], [2])
154
- self.assertRaises(
155
- Exception, AnsicFixedFormPacing, [1, 2], [2])
156
- self.assertRaises(
157
- Exception, AnsicFixedFormPacing, [2, 1], [2, 2])
158
- AnsicFixedFormPacing([1, 2], [1, 2])
159
-
160
138
  # Test with small lists
161
139
  values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
162
140
  times = [0, 0, 1, 1, 1, 2, 2, 2, 3, 4, 5, 7]
163
141
  values = list(range(len(times)))
164
- pacing = AnsicFixedFormPacing(times, values)
142
+ pacing = AnsicFixedFormPacing(myokit.TimeSeriesProtocol(times, values))
165
143
 
166
144
  def test(value, index):
167
145
  self.assertEqual(pacing.pace(value), index)
@@ -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 EventBasedPacingPythonTest(unittest.TestCase):
23
14
  """
@@ -6,9 +6,6 @@
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
-
12
9
  import os
13
10
  import unittest
14
11
 
@@ -17,18 +14,6 @@ import myokit.units
17
14
 
18
15
  from myokit.tests import DIR_DATA, TemporaryDirectory
19
16
 
20
- # Unit testing in Python 2 and 3
21
- try:
22
- unittest.TestCase.assertRaisesRegex
23
- except AttributeError:
24
- unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
25
-
26
- # Strings in Python 2 and 3
27
- try:
28
- basestring
29
- except NameError: # pragma: no python 2 cover
30
- basestring = str
31
-
32
17
 
33
18
  class TokenizerTest(unittest.TestCase):
34
19
  """
@@ -223,6 +208,7 @@ class PhasedParseTest(unittest.TestCase):
223
208
  """
224
209
  Tests several phases of parsing.
225
210
  """
211
+
226
212
  def test_segment_parsing(self):
227
213
  # Test :meth:`parse_model()`.
228
214
  from myokit._parsing import parse
@@ -907,29 +893,29 @@ class PhasedParseTest(unittest.TestCase):
907
893
  '[[script]]',
908
894
  )
909
895
  script = parse_script(code)
910
- self.assertIsInstance(script, basestring)
896
+ self.assertIsInstance(script, str)
911
897
  script = parse_script(''.join(code))
912
- self.assertIsInstance(script, basestring)
898
+ self.assertIsInstance(script, str)
913
899
 
914
900
  code = (
915
901
  '[[script]]\n',
916
902
  )
917
903
  script = parse_script(code)
918
- self.assertIsInstance(script, basestring)
904
+ self.assertIsInstance(script, str)
919
905
 
920
906
  code = (
921
907
  '[[script]]\n',
922
908
  'print("hi")',
923
909
  )
924
910
  script = parse_script(code)
925
- self.assertIsInstance(script, basestring)
911
+ self.assertIsInstance(script, str)
926
912
 
927
913
  code = (
928
914
  '[[script]]\n',
929
915
  'print("hi")\n',
930
916
  )
931
917
  script = parse_script(code)
932
- self.assertIsInstance(script, basestring)
918
+ self.assertIsInstance(script, str)
933
919
 
934
920
  # Not a script
935
921
  code = (
@@ -1229,7 +1215,12 @@ class PhasedParseTest(unittest.TestCase):
1229
1215
 
1230
1216
 
1231
1217
  class ModelParseTest(unittest.TestCase):
1218
+ """
1219
+ Test parsing models.
1220
+ """
1221
+
1232
1222
  def test_model_creation(self):
1223
+ # Basic model creation via the parser
1233
1224
  m = myokit.load_model(os.path.join(DIR_DATA, 'lr-1991.mmt'))
1234
1225
 
1235
1226
  # Test components
@@ -1263,36 +1254,14 @@ class ModelParseTest(unittest.TestCase):
1263
1254
  1,
1264
1255
  0.0057,
1265
1256
  0.0002]
1257
+ self.assertEqual(len(values), m.count_states())
1258
+
1259
+ # Test initial value parsing
1266
1260
  out = ', '.join([str(x) for x in m.states()])
1267
1261
  ref = ', '.join(states)
1268
1262
  self.assertEqual(ref, out)
1269
- for k, eq in enumerate(m.inits()):
1270
- self.assertEqual(eq.rhs.eval(), values[k])
1271
-
1272
- # Test state parsing / setting
1273
- m.set_state(values)
1274
- for k, eq in enumerate(m.inits()):
1275
- self.assertEqual(eq.rhs.eval(), values[k])
1276
- s = dict(zip(states, values))
1277
- m.set_state(s)
1278
- for k, eq in enumerate(m.inits()):
1279
- self.assertEqual(eq.rhs.eval(), values[k])
1280
- s = '\n'.join([str(a) + '=' + str(b) for a, b in s.items()])
1281
- m.set_state(s)
1282
- for k, eq in enumerate(m.inits()):
1283
- self.assertEqual(eq.rhs.eval(), values[k])
1284
-
1285
- # Test cloning
1286
- try:
1287
- m2 = m.clone()
1288
- except Exception as e:
1289
- s = m.code(line_numbers=True)
1290
- print('\n')
1291
- print(s)
1292
- print('-' * 80)
1293
- print(myokit.format_parse_error(e, s.splitlines()))
1294
- raise e
1295
- self.assertEqual(m.code(), m2.code())
1263
+ for val, ref in zip(m.initial_values(as_floats=True), values):
1264
+ self.assertEqual(val, ref)
1296
1265
 
1297
1266
  def test_unresolved_reference_error(self):
1298
1267
  # Test unresolved reference errors.
@@ -1354,19 +1323,21 @@ class ModelParseTest(unittest.TestCase):
1354
1323
  # Test evaluation
1355
1324
  x = m.get('test.x')
1356
1325
  y = m.get('test.y')
1357
- s = m.state()
1358
- i = m.get('membrane.V').indice()
1326
+ s = m.initial_values(as_floats=True)
1327
+ i = m.get('membrane.V').index()
1359
1328
  # Test x, xo, y, yo
1329
+
1330
+ v = myokit.Name(m.get('membrane.V'))
1360
1331
  s[i] = -80
1361
- m.set_state(s)
1332
+ m.set_initial_values(s)
1362
1333
  self.assertEqual(x.rhs().eval(), 3)
1363
1334
  self.assertEqual(y.rhs().eval(), 2)
1364
1335
  s[i] = -10
1365
- m.set_state(s)
1336
+ m.set_initial_values(s)
1366
1337
  self.assertEqual(x.rhs().eval(), 2)
1367
1338
  self.assertEqual(y.rhs().eval(), 2)
1368
1339
  s[i] = 30
1369
- m.set_state(s)
1340
+ m.set_initial_values(s)
1370
1341
  self.assertEqual(x.rhs().eval(), 1)
1371
1342
  self.assertEqual(y.rhs().eval(), 1)
1372
1343
  # Test code() output by cloning
@@ -1387,13 +1358,50 @@ class ModelParseTest(unittest.TestCase):
1387
1358
  dot(p) = 1
1388
1359
  dot(q) = 2
1389
1360
  """
1390
- myokit.parse(code)
1361
+ m = myokit.parse_model(code)
1362
+ self.assertEqual(m.get('c.p').initial_value(), myokit.Number(1))
1363
+ self.assertEqual(m.get('c.q').initial_value().code(), '10 * 2')
1364
+
1365
+ # initial expression
1366
+ code = """
1367
+ [[model]]
1368
+ c.q = 10 * 2 + c.p
1369
+ c.r = c.p + c.a
1370
+
1371
+ [engine]
1372
+ time = 0 bind time
1373
+
1374
+ [c]
1375
+ p = 0.5
1376
+ dot(q) = 2
1377
+ dot(r) = 1
1378
+ a = p + 1
1379
+ """
1380
+ m = myokit.parse_model(code)
1381
+ self.assertEqual(
1382
+ m.get('c.q').initial_value().code(), '10 * 2 + c.p')
1391
1383
 
1392
- # Non-literal value
1384
+ # initial expression with just literals
1385
+ code = """
1386
+ [[model]]
1387
+ c.q = 10 * exp(2)
1388
+
1389
+ [engine]
1390
+ time = 0 bind time
1391
+
1392
+ [c]
1393
+ p = 0.5
1394
+ dot(q) = 2
1395
+ """
1396
+ m = myokit.parse_model(code)
1397
+ self.assertEqual(
1398
+ m.get('c.q').initial_value().code(), '10 * exp(2)')
1399
+
1400
+ # non-existent variable in initial value
1393
1401
  code = """
1394
1402
  [[model]]
1395
1403
  c.p = 1.0
1396
- c.q = 10 * 2 + b
1404
+ c.q = 10 * 2 + c.b
1397
1405
 
1398
1406
  [engine]
1399
1407
  time = 0 bind time
@@ -1402,7 +1410,82 @@ class ModelParseTest(unittest.TestCase):
1402
1410
  dot(p) = 1
1403
1411
  dot(q) = 2
1404
1412
  """
1405
- self.assertRaises(myokit.ParseError, myokit.parse, code)
1413
+ self.assertRaisesRegex(
1414
+ myokit.ParseError, 'Unresolved reference', myokit.parse, code)
1415
+
1416
+ # initial expression using child variables should fail
1417
+ code = """
1418
+ [[model]]
1419
+ c.q = a
1420
+
1421
+ [engine]
1422
+ time = 0 bind time
1423
+
1424
+ [c]
1425
+ p = 0.5
1426
+ dot(q) = 2
1427
+ a = 10 * 2 + p
1428
+ """
1429
+ self.assertRaisesRegex(
1430
+ myokit.ParseError, 'Unresolved reference', myokit.parse, code)
1431
+
1432
+ # non-constant initial value
1433
+ code = """
1434
+ [[model]]
1435
+ c.p = engine.time
1436
+
1437
+ [engine]
1438
+ time = 0 bind time
1439
+
1440
+ [c]
1441
+ dot(p) = 1
1442
+ """
1443
+ self.assertRaisesRegex(
1444
+ myokit.ParseError, 'is not constant', myokit.parse, code)
1445
+
1446
+ # indirect non-constant initial value
1447
+ code = """
1448
+ [[model]]
1449
+ c.p = c.r
1450
+ c.q = 1
1451
+
1452
+ [engine]
1453
+ time = 0 bind time
1454
+
1455
+ [c]
1456
+ dot(p) = 1
1457
+ dot(q) = 2
1458
+ r = 2 * q
1459
+ """
1460
+ self.assertRaisesRegex(
1461
+ myokit.ParseError, 'is not constant', myokit.parse, code)
1462
+
1463
+ # looks like it shouldn't be constant, but it is!
1464
+ code = """
1465
+ [[model]]
1466
+ c.p = dot(c.p)
1467
+
1468
+ [engine]
1469
+ time = 0 bind time
1470
+
1471
+ [c]
1472
+ dot(p) = 0
1473
+ """
1474
+ # Treat all state variables as non-constant
1475
+ self.assertRaisesRegex(
1476
+ myokit.ParseError, 'is not constant', myokit.parse, code)
1477
+
1478
+ # Initial value cycles are caught in validation
1479
+ code = """
1480
+ [[model]]
1481
+ x.x = x.x
1482
+
1483
+ [x]
1484
+ dot(x) = x
1485
+ t = 0 bind time
1486
+ """
1487
+ self.assertRaisesRegex(
1488
+ myokit.ParseError, 'is not constant', myokit.parse, code)
1406
1489
 
1407
1490
  def test_aliases(self):
1408
1491
  code = """
@@ -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 unittest
12
9
  import re
13
10
  import time
@@ -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 pickle
12
9
  import unittest
13
10
 
@@ -15,12 +12,6 @@ import myokit
15
12
 
16
13
  from myokit.tests import WarningCollector
17
14
 
18
- # Unit testing in Python 2 and 3
19
- try:
20
- unittest.TestCase.assertRaisesRegex
21
- except AttributeError:
22
- unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
23
-
24
15
 
25
16
  class ProtocolTest(unittest.TestCase):
26
17
  """