myokit 1.36.1__py3-none-any.whl → 1.37.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 (65) hide show
  1. myokit/__init__.py +6 -19
  2. myokit/_aux.py +4 -0
  3. myokit/_datablock.py +55 -65
  4. myokit/_datalog.py +42 -7
  5. myokit/_err.py +26 -3
  6. myokit/_expressions.py +241 -127
  7. myokit/_model_api.py +19 -13
  8. myokit/_myokit_version.py +1 -1
  9. myokit/_sim/jacobian.py +3 -3
  10. myokit/_sim/openclsim.py +5 -5
  11. myokit/_sim/rhs.py +1 -1
  12. myokit/formats/__init__.py +4 -9
  13. myokit/formats/ansic/_ewriter.py +4 -20
  14. myokit/formats/axon/_abf.py +11 -4
  15. myokit/formats/diffsl/__init__.py +60 -0
  16. myokit/formats/diffsl/_ewriter.py +145 -0
  17. myokit/formats/diffsl/_exporter.py +435 -0
  18. myokit/formats/heka/_patchmaster.py +345 -115
  19. myokit/formats/opencl/_ewriter.py +3 -42
  20. myokit/formats/opencl/template/minilog.py +1 -1
  21. myokit/formats/sympy/_ereader.py +2 -1
  22. myokit/formats/wcp/_wcp.py +3 -3
  23. myokit/gui/datalog_viewer.py +28 -9
  24. myokit/lib/markov.py +2 -2
  25. myokit/lib/plots.py +4 -4
  26. myokit/tests/data/formats/wcp-file-empty.wcp +0 -0
  27. myokit/tests/data/io/bad1d-2-no-header.zip +0 -0
  28. myokit/tests/data/io/bad1d-3-no-data.zip +0 -0
  29. myokit/tests/data/io/bad1d-4-not-a-zip.zip +1 -105
  30. myokit/tests/data/io/bad1d-5-bad-data-type.zip +0 -0
  31. myokit/tests/data/io/bad1d-6-time-too-short.zip +0 -0
  32. myokit/tests/data/io/bad1d-7-0d-too-short.zip +0 -0
  33. myokit/tests/data/io/bad1d-8-1d-too-short.zip +0 -0
  34. myokit/tests/data/io/bad2d-2-no-header.zip +0 -0
  35. myokit/tests/data/io/bad2d-3-no-data.zip +0 -0
  36. myokit/tests/data/io/bad2d-4-not-a-zip.zip +1 -105
  37. myokit/tests/data/io/bad2d-5-bad-data-type.zip +0 -0
  38. myokit/tests/data/io/bad2d-8-2d-too-short.zip +0 -0
  39. myokit/tests/data/io/block1d.mmt +187 -0
  40. myokit/tests/data/io/datalog-18-duplicate-keys.csv +4 -0
  41. myokit/tests/test_aux.py +4 -0
  42. myokit/tests/test_datablock.py +16 -16
  43. myokit/tests/test_datalog.py +24 -1
  44. myokit/tests/test_expressions.py +532 -251
  45. myokit/tests/test_formats_ansic.py +6 -18
  46. myokit/tests/test_formats_cpp.py +0 -5
  47. myokit/tests/test_formats_cuda.py +7 -15
  48. myokit/tests/test_formats_diffsl.py +728 -0
  49. myokit/tests/test_formats_easyml.py +4 -9
  50. myokit/tests/test_formats_exporters_run.py +3 -0
  51. myokit/tests/test_formats_latex.py +10 -11
  52. myokit/tests/test_formats_matlab.py +0 -8
  53. myokit/tests/test_formats_opencl.py +0 -29
  54. myokit/tests/test_formats_python.py +2 -19
  55. myokit/tests/test_formats_stan.py +0 -13
  56. myokit/tests/test_formats_sympy.py +3 -3
  57. myokit/tests/test_formats_wcp.py +15 -0
  58. myokit/tests/test_model.py +20 -20
  59. myokit/tests/test_parsing.py +19 -0
  60. {myokit-1.36.1.dist-info → myokit-1.37.1.dist-info}/METADATA +1 -1
  61. {myokit-1.36.1.dist-info → myokit-1.37.1.dist-info}/RECORD +65 -58
  62. {myokit-1.36.1.dist-info → myokit-1.37.1.dist-info}/LICENSE.txt +0 -0
  63. {myokit-1.36.1.dist-info → myokit-1.37.1.dist-info}/WHEEL +0 -0
  64. {myokit-1.36.1.dist-info → myokit-1.37.1.dist-info}/entry_points.txt +0 -0
  65. {myokit-1.36.1.dist-info → myokit-1.37.1.dist-info}/top_level.txt +0 -0
