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,20 +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 myokit
12
9
  import unittest
13
10
 
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
-
22
12
  class VarOwnerTest(unittest.TestCase):
23
13
  """
24
14
  Tests parts of :class:`myokit.VarOwner`.
@@ -58,7 +48,7 @@ class VarOwnerTest(unittest.TestCase):
58
48
  myokit.Name(y)
59
49
  )
60
50
  ))
61
- x.set_state_value(10)
51
+ x.set_initial_value(10)
62
52
  y.set_rhs(myokit.Plus(
63
53
  myokit.Multiply(
64
54
  myokit.PrefixMinus(myokit.Name(c)), myokit.Name(y)
@@ -67,7 +57,7 @@ class VarOwnerTest(unittest.TestCase):
67
57
  myokit.Multiply(myokit.Name(d), myokit.Name(x)), myokit.Name(y)
68
58
  )
69
59
  ))
70
- y.set_state_value(5)
60
+ y.set_initial_value(5)
71
61
  Z = m.add_component('Z')
72
62
  t = Z.add_variable('total')
73
63
  t.set_rhs(myokit.Plus(myokit.Name(x), myokit.Name(y)))
@@ -117,92 +107,92 @@ class VarOwnerTest(unittest.TestCase):
117
107
  m = myokit.Model('LotkaVolterra')
118
108
 
119
109
  # Add a variable 'a'
120
- X = m.add_component('X')
110
+ z = m.add_component('z')
121
111
 
122
112
  # Simplest case
123
- a = X.add_variable('a')
124
- self.assertEqual(X.count_variables(), 1)
125
- X.remove_variable(a)
126
- self.assertEqual(X.count_variables(), 0)
127
- self.assertRaises(Exception, X.remove_variable, a)
113
+ a = z.add_variable('a')
114
+ self.assertEqual(z.count_variables(), 1)
115
+ z.remove_variable(a)
116
+ self.assertEqual(z.count_variables(), 0)
117
+ self.assertRaises(Exception, z.remove_variable, a)
128
118
 
129
119
  # Test re-adding
130
- a = X.add_variable('a')
120
+ a = z.add_variable('a')
131
121
  a.set_rhs(myokit.Number(5))
132
- self.assertEqual(X.count_variables(), 1)
122
+ self.assertEqual(z.count_variables(), 1)
133
123
 
134
124
  # Test deleting dependent variables
135
- b = X.add_variable('b')
136
- self.assertEqual(X.count_variables(), 2)
125
+ b = z.add_variable('b')
126
+ self.assertEqual(z.count_variables(), 2)
137
127
  b.set_rhs(myokit.Plus(myokit.Number(3), myokit.Name(a)))
138
128
 
139
129
  # Test blocking of removal
140
- self.assertRaises(myokit.IntegrityError, X.remove_variable, a)
141
- self.assertEqual(X.count_variables(), 2)
130
+ self.assertRaises(myokit.IntegrityError, z.remove_variable, a)
131
+ self.assertEqual(z.count_variables(), 2)
142
132
 
143
133
  # Test removal in the right order
144
- X.remove_variable(b)
145
- self.assertEqual(X.count_variables(), 1)
146
- X.remove_variable(a)
147
- self.assertEqual(X.count_variables(), 0)
134
+ z.remove_variable(b)
135
+ self.assertEqual(z.count_variables(), 1)
136
+ z.remove_variable(a)
137
+ self.assertEqual(z.count_variables(), 0)
148
138
 
149
139
  # Test reference to current state variable values
150
- a = X.add_variable('a')
140
+ a = z.add_variable('a')
151
141
  a.set_rhs(myokit.Number(5))
152
142
  a.promote()
153
- b = X.add_variable('b')
143
+ b = z.add_variable('b')
154
144
  b.set_rhs(myokit.Plus(myokit.Number(3), myokit.Name(a)))
155
- self.assertRaises(myokit.IntegrityError, X.remove_variable, a)
156
- X.remove_variable(b)
157
- X.remove_variable(a)
158
- self.assertEqual(X.count_variables(), 0)
145
+ self.assertRaises(myokit.IntegrityError, z.remove_variable, a)
146
+ z.remove_variable(b)
147
+ z.remove_variable(a)
148
+ self.assertEqual(z.count_variables(), 0)
159
149
 
160
150
  # Test reference to current state variable values with "self"-ref
161
- a = X.add_variable('a')
151
+ a = z.add_variable('a')
162
152
  a.promote()
163
153
  a.set_rhs(myokit.Name(a))
164
- X.remove_variable(a)
154
+ z.remove_variable(a)
165
155
 
166
156
  # Test it doesn't interfere with normal workings
167
- a = X.add_variable('a')
157
+ a = z.add_variable('a')
168
158
  a.promote()
169
159
  a.set_rhs(myokit.Name(a))
170
- b = X.add_variable('b')
160
+ b = z.add_variable('b')
171
161
  b.set_rhs(myokit.Name(a))
172
- self.assertRaises(myokit.IntegrityError, X.remove_variable, a)
173
- X.remove_variable(b)
174
- X.remove_variable(a)
162
+ self.assertRaises(myokit.IntegrityError, z.remove_variable, a)
163
+ z.remove_variable(b)
164
+ z.remove_variable(a)
175
165
 
176
166
  # Test reference to dot
177
- a = X.add_variable('a')
167
+ a = z.add_variable('a')
178
168
  a.set_rhs(myokit.Number(5))
179
169
  a.promote()
180
- b = X.add_variable('b')
170
+ b = z.add_variable('b')
181
171
  b.set_rhs(myokit.Derivative(myokit.Name(a)))
182
- self.assertRaises(myokit.IntegrityError, X.remove_variable, a)
183
- X.remove_variable(b)
184
- X.remove_variable(a)
172
+ self.assertRaises(myokit.IntegrityError, z.remove_variable, a)
173
+ z.remove_variable(b)
174
+ z.remove_variable(a)
185
175
 
186
176
  # Test if orphaned
187
177
  self.assertIsNone(b.parent())
188
178
 
189
179
  # Test deleting variable with nested variables
190
- a = X.add_variable('a')
180
+ a = z.add_variable('a')
191
181
  b = a.add_variable('b')
192
182
  b.set_rhs(myokit.Plus(myokit.Number(2), myokit.Number(2)))
193
183
  a.set_rhs(myokit.Multiply(myokit.Number(3), myokit.Name(b)))
194
- self.assertRaises(myokit.IntegrityError, X.remove_variable, a)
184
+ self.assertRaises(myokit.IntegrityError, z.remove_variable, a)
195
185
  self.assertEqual(a.count_variables(), 1)
196
- self.assertEqual(X.count_variables(), 1)
186
+ self.assertEqual(z.count_variables(), 1)
197
187
 
198
188
  # Test recursive deleting
199
- X.remove_variable(a, recursive=True)
189
+ z.remove_variable(a, recursive=True)
200
190
  self.assertEqual(a.count_variables(), 0)
201
- self.assertEqual(X.count_variables(), 0)
191
+ self.assertEqual(z.count_variables(), 0)
202
192
 
203
193
  # Test deleting variable with nested variables that depend on each
204
194
  # other
205
- a = X.add_variable('a')
195
+ a = z.add_variable('a')
206
196
  b = a.add_variable('b')
207
197
  c = a.add_variable('c')
208
198
  d = a.add_variable('d')
@@ -211,12 +201,12 @@ class VarOwnerTest(unittest.TestCase):
211
201
  b.set_rhs('2 * a - d')
212
202
  c.set_rhs('a + b + d')
213
203
  d.set_rhs('3 * a')
214
- self.assertRaises(myokit.IntegrityError, X.remove_variable, a)
204
+ self.assertRaises(myokit.IntegrityError, z.remove_variable, a)
215
205
  self.assertEqual(a.count_variables(), 3)
216
- self.assertEqual(X.count_variables(), 1)
217
- X.remove_variable(a, recursive=True)
206
+ self.assertEqual(z.count_variables(), 1)
207
+ z.remove_variable(a, recursive=True)
218
208
  self.assertEqual(a.count_variables(), 0)
219
- self.assertEqual(X.count_variables(), 0)
209
+ self.assertEqual(z.count_variables(), 0)
220
210
 
221
211
  # Test if removed from model's label and binding lists
222
212
  m = myokit.Model()
@@ -236,6 +226,68 @@ class VarOwnerTest(unittest.TestCase):
236
226
  self.assertIs(m.binding('time'), None)
237
227
  self.assertIs(m.label('membrane_potential'), None)
238
228
 
229
+ # Test variable can't be removed if used in initial expression
230
+ m = myokit.Model()
231
+ c = m.add_component('c')
232
+ p = c.add_variable('p')
233
+ p.set_rhs(2)
234
+ x = c.add_variable('x')
235
+ x.set_rhs(1)
236
+ x.promote('1 + c.p')
237
+ self.assertRaises(myokit.IntegrityError, c.remove_variable, p)
238
+ q = c.add_variable('q')
239
+ q.set_rhs(10)
240
+ x.set_initial_value('1 / c.q')
241
+ c.remove_variable(p)
242
+ self.assertRaises(myokit.IntegrityError, c.remove_variable, q)
243
+ x.set_initial_value('sqrt(2)')
244
+ c.remove_variable(q)
245
+
246
+ # But it's OK if we're deleting a whole component
247
+ m = myokit.Model()
248
+ c = m.add_component('c')
249
+ p = c.add_variable('p')
250
+ p.set_rhs(2)
251
+ x = c.add_variable('x')
252
+ x.set_rhs(1)
253
+ x.promote('1 + c.p')
254
+ m.remove_component('c')
255
+
256
+ def test_remove_variable_with_alias(self):
257
+ # Test cloning of a variable with an alias after an add / remove event.
258
+
259
+ m = myokit.Model('AddRemoveClone')
260
+ c = m.add_component('c')
261
+ p = c.add_variable('p')
262
+ p.set_binding('time')
263
+ p.set_rhs(0)
264
+ q = c.add_variable('q')
265
+ q.set_rhs(12)
266
+ m.validate() # Raises error if not ok
267
+ m.clone() # Raises error if not ok
268
+ d = m.add_component('d')
269
+ d.add_alias('bert', p)
270
+ e = d.add_variable('e')
271
+ e.set_rhs('10 * bert')
272
+ m.validate()
273
+ m.clone()
274
+ d.add_alias('ernie', q)
275
+ m.validate()
276
+ m.clone()
277
+ c.remove_variable(q)
278
+ m.validate()
279
+ m.clone() # Will raise error if alias isn't deleted
280
+
281
+ def test_resolve(self):
282
+ # Test if an error is raised when a variable can't be resolved.
283
+
284
+ m = myokit.Model('Resolve')
285
+ c = m.add_component('c')
286
+ p = c.add_variable('p')
287
+ q = c.add_variable('q')
288
+ p.set_rhs('10 * q')
289
+ self.assertRaises(myokit.ParseError, q.set_rhs, '10 * r')
290
+
239
291
  def test_sequence_interface(self):
240
292
  # Test the sequence interface implementation
241
293
 
@@ -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 sys
13
10
  import unittest
@@ -16,8 +13,7 @@ import myokit
16
13
 
17
14
  from myokit.tests import TemporaryDirectory, WarningCollector
18
15
 
19
-
20
- debug = True
16
+ debug = False
21
17
 
22
18
 
23
19
  # Simple test
@@ -44,7 +40,7 @@ str=String value
44
40
  """
