myokit 1.35.4__py3-none-any.whl → 1.36.1__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 (59) hide show
  1. myokit/__init__.py +5 -3
  2. myokit/__main__.py +9 -159
  3. myokit/_config.py +2 -2
  4. myokit/_expressions.py +6 -6
  5. myokit/_model_api.py +11 -7
  6. myokit/_myokit_version.py +1 -1
  7. myokit/_protocol.py +4 -0
  8. myokit/_sim/__init__.py +1 -0
  9. myokit/_sim/cvodessim.c +321 -177
  10. myokit/_sim/cvodessim.py +107 -43
  11. myokit/_sim/mcl.h +54 -0
  12. myokit/formats/__init__.py +63 -12
  13. myokit/formats/ansic/__init__.py +2 -1
  14. myokit/formats/ansic/_ewriter.py +159 -40
  15. myokit/formats/cpp/_ewriter.py +12 -1
  16. myokit/formats/cuda/_ewriter.py +15 -51
  17. myokit/formats/easyml/_ewriter.py +26 -54
  18. myokit/formats/heka/_patchmaster.py +15 -3
  19. myokit/formats/latex/_ewriter.py +103 -88
  20. myokit/formats/latex/_exporter.py +1 -1
  21. myokit/formats/mathml/_ewriter.py +2 -2
  22. myokit/formats/matlab/_ewriter.py +50 -28
  23. myokit/formats/opencl/_ewriter.py +61 -78
  24. myokit/formats/python/_ewriter.py +81 -50
  25. myokit/formats/stan/_ewriter.py +29 -37
  26. myokit/gui/source.py +1 -1
  27. myokit/lib/hh.py +3 -0
  28. myokit/lib/markov.py +6 -0
  29. myokit/tests/__init__.py +70 -0
  30. myokit/tests/data/decker.model +59 -59
  31. myokit/tests/test_formats.py +115 -7
  32. myokit/tests/test_formats_ansic.py +344 -0
  33. myokit/tests/test_formats_axon.py +17 -0
  34. myokit/tests/test_formats_cpp.py +97 -0
  35. myokit/tests/test_formats_cuda.py +226 -0
  36. myokit/tests/test_formats_easyml.py +169 -152
  37. myokit/tests/{test_formats_exporters.py → test_formats_exporters_run.py} +1 -69
  38. myokit/tests/test_formats_html.py +1 -3
  39. myokit/tests/test_formats_latex.py +211 -0
  40. myokit/tests/test_formats_mathml_content.py +13 -0
  41. myokit/tests/test_formats_mathml_presentation.py +54 -42
  42. myokit/tests/test_formats_matlab.py +218 -0
  43. myokit/tests/test_formats_opencl.py +206 -380
  44. myokit/tests/test_formats_python.py +557 -0
  45. myokit/tests/test_formats_stan.py +175 -0
  46. myokit/tests/test_formats_sympy.py +9 -2
  47. myokit/tests/test_lib_hh.py +36 -0
  48. myokit/tests/test_lib_plots.py +0 -16
  49. myokit/tests/test_model.py +21 -1
  50. myokit/tests/test_simulation_cvodes.py +137 -56
  51. myokit/tools.py +3 -2
  52. {myokit-1.35.4.dist-info → myokit-1.36.1.dist-info}/LICENSE.txt +1 -1
  53. {myokit-1.35.4.dist-info → myokit-1.36.1.dist-info}/METADATA +19 -8
  54. {myokit-1.35.4.dist-info → myokit-1.36.1.dist-info}/RECORD +57 -52
  55. {myokit-1.35.4.dist-info → myokit-1.36.1.dist-info}/WHEEL +1 -1
  56. myokit/tests/test_formats_expression_writers.py +0 -1281
  57. myokit/tests/test_formats_importers.py +0 -53
  58. {myokit-1.35.4.dist-info → myokit-1.36.1.dist-info}/entry_points.txt +0 -0
  59. {myokit-1.35.4.dist-info → myokit-1.36.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # Tests the expression writer for Matlab.
4
+ #
5
+ # This file is part of Myokit.
6
+ # See http://myokit.org for copyright, sharing, and licensing details.
7
+ #
8
+ import unittest
9
+
10
+ import myokit
11
+ import myokit.formats.matlab
12
+
13
+ from myokit import (
14
+ Number, PrefixPlus, PrefixMinus, Plus, Minus,
15
+ Multiply, Divide, Quotient, Remainder, Power, Sqrt,
16
+ Exp, Log, Log10, Sin, Cos, Tan, ASin, ACos, ATan, Floor, Ceil, Abs,
17
+ Not, And, Or, Equal, NotEqual, More, Less, MoreEqual, LessEqual,
18
+ If, Piecewise,
19
+ )
20
+
21
+ import myokit.tests
22
+
23
+
24
+ class MatlabExpressionWriterTest(myokit.tests.ExpressionWriterTestCase):
25
+ _name = 'matlab'
26
+ _target = myokit.formats.matlab.MatlabExpressionWriter
27
+
28
+ def test_number(self):
29
+ self.eq(Number(1), '1.0')
30
+ self.eq(Number(-2), '-2.0')
31
+ self.eq(Number(13, 'mV'), '13.0')
32
+
33
+ def test_name(self):
34
+ self.eq(self.a, 'a')
35
+ w = self._target()
36
+ w.set_lhs_function(lambda v: v.var().qname().upper())
37
+ self.assertEqual(w.ex(self.a), 'COMP.A')
38
+
39
+ def test_derivative(self):
40
+ self.eq(myokit.Derivative(self.a), 'dot(a)')
41
+
42
+ def test_partial_derivative(self):
43
+ e = myokit.PartialDerivative(self.a, self.b)
44
+ self.assertRaisesRegex(NotImplementedError, 'Partial', self.w.ex, e)
45
+
46
+ def test_initial_value(self):
47
+ e = myokit.InitialValue(self.a)
48
+ self.assertRaisesRegex(NotImplementedError, 'Initial', self.w.ex, e)
49
+
50
+ def test_prefix_plus(self):
51
+ # Inherited from Python writer
52
+ # Test with numbers
53
+ p = Number(11, 'kV')
54
+ self.eq(PrefixPlus(p), '+11.0')
55
+ self.eq(PrefixPlus(PrefixPlus(p)), '++11.0')
56
+ self.eq(PrefixPlus(Number('+1')), '+1.0')
57
+
58
+ a, b, c = self.abc
59
+ self.eq(PrefixPlus(Plus(a, b)), '+(a + b)')
60
+ self.eq(Divide(PrefixPlus(Plus(a, b)), c), '+(a + b) / c')
61
+ self.eq(Power(PrefixPlus(a), b), '(+a)^b')
62
+
63
+ def test_prefix_minus(self):
64
+ # Inherited from Python writer
65
+ # Test with numbers
66
+ p = Number(11, 'kV')
67
+ self.eq(PrefixMinus(p), '-11.0')
68
+ self.eq(PrefixMinus(PrefixMinus(p)), '--11.0')
69
+ self.eq(PrefixMinus(Number(-1)), '--1.0')
70
+
71
+ a, b, c = self.abc
72
+ self.eq(PrefixMinus(Minus(a, b)), '-(a - b)')
73
+ self.eq(Multiply(PrefixMinus(Plus(b, a)), c), '-(b + a) * c')
74
+ self.eq(Power(PrefixMinus(a), b), '(-a)^b')
75
+
76
+ def test_plus_minus(self):
77
+ # Inherited from Python writer
78
+ a, b, c = self.abc
79
+ self.eq(Plus(a, b), 'a + b')
80
+ self.eq(Plus(Plus(a, b), c), 'a + b + c')
81
+ self.eq(Plus(a, Plus(b, c)), 'a + (b + c)')
82
+
83
+ self.eq(Minus(a, b), 'a - b')
84
+ self.eq(Minus(Minus(a, b), c), 'a - b - c')
85
+ self.eq(Minus(a, Minus(b, c)), 'a - (b - c)')
86
+
87
+ self.eq(Minus(a, b), 'a - b')
88
+ self.eq(Plus(Minus(a, b), c), 'a - b + c')
89
+ self.eq(Minus(a, Plus(b, c)), 'a - (b + c)')
90
+ self.eq(Minus(Plus(a, b), c), 'a + b - c')
91
+ self.eq(Minus(a, Plus(b, c)), 'a - (b + c)')
92
+
93
+ def test_multiply_divide(self):
94
+ # Inherited from Python writer
95
+
96
+ a, b, c = self.abc
97
+ self.eq(Multiply(a, b), 'a * b')
98
+ # Left-to-right, so (a * b) * c is the same as a * b * c...
99
+ self.eq(Multiply(Multiply(a, b), c), 'a * b * c')
100
+ # ...but order-of-operations-wise, a * (b * c) is different!
101
+ self.eq(Multiply(a, Multiply(b, c)), 'a * (b * c)')
102
+ # Note that a user typing a * b * c results in (a * b) * c
103
+
104
+ self.eq(Divide(a, b), 'a / b')
105
+ self.eq(Divide(Divide(a, b), c), 'a / b / c')
106
+ self.eq(Divide(a, Divide(b, c)), 'a / (b / c)')
107
+
108
+ self.eq(Divide(Multiply(a, b), c), 'a * b / c')
109
+ self.eq(Multiply(Divide(a, b), c), 'a / b * c')
110
+ self.eq(Divide(a, Multiply(b, c)), 'a / (b * c)')
111
+ self.eq(Multiply(a, Divide(b, c)), 'a * (b / c)')
112
+
113
+ self.eq(Multiply(Minus(a, b), c), '(a - b) * c')
114
+ self.eq(Multiply(a, Plus(b, c)), 'a * (b + c)')
115
+ self.eq(Minus(Multiply(a, b), c), 'a * b - c')
116
+ self.eq(Plus(a, Multiply(b, c)), 'a + b * c')
117
+ self.eq(Divide(Plus(a, b), c), '(a + b) / c')
118
+ self.eq(Divide(a, Minus(b, c)), 'a / (b - c)')
119
+ self.eq(Plus(Divide(a, b), c), 'a / b + c')
120
+ self.eq(Minus(a, Divide(b, c)), 'a - b / c')
121
+ self.eq(Divide(a, Divide(b, c)), 'a / (b / c)')
122
+ self.eq(Divide(Divide(a, b), c), 'a / b / c')
123
+
124
+ def test_quotient(self):
125
+ a, b, c = self.abc
126
+ self.eq(Quotient(a, b), 'floor(a / b)')
127
+ self.eq(Quotient(Plus(a, c), b), 'floor((a + c) / b)')
128
+ self.eq(Quotient(Divide(a, c), b), 'floor(a / c / b)')
129
+ self.eq(Quotient(a, Divide(b, c)), 'floor(a / (b / c))')
130
+ self.eq(Multiply(Quotient(a, b), c), 'floor(a / b) * c')
131
+ # Bracket() method expects a PRODUCT level operation, so will add
132
+ # unnecessary brackets here
133
+ self.eq(Multiply(c, Quotient(a, b)), 'c * (floor(a / b))')
134
+
135
+ def test_remainder(self):
136
+ a, b, c = self.abc
137
+ self.eq(Remainder(a, b), 'mod(a, b)')
138
+ self.eq(Remainder(Plus(a, c), b), 'mod(a + c, b)')
139
+ self.eq(Multiply(Remainder(a, b), c), 'mod(a, b) * c')
140
+ # Bracket() method expects a PRODUCT level operation, so will add
141
+ # unnecessary brackets here
142
+ self.eq(Divide(c, Remainder(b, a)), 'c / (mod(b, a))')
143
+
144
+ def test_power(self):
145
+ a, b, c = self.abc
146
+ self.eq(Power(a, b), 'a^b')
147
+
148
+ # Like Myokit, Matlab sees a^b^c as (a^b)^c
149
+ self.eq(Power(Power(a, b), c), 'a^b^c')
150
+ self.eq(Power(a, Power(b, c)), 'a^(b^c)')
151
+
152
+ self.eq(Power(Plus(a, b), c), '(a + b)^c')
153
+ self.eq(Power(a, Minus(b, c)), 'a^(b - c)')
154
+ self.eq(Power(Multiply(a, b), c), '(a * b)^c')
155
+ self.eq(Power(a, Divide(b, c)), 'a^(b / c)')
156
+
157
+ def test_log(self):
158
+ a, b = self.ab
159
+ self.eq(Log(a), 'log(a)')
160
+ self.eq(Log10(a), 'log10(a)')
161
+ self.eq(Log(a, b), '(log(a) / log(b))')
162
+
163
+ def test_functions(self):
164
+ a, b = self.ab
165
+ self.eq(Sqrt(a), 'sqrt(a)')
166
+ self.eq(Exp(a), 'exp(a)')
167
+ self.eq(Sin(a), 'sin(a)')
168
+ self.eq(Cos(a), 'cos(a)')
169
+ self.eq(Tan(a), 'tan(a)')
170
+ self.eq(ASin(a), 'asin(a)')
171
+ self.eq(ACos(a), 'acos(a)')
172
+ self.eq(ATan(a), 'atan(a)')
173
+ self.eq(Floor(a), 'floor(a)')
174
+ self.eq(Ceil(a), 'ceil(a)')
175
+ self.eq(Abs(a), 'abs(a)')
176
+
177
+ def test_conditions(self):
178
+ a, b, c, d = self.abcd
179
+
180
+ self.eq(And(a, b), '(a && b)')
181
+ self.eq(Or(d, c), '(d || c)')
182
+ self.eq(Not(c), '(!c)')
183
+
184
+ self.eq(Equal(a, b), '(a == b)')
185
+ self.eq(NotEqual(a, b), '(a != b)')
186
+ self.eq(More(b, a), '(b > a)')
187
+ self.eq(Less(d, c), '(d < c)')
188
+ self.eq(MoreEqual(c, a), '(c >= a)')
189
+ self.eq(LessEqual(b, d), '(b <= d)')
190
+
191
+ self.eq(And(Equal(a, b), NotEqual(c, d)), '((a == b) && (c != d))')
192
+ self.eq(Or(More(d, c), Less(b, a)), '((d > c) || (b < a))')
193
+ self.eq(Not(Equal(d, d)), '(!(d == d))')
194
+ self.eq(Not(Or(Number(1), Number(2))), '(!(1.0 || 2.0))')
195
+
196
+ self.eq(Equal(Equal(Number(0), Number(0)), Number(0)),
197
+ '((0.0 == 0.0) == 0.0)')
198
+
199
+ def test_conditionals(self):
200
+ a, b, c, d = self.abcd
201
+ self.eq(If(Equal(a, b), d, c), 'ifthenelse((a == b), d, c)')
202
+ self.eq(Piecewise(NotEqual(d, c), b, a), 'ifthenelse((d != c), b, a)')
203
+ self.eq(Piecewise(Equal(a, b), c, Equal(a, d), Number(3), Number(4)),
204
+ 'ifthenelse((a == b), c, ifthenelse((a == d), 3.0, 4.0))')
205
+
206
+ def test_unset_condition_function(self):
207
+ # No ternary operator, so matlab must always have an ifthenelse
208
+ w = self._target()
209
+ self.assertRaisesRegex(
210
+ ValueError, 'needs a condition function',
211
+ w.set_condition_function, None)
212
+ self.assertRaisesRegex(
213
+ ValueError, 'needs a condition function',
214
+ w.set_condition_function, '')
215
+
216
+
217
+ if __name__ == '__main__':
218
+ unittest.main()