@@ -31,27 +31,6 @@ class OpenCLExpressionWriter(CBasedExpressionWriter):
31
31
  self._sp = (precision == myokit.SINGLE_PRECISION)
32
32
  self._nm = bool(native_math)
33
33
 
34
- def _exc(self, e):
35
- """Returns ``ex(e)`` if ``e`` is a Condition, else ``ex(e != 0)``."""
36
- # Can be removed after https://github.com/myokit/myokit/issues/1056
37
- if isinstance(e, myokit.Condition):
38
- return self.ex(e)
39
- return self.ex(myokit.NotEqual(e, myokit.Number(0)))
40
-
41
- def _ex_infix_comparison(self, e, op):
42
- """Handles ex() for infix condition operators (==, !=, > etc.)."""
43
- # Can be removed after https://github.com/myokit/myokit/issues/1056
44
- c1 = isinstance(e[0], myokit.Condition)
45
- c2 = isinstance(e[1], myokit.Condition)
46
- if (c1 and c2) or not (c1 or c2):
47
- return f'({self.ex(e[0])} {op} {self.ex(e[1])})'
48
- else:
49
- return f'({self._exc(e[0])} {op} {self._exc(e[1])})'
50
-
51
- def _ex_infix_logical(self, e, op):
52
- # Can be removed after https://github.com/myokit/myokit/issues/1056
53
- return f'({self._exc(e[0])} {op} {self._exc(e[1])})'
54
-
55
34
  #def _ex_name(self, e):
56
35
  #def _ex_derivative(self, e):
57
36
  #def _ex_initial_value(self, e):
@@ -126,25 +105,7 @@ class OpenCLExpressionWriter(CBasedExpressionWriter):
126
105
 
127
106
  #def _ex_and(self, e):
128
107
  #def _ex_or(self, e):
129
-
130
- def _ex_not(self, e):
131
- # Can be removed after https://github.com/myokit/myokit/issues/1056
132
- return f'(!{self._exc(e[0])})'
133
-
134
- def _ex_if(self, e):
135
- # Can be removed after https://github.com/myokit/myokit/issues/1056
136
- _if, _then, _else = self._exc(e._i), self.ex(e._t), self.ex(e._e)
137
- return f'({_if} ? {_then} : {_else})'
138
-
139
- def _ex_piecewise(self, e):
140
- # Can be removed after https://github.com/myokit/myokit/issues/1056
141
- _ifs = [self._exc(x) for x in e._i]
142
- _thens = [self.ex(x) for x in e._e]
143
- s = []
144
- n = len(_ifs)
145
- for _if, _then in zip(_ifs, _thens):
146
- s.append(f'({_if} ? {_then} : ')
147
- s.append(_thens[-1])
148
- s.append(')' * len(_ifs))
149
- return ''.join(s)
108
+ #def _ex_not(self, e):
109
+ #def _ex_if(self, e):
110
+ #def _ex_piecewise(self, e):
150
111
 
@@ -177,7 +177,7 @@ class DataLog(OrderedDict):
177
177
  import numpy as np
178
178
  out = DataLog()
179
179
  for k, d in self.items():
180
- out[k] = np.array(d, copy=False)
180
+ out[k] = np.asarray(d)
181
181
  return out
182
182
 
183
183
  def save_csv(self, filename, pad=None):
@@ -156,7 +156,8 @@ class SymPyExpressionReader:
156
156
  def _ex_abs(self, e):
157
157
  return myokit.Abs(self.ex(e.args[0]))
158
158
 
159
- def _ex_not(self, e):
159
+ def _ex_not(self, e): # pragma: no cover
160
+ # Sympy turns not(a == b) into a != b etc., so can't test!
160
161
  return myokit.Not(self.ex(e.args[0]))
161
162
 
162
163
  def _ex_equal(self, e):
@@ -241,7 +241,7 @@ class WcpFile(myokit.formats.SweepSource):
241
241
 
242
242
  def _channel_id(self, channel_id):
243
243
  """ Checks an int or str channel id and returns a valid int. """
244
- if self._nr == 0: # pragma: no cover
244
+ if self._nr == 0:
245
245
  raise KeyError(f'Channel {channel_id} not found (empty file).')