45
41
 
46
42
  # Config with empty paths and spaces
47
- config_paths_1 = """
43
+ config_paths = """
48
44
  [sundials]
49
45
  lib = five
50
46
  inc = three;four;
@@ -53,16 +49,6 @@ lib = one;; two point five;three;
53
49
  inc =
54
50
  """
55
51
 
56
- # Config with empty paths and " ;", which in Python 2 is ignored
57
- config_paths_2 = """
58
- [sundials]
59
- lib = five ; six
60
- inc = three;four;
61
- [opencl]
62
- lib = one ;; two point five ;three;
63
- inc =
64
- """
65
-
66
52
 
67
53
  class TestConfig(unittest.TestCase):
68
54
 
@@ -82,10 +68,10 @@ class TestConfig(unittest.TestCase):
82
68
  cls._compat_no_fd_capture = myokit.COMPAT_NO_FD_CAPTURE
83
69
  cls._date_format = myokit.DATE_FORMAT
84
70
  cls._time_format = myokit.TIME_FORMAT
85
- cls._force_pyside = myokit.FORCE_PYSIDE
86
- cls._force_pyside2 = myokit.FORCE_PYSIDE2
87
- cls._force_pyqt4 = myokit.FORCE_PYQT4
71
+ cls._force_pyqt6 = myokit.FORCE_PYQT6
88
72
  cls._force_pyqt5 = myokit.FORCE_PYQT5
73
+ cls._force_pyside6 = myokit.FORCE_PYSIDE6
74
+ cls._force_pyside2 = myokit.FORCE_PYSIDE2
89
75
  cls._sundials_lib = myokit.SUNDIALS_LIB
90
76
  cls._sundials_inc = myokit.SUNDIALS_INC
91
77
  cls._opencl_lib = myokit.OPENCL_LIB
@@ -114,10 +100,10 @@ class TestConfig(unittest.TestCase):
114
100
  myokit.COMPAT_NO_FD_CAPTURE = cls._compat_no_fd_capture
115
101
  myokit.DATE_FORMAT = cls._date_format
116
102
  myokit.TIME_FORMAT = cls._time_format
117
- myokit.FORCE_PYSIDE = cls._force_pyside
118
- myokit.FORCE_PYSIDE2 = cls._force_pyside2
119
- myokit.FORCE_PYQT4 = cls._force_pyqt4
103
+ myokit.FORCE_PYQT6 = cls._force_pyqt6
120
104
  myokit.FORCE_PYQT5 = cls._force_pyqt5
105
+ myokit.FORCE_PYSIDE6 = cls._force_pyside6
106
+ myokit.FORCE_PYSIDE2 = cls._force_pyside2
121
107
  myokit.SUNDIALS_LIB = cls._sundials_lib
122
108
  myokit.SUNDIALS_INC = cls._sundials_inc
123
109
  myokit.OPENCL_LIB = cls._opencl_lib
@@ -131,10 +117,10 @@ class TestConfig(unittest.TestCase):
131
117
  assert myokit.COMPAT_NO_FD_CAPTURE == cls._compat_no_fd_capture
132
118
  assert myokit.DATE_FORMAT != 'TEST_DATE_FORMAT'
133
119
  assert myokit.TIME_FORMAT != 'TEST_TIME_FORMAT'
134
- assert myokit.FORCE_PYSIDE == cls._force_pyside
135
- assert myokit.FORCE_PYSIDE2 == cls._force_pyside2
136
- assert myokit.FORCE_PYQT4 == cls._force_pyqt4
120
+ assert myokit.FORCE_PYQT6 == cls._force_pyqt6
137
121
  assert myokit.FORCE_PYQT5 == cls._force_pyqt5
122
+ assert myokit.FORCE_PYSIDE6 == cls._force_pyside6
123
+ assert myokit.FORCE_PYSIDE2 == cls._force_pyside2
138
124
  assert myokit.SUNDIALS_LIB != ['one', 'two']
139
125
  assert myokit.SUNDIALS_INC != ['three', 'four']
140
126
  assert myokit.OPENCL_LIB != ['five', 'six']
@@ -168,17 +154,17 @@ class TestConfig(unittest.TestCase):
168
154
  myokit.SUNDIALS_INC = []
169
155
  myokit.OPENCL_LIB = []
170
156
  myokit.OPENCL_INC = []
171
- myokit.FORCE_PYSIDE = myokit.FORCE_PYSIDE2 = False
172
- myokit.FORCE_PYQT4 = myokit.FORCE_PYQT5 = False
157
+ myokit.FORCE_PYSIDE6 = myokit.FORCE_PYSIDE2 = False
158
+ myokit.FORCE_PYQT6 = myokit.FORCE_PYQT5 = False
173
159
  with open(self._temp_dir.path('myokit.ini'), 'w') as f:
174
160
  f.write(config_basic)
175
161
  self._config_module._load()
176
162
  self.assertEqual(myokit.DATE_FORMAT, 'TEST_DATE_FORMAT')
177
163
  self.assertEqual(myokit.TIME_FORMAT, 'TEST_TIME_FORMAT')
178
- self.assertFalse(myokit.FORCE_PYSIDE)
179
- self.assertFalse(myokit.FORCE_PYSIDE2)
180
- self.assertFalse(myokit.FORCE_PYQT4)
164
+ self.assertFalse(myokit.FORCE_PYQT6)
181
165
  self.assertFalse(myokit.FORCE_PYQT5)
166
+ self.assertFalse(myokit.FORCE_PYSIDE6)
167
+ self.assertFalse(myokit.FORCE_PYSIDE2)
182
168
  self.assertEqual(myokit.SUNDIALS_LIB, ['one', 'two'])
183
169
  self.assertEqual(myokit.SUNDIALS_INC, ['three', 'four'])
184
170
  self.assertEqual(myokit.OPENCL_LIB, ['five', 'six'])
@@ -205,7 +191,7 @@ class TestConfig(unittest.TestCase):
205
191
  myokit.OPENCL_LIB = []
206
192
  myokit.OPENCL_INC = []
207
193
  with open(self._temp_dir.path('myokit.ini'), 'w') as f:
208
- f.write(config_paths_1)
194
+ f.write(config_paths)
209
195
  self._config_module._load()
210
196
  self.assertEqual(myokit.SUNDIALS_LIB, ['five'])
211
197
  self.assertEqual(myokit.SUNDIALS_INC, ['three', 'four'])
@@ -214,60 +200,41 @@ class TestConfig(unittest.TestCase):
214
200
  ['one', 'two point five', 'three'])
215
201
  self.assertEqual(myokit.OPENCL_INC, [])
216
202
 
217
- # Even if the list contains " ;", which Python 2's config parser treats
218
- # as a comment
219
- myokit.SUNDIALS_LIB = []
220
- myokit.SUNDIALS_INC = []
221
- myokit.OPENCL_LIB = []
222
- myokit.OPENCL_INC = []
223
- with open(self._temp_dir.path('myokit.ini'), 'w') as f:
224
- f.write(config_paths_2)
225
- if sys.hexversion < 0x03020000:
226
- self.assertRaises(ImportError, self._config_module._load)
227
- else:
228
- self._config_module._load()
229
- self.assertEqual(myokit.SUNDIALS_LIB, ['five', 'six'])
230
- self.assertEqual(myokit.SUNDIALS_INC, ['three', 'four'])
231
- self.assertEqual(
232
- myokit.OPENCL_LIB,
233
- ['one', 'two point five', 'three'])
234
- self.assertEqual(myokit.OPENCL_INC, [])
235
-
236
203
  def test_load_gui_backend(self):
237
204
  # Tests setting the GUI back end
238
205
 
239
206
  # Qt gui options
240
207
  with open(self._temp_dir.path('myokit.ini'), 'w') as f:
241
- f.write('[gui]\nbackend=pyqt4\n')
208
+ f.write('[gui]\nbackend=pyqt6\n')
242
209
  self._config_module._load()
243
- self.assertFalse(myokit.FORCE_PYSIDE)
244
- self.assertFalse(myokit.FORCE_PYSIDE2)
245
- self.assertTrue(myokit.FORCE_PYQT4)
210
+ self.assertTrue(myokit.FORCE_PYQT6)
246
211
  self.assertFalse(myokit.FORCE_PYQT5)
212
+ self.assertFalse(myokit.FORCE_PYSIDE6)
213
+ self.assertFalse(myokit.FORCE_PYSIDE2)
247
214
 
248
215
  with open(self._temp_dir.path('myokit.ini'), 'w') as f:
249
216
  f.write('[gui]\nbackend=pyqt5\n')
250
217
  self._config_module._load()
251
- self.assertFalse(myokit.FORCE_PYSIDE)
252
- self.assertFalse(myokit.FORCE_PYSIDE2)
253
- self.assertFalse(myokit.FORCE_PYQT4)
218
+ self.assertFalse(myokit.FORCE_PYQT6)
254
219
  self.assertTrue(myokit.FORCE_PYQT5)
220
+ self.assertFalse(myokit.FORCE_PYSIDE6)
221
+ self.assertFalse(myokit.FORCE_PYSIDE2)
255
222
 
256
223
  with open(self._temp_dir.path('myokit.ini'), 'w') as f:
257
- f.write('[gui]\nbackend=pyside\n')
224
+ f.write('[gui]\nbackend=pyside6\n')
258
225
  self._config_module._load()
259
- self.assertTrue(myokit.FORCE_PYSIDE)
260
- self.assertFalse(myokit.FORCE_PYSIDE2)
261
- self.assertFalse(myokit.FORCE_PYQT4)
226
+ self.assertFalse(myokit.FORCE_PYQT6)
262
227
  self.assertFalse(myokit.FORCE_PYQT5)
228
+ self.assertTrue(myokit.FORCE_PYSIDE6)
229
+ self.assertFalse(myokit.FORCE_PYSIDE2)
263
230
 
264
231
  with open(self._temp_dir.path('myokit.ini'), 'w') as f:
265
232
  f.write('[gui]\nbackend=pyside2\n')
266
233
  self._config_module._load()
267
- self.assertFalse(myokit.FORCE_PYSIDE)
268
- self.assertTrue(myokit.FORCE_PYSIDE2)
269
- self.assertFalse(myokit.FORCE_PYQT4)
234
+ self.assertFalse(myokit.FORCE_PYQT6)
270
235
  self.assertFalse(myokit.FORCE_PYQT5)
236
+ self.assertFalse(myokit.FORCE_PYSIDE6)
237
+ self.assertTrue(myokit.FORCE_PYSIDE2)
271
238
 
272
239
  # Empty has no effect
273
240
  with open(self._temp_dir.path('myokit.ini'), 'w') as f:
@@ -275,10 +242,10 @@ class TestConfig(unittest.TestCase):
275
242
  with WarningCollector() as c:
276
243
  self._config_module._load()
277
244
  self.assertEqual(c.text(), '')
278
- self.assertFalse(myokit.FORCE_PYSIDE)
279
- self.assertTrue(myokit.FORCE_PYSIDE2)
280
- self.assertFalse(myokit.FORCE_PYQT4)
245
+ self.assertFalse(myokit.FORCE_PYQT6)
281
246
  self.assertFalse(myokit.FORCE_PYQT5)
247
+ self.assertFalse(myokit.FORCE_PYSIDE6)
248
+ self.assertTrue(myokit.FORCE_PYSIDE2)
282
249
 
283
250
  # Invalid raises warning
284
251
  with open(self._temp_dir.path('myokit.ini'), 'w') as f:
@@ -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
@@ -23,12 +21,6 @@ from myokit.tests import (
23
21
  WarningCollector,
24
22
  )
25
23
 
26
- # Unit testing in Python 2 and 3
27
- try:
28
- unittest.TestCase.assertRaisesRegex
29
- except AttributeError:
30
- unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
31
-
32
24
 
33
25
  class DataBlock1dTest(unittest.TestCase):
34
26
  """
@@ -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
@@ -23,21 +21,6 @@ from myokit.tests import (
23
21
  WarningCollector,
24
22
  )
25
23
 
26
- # Unit testing in Python 2 and 3
27
- try:
28
- unittest.TestCase.assertRaisesRegex
29
- except AttributeError:
30
- unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
31
-
32
-
33
- # Universal newline mode in Python 2 and 3
34
- def uopen(filename):
35
- try:
36
- return open(filename, 'r', newline=None)
37
- except TypeError:
38
- return open(filename, 'U')
39
-
40
-
41
24
  # Extra output
42
25
  debug = False
43
26
 
@@ -126,8 +109,10 @@ class DataLogTest(unittest.TestCase):
126
109
  'engine.time': [0, 5, 10, 15, 20],
127
110
  'membrane.V': [0, 50, 100, 150, 200]})
128
111
  d.set_time_key('engine.time')
129
- with WarningCollector():
112
+ with WarningCollector() as w:
130
113
  self.assertEqual(d.find(-5), d.find_after(-5))
114
+ self.assertIn('eprecated', w.text())
115
+ with WarningCollector():
131
116
  self.assertEqual(d.find(0), d.find_after(0))
132
117
  self.assertEqual(d.find(2), d.find_after(2))
133
118
  self.assertEqual(d.find(5), d.find_after(5))