246
246
 
247
247
  # Handle string
@@ -314,7 +314,7 @@ class WcpFile(myokit.formats.SweepSource):
314
314
 
315
315
  # Create log
316
316
  log = myokit.DataLog()
317
- if self._nr == 0: # pragma: no cover
317
+ if self._nr == 0:
318
318
  return log
319
319
 
320
320
  # Get channel names
@@ -433,7 +433,7 @@ class WcpFile(myokit.formats.SweepSource):
433
433
  return self._nr
434
434
 
435
435
  def records(self):
436
- """ Deprecated alias of :meth:`sweep_count`. """
436
+ """ Deprecated alias of :meth:`record_count`. """
437
437
  # Deprecated since 2023-06-22
438
438
  import warnings
439
439
  warnings.warn(
@@ -641,13 +641,18 @@ class SweepSourceTab(GraphTabWidget):
641
641
  def __init__(self, parent, source):
642
642
  super().__init__(parent)
643
643
 
644
- # Add A/D
645
- for i in range(source.channel_count()):
646
- self._add_graph_tab(source, i)
644
+ if source.sweep_count() > 0:
645
+ # Must have this condition to avoid getting exceptions with e.g.
646
+ # the empty WCP file in the test data set.
647
+ # myokit log myokit/tests/data/formats/wcp-file-empty.wcp
647
648
 
648
- # Add D/A
649
- for i in range(source.da_count()):
650
- self._add_graph_tab(source, i, True)
649
+ # Add A/D
650
+ for i in range(source.channel_count()):
651
+ self._add_graph_tab(source, i)
652
+
653
+ # Add D/A
654
+ for i in range(source.da_count()):
655
+ self._add_graph_tab(source, i, True)
651
656
 
652
657
  # Add meta data
653
658
  self._add_meta_tab(source)
@@ -846,6 +851,10 @@ class CsvTab(GraphTabWidget):
846
851
  for k in keys:
847
852
  self.addTab(self.create_graph_tab(k, groups.get(k)), k)
848
853
 
854
+ # Add meta data tab
855
+ if log.meta:
856
+ self.addTab(self.create_meta_tab(log.meta), 'info')
857
+
849
858
  def create_graph_tab(self, key, indices=None):
850
859
  """ Creates a widget displaying the data stored under ``key``. """
851
860
  widget = QtWidgets.QWidget(self)
@@ -875,6 +884,18 @@ class CsvTab(GraphTabWidget):
875
884
  self._axes.append(axes)
876
885
  return widget
877
886
 
887
+ def create_meta_tab(self, meta):
888
+ """
889
+ Returns a tab showing information from a DataLog meta data object.
890
+ """
891
+ widget = QtWidgets.QTextEdit(self)
892
+ lines = []
893
+ for k, v in meta.items():
894
+ lines.append(f'{k}: {v}')
895
+ widget.setText('\n'.join(lines))
896
+ widget.setReadOnly(True)
897
+ return widget
898
+
878
899
 
879
900
  class MatTab(GraphTabWidget):
880
901
  """ A widget displaying a .mat file. """
@@ -992,9 +1013,7 @@ class TxtTab(GraphTabWidget):
992
1013
  return
993
1014
 
994
1015
  def create_graph_tab(self, time, data):
995
- """
996
- Creates a widget displaying a time series.
997
- """
1016
+ """ Creates a widget displaying a time series. """
998
1017
  widget = QtWidgets.QWidget(self)
999
1018
  # Create figure
1000
1019
  figure = matplotlib.figure.Figure()
myokit/lib/markov.py CHANGED
@@ -1077,7 +1077,7 @@ class AnalyticalSimulation:
1077
1077
  y0 = PI.dot(self._state.reshape((n, 1)))
1078
1078
 
1079
1079
  # Reshape times array
1080
- times = np.array(times, copy=False).reshape((len(times),))
1080
+ times = np.asarray(times).reshape((len(times),))
1081
1081
 
1082
1082
  # Calculate state
1083
1083
  x = P.dot(y0 * np.exp(times * E))
@@ -1223,7 +1223,7 @@ class DiscreteSimulation:
1223
1223
 
1224
1224
  Returns a discretized state ``y`` where ``sum(y) = nchannels``.
1225
1225
  """
1226
- x = np.array(x, copy=False, dtype=float)
1226
+ x = np.asarray(x, dtype=float)
1227
1227
  if (np.abs(1 - np.sum(x))) > 1e-6:
1228
1228
  raise ValueError(
1229
1229
  'The sum of fractions in the state to be discretized must'
myokit/lib/plots.py CHANGED
@@ -62,28 +62,28 @@ def simulation_times(
62
62
  def stair(ax, time, realtime, evaluations):
63
63
  if time is None:
64
64
  raise ValueError('This plotting mode requires "time" to be set.')
65
- time = np.array(time, copy=False)
65
+ time = np.asarray(time)
66
66
  step = np.arange(0, len(time))
67
67
  ax.step(time, step, label=label)
68
68
 
69
69
  def stair_inverse(ax, time, realtime, evaluations):
70
70
  if time is None:
71
71
  raise ValueError('This plotting mode requires "time" to be set.')
72
- time = np.array(time, copy=False)
72
+ time = np.asarray(time)
73
73
  step = np.arange(0, len(time))
74
74
  ax.step(step, time, label=label)
75
75
 
76
76
  def load(ax, time, realtime, evaluations):
77
77
  if time is None:
78
78
  raise ValueError('This plotting mode requires "time" to be set.')
79
- time = np.array(time, copy=False)
79
+ time = np.asarray(time)
80
80
  size = np.log(1 / (time[1:] - time[:-1]))
81
81
  ax.step(time[1:], size, label=label)
82
82
 
83
83
  def histo(ax, time, realtime, evaluations):
84
84
  if time is None:
85
85
  raise ValueError('This plotting mode requires "time" to be set.')
86
- time = np.array(time, copy=False)
86
+ time = np.asarray(time)
87
87
  zero = float(time[0])
88
88
  bucket_w = (time[-1] - zero) / nbuckets
89
89
  bucket_x = np.zeros(nbuckets)
Binary file
Binary file
@@ -1,105 +1 @@
1
- [[model]]
2
- name: beeler-1977
3
- author: Michael Clerx
4
- desc: """
5
- The 1997 Beeler Reuter model of the AP in ventricular myocytes
6
-
7
- Reference:
8
-
9
- Beeler, Reuter (1976) Reconstruction of the action potential of ventricular
10
- myocardial fibres
11
- """
12
- f(x) = 4 * x
13
- # Initial values:
14
- membrane.V = -84.622
15
- calcium.Cai = 2e-7
16
- ina.m = 0.01
17
- ina.h = 0.99
18
- ina.j = 0.98
19
- isi.d = 0.003
20
- isi.f = 0.99
21
- ix1.x1 = 0.0004
22
-
23
-
24
- [engine]
25
- time = 0 in [ms] bind time
26
- pace = 0 bind pace
27
-
28
- [membrane]
29
- C = 1 [uF/cm^2] : The membrane capacitance
30
- dot(V) = -(1/C) * (i_ion + i_stim)
31
- in [mV]
32
- label membrane_potential
33
- desc: Membrane potential
34
- i_ion = ik1.IK1 + ix1.Ix1 + ina.INa + isi.Isi
35
- label cellular_current
36
- in [uA/cm^2]
37
- i_stim = engine.pace * amplitude
38
- amplitude = -25 [uA/cm^2]
39
-
40
- [ina]
41
- use membrane.V as V
42
- gNaBar = 4 [mS/cm^2]
43
- gNaC = 0.003 [mS/cm^2]
44
- ENa = 50 [mV]
45
- INa = (gNaBar * m^3 * h * j + gNaC) * (V - ENa)
46
- in [uA/cm^2]
47
- desc: The excitatory inward sodium current
48
- dot(m) = alpha * (1 - m) - beta * m
49
- alpha = (V + 47) / (1 - exp(-0.1 * (V + 47)))
50
- beta = 40 * exp(-0.056 * (V + 72))
51
- desc: The activation parameter
52
- dot(h) = alpha * (1 - h) - beta * h
53
- alpha = 0.126 * exp(-0.25 * (V + 77))
54
- beta = 1.7 / (1 + exp(-0.082 * (V + 22.5)))
55
- desc: An inactivation parameter
56
- dot(j) = alpha * (1 - j) - beta * j
57
- alpha = 0.055 * exp(-0.25 * (V + 78)) / (1 + exp(-0.2 * (V + 78)))
58
- beta = 0.3 / (1 + exp(-0.1 * (V + 32)))
59
- desc: An inactivation parameter
60
-
61
- [isi]
62
- use membrane.V as V
63
- gsBar = 0.09
64
- Es = -82.3 - 13.0287 * log(calcium.Cai)
65
- in [mV]
66
- Isi = gsBar * d * f * (V - Es)
67
- in [uA/cm^2]
68
- desc: """
69
- The slow inward current, primarily carried by calcium ions. Called either
70
- "iCa" or "is" in the paper.
71
- """
72
- dot(d) = alpha * (1 - d) - beta * d
73
- alpha = 0.095 * exp(-0.01 * (V + -5)) / (exp(-0.072 * (V + -5)) + 1)
74
- beta = 0.07 * exp(-0.017 * (V + 44)) / (exp(0.05 * (V + 44)) + 1)
75
- dot(f) = alpha * (1 - f) - beta * f
76
- alpha = 0.012 * exp(-0.008 * (V + 28)) / (exp(0.15 * (V + 28)) + 1)
77
- beta = 0.0065 * exp(-0.02 * (V + 30)) / (exp(-0.2 * (V + 30)) + 1)
78
-
79
- [calcium]
80
- dot(Cai) = -1e-7 * isi.Isi + 0.07 * (1e-7 - Cai)
81
- desc: The intracellular Calcium concentration
82
- in [mol/L]
83
-
84
- [ik1]
85
- use membrane.V as V
86
- IK1 = 0.35 * (
87
- 4 * (exp(0.04 * (V + 85)) - 1)
88
- / (exp(0.08 * (V + 53)) + exp(0.04 * (V + 53)))
89
- + 0.2 * (V + 23)
90
- / (1 - exp(-0.04 * (V + 23)))
91
- )
92
- in [uA/cm^2]
93
- desc: """A time-independent outward potassium current exhibiting
94
- inward-going rectification"""
95
-
96
- [ix1]
97
- use membrane.V as V
98
- Ix1 = x1 * 0.8 * (exp(0.04 * (V + 77)) - 1) / exp(0.04 * (V + 35))
99
- in [uA/cm^2]
100
- desc: """A voltage- and time-dependent outward current, primarily carried
101
- by potassium ions"""
102
- dot(x1) = alpha * (1 - x1) - beta * x1
103
- alpha = 0.0005 * exp(0.083 * (V + 50)) / (exp(0.057 * (V + 50)) + 1)
104
- beta = 0.0013 * exp(-0.06 * (V + 20)) / (exp(-0.04 * (V + 333)) + 1)
105
-
1
+ ;
Binary file
Binary file
@@ -1,105 +1 @@
1
- [[model]]
2
- name: beeler-1977
3
- author: Michael Clerx
4
- desc: """
5
- The 1997 Beeler Reuter model of the AP in ventricular myocytes
6
-
7
- Reference:
8
-
9
- Beeler, Reuter (1976) Reconstruction of the action potential of ventricular
10
- myocardial fibres
11
- """
12
- f(x) = 4 * x
13
- # Initial values:
14
- membrane.V = -84.622
15
- calcium.Cai = 2e-7
16
- ina.m = 0.01
17
- ina.h = 0.99
18
- ina.j = 0.98
19
- isi.d = 0.003
20
- isi.f = 0.99
21
- ix1.x1 = 0.0004
22
-
23
-
24
- [engine]
25
- time = 0 in [ms] bind time
26
- pace = 0 bind pace
27
-
28
- [membrane]
29
- C = 1 [uF/cm^2] : The membrane capacitance
30
- dot(V) = -(1/C) * (i_ion + i_stim)
31
- in [mV]
32
- label membrane_potential
33
- desc: Membrane potential
34
- i_ion = ik1.IK1 + ix1.Ix1 + ina.INa + isi.Isi
35
- label cellular_current
36
- in [uA/cm^2]
37
- i_stim = engine.pace * amplitude
38
- amplitude = -25 [uA/cm^2]
39
-
40
- [ina]
41
- use membrane.V as V
42
- gNaBar = 4 [mS/cm^2]
43
- gNaC = 0.003 [mS/cm^2]
44
- ENa = 50 [mV]
45
- INa = (gNaBar * m^3 * h * j + gNaC) * (V - ENa)
46
- in [uA/cm^2]
47
- desc: The excitatory inward sodium current
48
- dot(m) = alpha * (1 - m) - beta * m
49
- alpha = (V + 47) / (1 - exp(-0.1 * (V + 47)))
50
- beta = 40 * exp(-0.056 * (V + 72))
51
- desc: The activation parameter
52
- dot(h) = alpha * (1 - h) - beta * h
53
- alpha = 0.126 * exp(-0.25 * (V + 77))
54
- beta = 1.7 / (1 + exp(-0.082 * (V + 22.5)))
55
- desc: An inactivation parameter
56
- dot(j) = alpha * (1 - j) - beta * j
57
- alpha = 0.055 * exp(-0.25 * (V + 78)) / (1 + exp(-0.2 * (V + 78)))
58
- beta = 0.3 / (1 + exp(-0.1 * (V + 32)))
59
- desc: An inactivation parameter
60
-
61
- [isi]
62
- use membrane.V as V
63
- gsBar = 0.09
64
- Es = -82.3 - 13.0287 * log(calcium.Cai)
65
- in [mV]
66
- Isi = gsBar * d * f * (V - Es)
67
- in [uA/cm^2]
68
- desc: """
69
- The slow inward current, primarily carried by calcium ions. Called either
70
- "iCa" or "is" in the paper.
71
- """
72
- dot(d) = alpha * (1 - d) - beta * d
73
- alpha = 0.095 * exp(-0.01 * (V + -5)) / (exp(-0.072 * (V + -5)) + 1)
74
- beta = 0.07 * exp(-0.017 * (V + 44)) / (exp(0.05 * (V + 44)) + 1)
75
- dot(f) = alpha * (1 - f) - beta * f
76
- alpha = 0.012 * exp(-0.008 * (V + 28)) / (exp(0.15 * (V + 28)) + 1)
77
- beta = 0.0065 * exp(-0.02 * (V + 30)) / (exp(-0.2 * (V + 30)) + 1)
78
-
79
- [calcium]
80
- dot(Cai) = -1e-7 * isi.Isi + 0.07 * (1e-7 - Cai)
81
- desc: The intracellular Calcium concentration
82
- in [mol/L]
83
-
84
- [ik1]
85
- use membrane.V as V
86
- IK1 = 0.35 * (
87
- 4 * (exp(0.04 * (V + 85)) - 1)
88
- / (exp(0.08 * (V + 53)) + exp(0.04 * (V + 53)))
89
- + 0.2 * (V + 23)
90
- / (1 - exp(-0.04 * (V + 23)))
91
- )
92
- in [uA/cm^2]
93
- desc: """A time-independent outward potassium current exhibiting
94
- inward-going rectification"""
95
-
96
- [ix1]
97
- use membrane.V as V
98
- Ix1 = x1 * 0.8 * (exp(0.04 * (V + 77)) - 1) / exp(0.04 * (V + 35))
99
- in [uA/cm^2]
100
- desc: """A voltage- and time-dependent outward current, primarily carried
101
- by potassium ions"""
102
- dot(x1) = alpha * (1 - x1) - beta * x1
103
- alpha = 0.0005 * exp(0.083 * (V + 50)) / (exp(0.057 * (V + 50)) + 1)
104
- beta = 0.0013 * exp(-0.06 * (V + 20)) / (exp(-0.04 * (V + 333)) + 1)
105
-
1
+ ;
@@ -0,0 +1,187 @@
1
+ [[model]]
2
+ author: Michael Clerx
3
+ desc: """
4
+ Implementation of the Luo-Rudy model I for the ventricular myocyte.
5
+ Based on an updated formulation downloaded from http://rudylab.wustl.edu
6
+
7
+ Original copyright notice:
8
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9
+ Copyright (C) 2006 by Leonid Livshitz and Yoram Rudy
10
+ Email rudy@wustl.edu
11
+
12
+ This program is free software; you can redistribute it and/or modify
13
+ it under the terms of the GNU General Public License as published by
14
+ the Free Software Foundation; either version 2 of the License, or
15
+ (at your option) any later version.
16
+
17
+ This program is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ GNU General Public License for more details.
21
+
22
+ You should have received a copy of the GNU General Public License
23
+ along with this program; if not, write to the
24
+ Free Software Foundation, Inc.,
25
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
+ """
27
+ name: Luo-Rudy model (1991)
28
+ # Initial conditions
29
+ membrane.V = -84.5286
30
+ ina.m = 0.0017
31
+ ina.h = 0.9832
32
+ ina.j = 0.995484
33
+ ica.d = 0.000003
34
+ ica.f = 1
35
+ ik.x = 0.0057
36
+ ica.Ca_i = 0.0002
37
+
38
+ # Engine variables
39
+ [engine]
40
+ time = 0 bind time
41
+ pace = 1 bind pace # Set to 1 to test if it becomes 0 without a protocol
42
+
43
+ # Membrane potential and stimulus
44
+ [membrane]
45
+ dot(V) = -(i_ion + i_stim + i_diff)
46
+ label membrane_potential
47
+ in [mV]
48
+ desc: The membrane potential
49
+ i_ion = ina.INa + ik.IK + ib.Ib + ikp.IKp + ik1.IK1 + ica.ICa
50
+ i_stim = engine.pace * stim_amplitude
51
+ stim_amplitude = -80 [uA/cm^2]
52
+ desc: """
53
+ Stimulus amplitude.
54
+ The online matlab implementation features this 80 uA/cm^2, 0.5 millisecond
55
+ pulse. The cellml version uses a 2 millisecond 25.5 uA/cm^2 pulse.
56
+ """
57
+ i_diff = 0 bind diffusion_current
58
+ in [uA/cm^2]
59
+
60
+ # Fast Sodium current
61
+ [ina]
62
+ use membrane.V as V
63
+ ENa = cell.RTF * log(cell.Na_o / cell.Na_i)
64
+ desc: Nernst potential of Na
65
+ in [mV]
66
+ a = 1 - 1 / (1 + exp(-(V + 40) / 0.24))
67
+ desc: Used instead of if statement.
68
+ dot(m) = alpha * (1 - m) - beta * m
69
+ alpha = if(V == -47.13, -3.2,
70
+ 0.32 * (V + 47.13) / (1 - exp(-0.1 * (V + 47.13))))
71
+ beta = 0.08 * exp(-V / 11)
72
+ desc: """
73
+ Activation parameter of the fast sodium channel, based on Ebihara-Johnson
74
+ (E-J) model of cardiac cells (chicken embryo)
75
+ """
76
+ dot(h) = alpha * (1 - h) - beta * h
77
+ alpha = a * 0.135 * exp((80 + V) / -6.8)
78
+ beta = a * (3.56 * exp(0.079 * V) + 3.1e5 * exp(0.35 * V)) \
79
+ + (1 - a) / (0.13 * (1 + exp((V + 10.66) / -11.1)))
80
+ desc: """
81
+ (Fast) Inactivation parameter of the fast sodium channel, based on
82
+ Ebihara-Johnson (E-J) model of cardiac cells (chicken embryo)
83
+ """
84
+ dot(j) = alpha * (1 - j) - beta * j
85
+ alpha = a * ( -127140 * exp(0.2444 * V) - 3.474e-5 * exp(-0.04391 * V)) \
86
+ * (V + 37.78) / (1 + exp(0.311 * (V + 79.23)))
87
+ beta = a * (0.1212 * exp(-0.01052 * V) / (1 + exp(-0.1378 * (V + 40.14)))) \
88
+ + (1 - a) * (0.3 * exp(-2.535e-7 * V) / (1 + exp(-0.1 * (V + 32))))
89
+ desc: """
90
+ Slow inactivation gate. Inspired by Beeler-Reuter and Haas. Steady-state
91
+ value (j_inf) is set to value from h gate (h_inf). Time constant obtained
92
+ from Beeler-Reuter model.
93
+ """
94
+ gNa = 16
95
+ INa = gNa * m^3 * h * j * (V - ENa)
96
+ desc: Fast sodium current
97
+ in [uA/cm^2]
98
+
99
+ # Time-dependent Potassium current
100
+ [ik]
101
+ use membrane.V as V
102
+ PNa_K = 0.01833 : Permability ratio of Na to K
103
+ gK = 0.282 * sqrt(cell.K_o / 5.4)
104
+ in [mS/uF]
105
+ E = cell.RTF * log((cell.K_o + PNa_K * cell.Na_o) / (cell.K_i + PNa_K * cell.Na_i))
106
+ in [mV]
107
+ xi = if(V < -100,
108
+ 1,
109
+ if(V == -77,
110
+ 2.837 * 0.04 / exp(0.04 * (V + 35)),
111
+ 2.837 * (exp(0.04 * (V + 77)) - 1) / ((V + 77) * exp(0.04 * (V + 35)))
112
+ ))
113
+ dot(x) = alpha * (1 - x) - beta * x
114
+ alpha = 0.0005 * exp(0.083 * (V + 50)) / (1 + exp(0.057 * (V + 50)))
115
+ beta = 0.0013 * exp(-0.06 * (V + 20)) / (1 + exp(-0.04 * (V + 20)))
116
+ IK = gK * xi * x * (V - E)
117
+ desc: Time-dependent Potassium current
118
+
119
+ # Plateau Potassium current
120
+ [ikp]
121
+ use membrane.V as V
122
+ gKp = 0.0183
123
+ IKp = gKp * (V + 87.8789) / (1 + exp((7.488 - V) / 5.98))
124
+ desc: Plateau Potassium current
125
+
126
+ # Slow inward Calcium current
127
+ [ica]
128
+ use membrane.V as V
129
+ dot(Ca_i) = -1e-4 * ICa + 0.07 * (1e-4 - Ca_i)
130
+ desc: Intracellular Calcium concentration
131
+ E = 7.7 - 13.0287 * log(Ca_i / cell.Ca_o)
132
+ desc: Nernst potential
133
+ in [mV]
134
+ dot(d) = alpha * (1 - d) - beta * d
135
+ alpha = 0.095 * exp(-0.01 * (V - 5)) / (1 + exp(-0.072 * (V - 5)))
136
+ beta = 0.07 * exp(-0.017 * (V + 44)) / (1 + exp(0.05 * (V + 44)))
137
+ dot(f) = alpha * (1-f) - beta * f
138
+ alpha = 0.012 * exp(-0.008 * (V + 28)) / (1 + exp(0.15 * (V + 28)))
139
+ beta = 0.0065 * exp(-0.02 * (V + 30)) / (1 + exp(-0.2 * (V + 30)))
140
+ gCa = 0.09
141
+ ICa = gCa * d * f * (V - E)
142
+
143
+ # Time-independent potassium current
144
+ [ik1]
145
+ use membrane.V as V
146
+ E = cell.RTF * log(cell.K_o / cell.K_i)
147
+ gK1 = 0.6047 * sqrt(cell.K_o / 5.4) * alpha / (alpha + beta)
148
+ alpha = 1.02 / (1 + exp(0.2385 * (V - E - 59.215)))
149
+ beta = (0.49124 * exp(0.08032 * (V - E + 5.476)) + exp(0.06175 * (V - E - 594.31))) \
150
+ / (1 + exp(-0.5143 * (V - E + 4.753)))
151
+ IK1 = gK1 * (V - E)
152
+
153
+ # Background current
154
+ [ib]
155
+ gb = 0.03921
156
+ Ib = gb * (membrane.V + 59.87) : Background current
157
+
158
+ # Cell parameters (ventricular mammalian cell)
159
+ [cell]
160
+ K_o = 5.4 [mM]
161
+ K_i = 145 [mM]
162
+ Na_o = 140 [mM]
163
+ Na_i = 10 [mM]
164
+ Ca_o = 1.8 [mM]
165
+ RTF = R*T/F
166
+ R = 8.314 [J/K] : Gas constant
167
+ T = 273 + 37 [K] : Absolute temperature
168
+ F = 96.5 [C/mol] : Faraday constant
169
+
170
+ [[protocol]]
171
+ # Level Start Length Period Multiplier
172
+ 1.0 1 0.5 1000 0
173
+
174
+ [[script]]
175
+ import matplotlib.pyplot as pl
176
+ import myokit
177
+
178
+ # Create simulation
179
+ m = get_model()
180
+ p = get_protocol()
181
+ s = myokit.SimulationOpenCL(m, p, 16)
182
+
183
+ # Run
184
+ d = s.run(5, log=['engine.time', 'membrane.V', 'engine.pace'])
185
+ b = d.block1d()
186
+ b.save('block1d.zip')
187
+
@@ -0,0 +1,4 @@
1
+ "time","x","x","ys-2","x","ys-2","x-2"
2
+ 1, 0, 2, 4, 6, 8, 5
3
+ 2, 1, 3, 5, 7, 9, 4
4
+
myokit/tests/test_aux.py CHANGED
@@ -526,6 +526,10 @@ class AuxTest(unittest.TestCase):
526
526
  self.assertEqual(a, b)
527
527
  self.assertEqual(len(x), len(y))
528
528
 
529
+ # No issues when passing initial state from a model
530
+ # See https://github.com/myokit/myokit/pull/1083
531
+ myokit.step(m1, reference=m2, initial=m1.initial_values())
532
+
529
533
  def test_strfloat(self):
530
534
  # Deprecated alias of myokit.float.str
531
535
  args = ['-1.234', True, myokit.SINGLE_PRECISION]