@@ -1393,12 +1378,12 @@ class DataLogTest(unittest.TestCase):
1393
1378
  with TemporaryDirectory() as td:
1394
1379
  fname = td.path('test.csv')
1395
1380
  d.save_csv(fname, order=['a.b', 'c.d', 'e.f'])
1396
- with uopen(fname) as f:
1381
+ with open(fname, 'r', newline=None) as f:
1397
1382
  header = f.readline()
1398
1383
  self.assertEqual(header, '"a.b","c.d","e.f"\n')
1399
1384
 
1400
1385
  d.save_csv(fname, order=['e.f', 'a.b', 'c.d'])
1401
- with uopen(fname) as f:
1386
+ with open(fname, 'r', newline=None) as f:
1402
1387
  header = f.readline()
1403
1388
  self.assertEqual(header, '"e.f","a.b","c.d"\n')
1404
1389
 
@@ -1420,7 +1405,7 @@ class DataLogTest(unittest.TestCase):
1420
1405
  with TemporaryDirectory() as td:
1421
1406
  fname = td.path('test.csv')
1422
1407
  d.save_csv(fname)
1423
- with uopen(fname) as f:
1408
+ with open(fname, 'r', newline=None) as f:
1424
1409
  order = [x[1:-1] for x in f.readline().strip().split(',')]
1425
1410
  self.assertEqual(len(order), 9)
1426
1411
  self.assertEqual(order[0], 'e.t')
@@ -2181,12 +2166,22 @@ class DataLogTest(unittest.TestCase):
2181
2166
  self.assertEqual(d.length(), 100)
2182
2167
 
2183
2168
  def test_regularize(self):
2184
- # Test the regularize() method.
2169
+ # Test the deprecated regularize() method.
2185
2170
 
2186
2171
  d = myokit.DataLog(time='time')
2187
2172
  d['time'] = np.log(np.linspace(1, 25, 100))
2188
2173
  d['values'] = np.linspace(1, 25, 100)
2189
- e = d.regularize(dt=0.5)
2174
+
2175
+ has_scipy = True
2176
+ with WarningCollector() as w:
2177
+ try:
2178
+ e = d.regularize(dt=0.5)
2179
+ except ImportError:
2180
+ has_scipy = False
2181
+ self.assertIn('eprecated', w.text())
2182
+ if not has_scipy:
2183
+ return
2184
+
2190
2185
  self.assertEqual(len(e['time']), 7)
2191
2186
  x = np.array([0, 0.5, 1, 1.5, 2, 2.5, 3])
2192
2187
  self.assertTrue(np.all(e['time'] == x))
@@ -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
 
@@ -16,18 +13,6 @@ import myokit
16
13
 
17
14
  from myokit.tests import DIR_DATA
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
- # Strings in Python 2 and 3
26
- try:
27
- basestring
28
- except NameError: # pragma: no cover
29
- basestring = str
30
-
31
16
 
32
17
  # Extra output
33
18
  debug = False
@@ -55,7 +40,7 @@ class DepTest(unittest.TestCase):
55
40
  """
56
41
  # If a string lhs is given, interpret it as a variable name and get
57
42
  # the lhs of its defining equation
58
- if isinstance(key, basestring):
43
+ if isinstance(key, str):
59
44
  key = self.m.get(key)
60
45
  if isinstance(key, myokit.Variable):
61
46
  key = key.lhs()
@@ -64,7 +49,7 @@ class DepTest(unittest.TestCase):
64
49
  # convert it to a Name. Ensure no duplicates are given.
65
50
  deps = list(set(deps))
66
51
  for k, dep in enumerate(deps):
67
- if isinstance(dep, basestring):
52
+ if isinstance(dep, str):
68
53
  deps[k] = self.n(dep)
69
54
 
70
55
  # Get dep map
@@ -449,7 +434,7 @@ class DeepDepTest(DepTest):
449
434
  return self.has_lhs(depmap, lhs, *deps)
450
435
 
451
436
  def nhas(lhs):
452
- if isinstance(lhs, basestring):
437
+ if isinstance(lhs, str):
453
438
  lhs = self.m.get(lhs).lhs()
454
439
  self.assertNotIn(lhs, depmap)
455
440
 
@@ -594,7 +579,7 @@ class DeepDepTest(DepTest):
594
579
  return self.has_lhs(depmap, lhs, *deps)
595
580
 
596
581
  def nhas(lhs):
597
- if isinstance(lhs, basestring):
582
+ if isinstance(lhs, str):
598
583
  lhs = self.m.get(lhs).lhs()
599
584
  self.assertNotIn(lhs, depmap)
600
585
 
@@ -1360,10 +1345,10 @@ class SolvableOrderTest(DepTest):
1360
1345
 
1361
1346
  def before(lhs1, *lhs2s):
1362
1347
  """ Asserts lhs1 comes before lhs2 in the current component """
1363
- if isinstance(lhs1, basestring):
1348
+ if isinstance(lhs1, str):
1364
1349
  lhs1 = self.m.get(self.ccomp + '.' + lhs1).lhs()
1365
1350
  for lhs2 in lhs2s:
1366
- if isinstance(lhs2, basestring):
1351
+ if isinstance(lhs2, str):
1367
1352
  lhs2 = self.m.get(self.ccomp + '.' + lhs2).lhs()
1368
1353
  i1 = i2 = None
1369
1354
  for i, eq in enumerate(self.order[self.ccomp]):
@@ -1508,14 +1493,14 @@ class SolvableOrderTest(DepTest):
1508
1493
 
1509
1494
  def before(lhs1, *lhs2s):
1510
1495
  """ Asserts lhs2 comes before lhs1 """
1511
- if isinstance(lhs1, basestring):
1496
+ if isinstance(lhs1, str):
1512
1497
  if lhs1.startswith('dot('):
1513
1498
  lhs1 = myokit.Derivative(myokit.Name(
1514
1499
  self.m.get(lhs1[4:-1])))
1515
1500
  else:
1516
1501
  lhs1 = myokit.Name(self.m.get(lhs1))
1517
1502
  for lhs2 in lhs2s:
1518
- if isinstance(lhs2, basestring):
1503
+ if isinstance(lhs2, str):
1519
1504
  if lhs2.startswith('dot('):
1520
1505
  lhs2 = myokit.Derivative(myokit.Name(
1521
1506
  self.m.get(lhs2[4:-1])))