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
myokit/gui/vargrapher.py CHANGED
@@ -4,23 +4,13 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
- # Standard library imports
11
-
12
- # Myokit
13
7
  import myokit
8
+ import myokit.gui
14
9
 
15
- # Qt imports
16
10
  from myokit.gui import QtGui, QtWidgets
17
11
 
18
- # NumPy
19
12
  import numpy as np
20
13
 
21
- # GUI components
22
- import myokit.gui
23
-
24
14
  # Matplotlib (must be imported _after_ gui has had chance to set backend)
25
15
  import matplotlib
26
16
  import matplotlib.figure
@@ -50,7 +40,7 @@ class VarGrapher(QtWidgets.QDialog):
50
40
  *Extends:* ``QtWidgets.QDialog``
51
41
  """
52
42
  def __init__(self, parent, title, var, func, args):
53
- super(VarGrapher, self).__init__(parent)
43
+ super().__init__(parent)
54
44
  self.setFixedSize(700, 600)
55
45
  self.setWindowTitle(title)
56
46
 
myokit/lib/deps.py CHANGED
@@ -5,12 +5,11 @@
5
5
  # This file is part of Myokit.
6
6
  # See http://myokit.org for copyright, sharing, and licensing details.
7
7
  #
8
- from __future__ import absolute_import, division
9
- from __future__ import print_function, unicode_literals
10
-
11
- import random
12
8
  import collections
9
+ import random
10
+
13
11
  import myokit
12
+
14
13
  # Don't import pyplot yet, this will crash if no window environment is loaded
15
14
 
16
15
 
@@ -52,7 +51,7 @@ def create_state_dependency_matrix(model, direct=False, knockout=None):
52
51
  v = model.get(v, class_filter=myokit.Variable)
53
52
  if not v.is_state():
54
53
  raise ValueError('Knockout variables must be states.')
55
- iknock.append(v.indice())
54
+ iknock.append(v.index())
56
55
 
57
56
  # Create matrix of direct dependencies
58
57
  m = []
@@ -61,7 +60,7 @@ def create_state_dependency_matrix(model, direct=False, knockout=None):
61
60
  if i not in iknock:
62
61
  for dep in deep[var.lhs()]:
63
62
  if dep.var().is_state():
64
- j = dep.var().indice()
63
+ j = dep.var().index()
65
64
  if j not in iknock:
66
65
  row[j] = 1
67
66
  m.append(row)
@@ -174,7 +173,7 @@ def plot_state_dependency_matrix(
174
173
  return a
175
174
 
176
175
 
177
- class DiGraph(object):
176
+ class DiGraph:
178
177
  """
179
178
  A simple directed graph implementation.
180
179
 
@@ -182,7 +181,7 @@ class DiGraph(object):
182
181
  for example ``matrix=[[0, 1, 1], [0, 1, 0], [0, 0, 0]]``
183
182
  """
184
183
  def __init__(self, matrix=None):
185
- super(DiGraph, self).__init__()
184
+ super().__init__()
186
185
  if isinstance(matrix, DiGraph):
187
186
  # Clone
188
187
  self.nodes = collections.OrderedDict()
@@ -455,7 +454,7 @@ class DiGraph(object):
455
454
  for n_runs in range(max_runs):
456
455
  change = False
457
456
  for i, layer in enumerate(layers):
458
- # Set nodes to median of neighbours
457
+ # Set nodes to median of neighbors
459
458
  for j, node in enumerate(layer):
460
459
  n = len(node.edgi) + len(node.edgo)
461
460
  if n > 0:
@@ -493,8 +492,8 @@ class DiGraph(object):
493
492
  x2 = None
494
493
  for k in range(j + 1, n):
495
494
  if abs(layer[k].x - node.x) >= too_close:
496
- x2 = layer[k].x
497
- break
495
+ x2 = layer[k].x # pragma: no cover
496
+ break # pragma: no cover
498
497
  eq.append(layer[k])
499
498
  if x2 is None:
500
499
  x2 = 1.0
@@ -526,7 +525,7 @@ class DiGraph(object):
526
525
  return test
527
526
 
528
527
 
529
- class Node(object):
528
+ class Node:
530
529
  """
531
530
  Defines a node in a graph
532
531
  """
@@ -534,7 +533,7 @@ class Node(object):
534
533
  """
535
534
  Creates a new, graphless node with the given identifier
536
535
  """
537
- super(Node, self).__init__()
536
+ super().__init__()
538
537
  self.graph = None
539
538
  self.uid = uid
540
539
  self.edgo = set()
myokit/lib/guess.py CHANGED
@@ -5,9 +5,8 @@
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
8
  import collections
9
+
11
10
  import myokit
12
11
 
13
12
 
@@ -392,7 +391,7 @@ def membrane_potential(model):
392
391
  # Common units for the membrane potential
393
392
  common_units = [myokit.units.V]
394
393
 
395
- # Non-dimensionalised (e.g. Mitchell-Schaeffer) use [1]
394
+ # Non-dimensionalized (e.g. Mitchell-Schaeffer) use [1]
396
395
  # But this causes too many false positives
397
396
  # common_units.append(myokit.units.dimensionless)
398
397
 
@@ -581,7 +580,7 @@ def stimulus_current(model):
581
580
  myokit.units.A / myokit.units.m**2,
582
581
  ]
583
582
 
584
- # Non-dimensionalised (e.g. Mitchell-Schaeffer) use [mS/uF]
583
+ # Non-dimensionalized (e.g. Mitchell-Schaeffer) use [mS/uF]
585
584
  # But this causes too many false positives
586
585
  # common_units.append(myokit.units.S / myokit.units.F)
587
586
 
myokit/lib/hh.py CHANGED
@@ -4,14 +4,12 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
7
  import numpy as np
8
+
11
9
  import myokit
12
10
 
13
11
 
14
- class HHModel(object):
12
+ class HHModel:
15
13
  """
16
14
  Represents a Hodgkin-Huxley (HH)-style model of an ion channel, extracted
17
15
  from a :class:`myokit.Model`.
@@ -29,7 +27,8 @@ class HHModel(object):
29
27
  The model variables to treat as parameter are specified by the user when
30
28
  the model is created. Any other variables, for example state variables such
31
29
  as intercellular calcium or constants such as temperature, are fixed when
32
- the current model is created and can no longer be changed.
30
+ the current model is created and can no longer be changed. Initial values
31
+ written as expressions are evaluated when the model is made.
33
32
 
34
33
  The current variable is optional.
35
34
 
@@ -83,7 +82,7 @@ class HHModel(object):
83
82
  # Load a model from disk
84
83
  model = myokit.load_model('some-model.mmt')
85
84
 
86
- # Extract a markov model
85
+ # Extract a Hodgkin-Huxley style channel model
87
86
  mm = hh.HHModel.from_component(model.get('ina'))
88
87
 
89
88
  """
@@ -93,7 +92,7 @@ class HHModel(object):
93
92
  # A HHModel can return a function to calculate state values, but it never
94
93
  # updates its internal state in any way.
95
94
  def __init__(self, model, states, parameters=None, current=None, vm=None):
96
- super(HHModel, self).__init__()
95
+ super().__init__()
97
96
 
98
97
  #
99
98
  # Check input
@@ -183,15 +182,18 @@ class HHModel(object):
183
182
  'The membrane potential should not be the current variable.')
184
183
  del vm
185
184
 
185
+ # Get values of all states
186
+ # Note: Do this _before_ changing the model!
187
+ s = self._model.initial_values(True)
188
+ self._model.set_initial_values(s) # Remove expressions
189
+ self._default_state = np.array(
190
+ [v.initial_value(True) for v in self._states])
191
+
186
192
  #
187
193
  # Demote unnecessary states and remove bindings
188
194
  #
189
- # Get values of all states
190
- # Note: Do this _before_ changing the model!
191
- self._default_state = np.array([v.state_value() for v in self._states])
192
195
 
193
196
  # Freeze remaining, non-current-model states
194
- s = self._model.state() # Get state values before changing anything!
195
197
  # Note: list() cast is required so that we iterate over a static list,
196
198
  # otherwise we can get issues because the iterator depends on the model
197
199
  # (which we're changing).
@@ -346,19 +348,19 @@ class HHModel(object):
346
348
 
347
349
  def default_membrane_potential(self):
348
350
  """
349
- Returns this markov model's default membrane potential value.
351
+ Returns this HH model's default membrane potential value.
350
352
  """
351
353
  return self._default_inputs[0]
352
354
 
353
355
  def default_parameters(self):
354
356
  """
355
- Returns this markov model's default parameter values
357
+ Returns this HH model's default parameter values
356
358
  """
357
359
  return list(self._default_inputs[1:])
358
360
 
359
361
  def default_state(self):
360
362
  """
361
- Returns this markov model's default state values.
363
+ Returns this HH model's default state values.
362
364
  """
363
365
  return list(self._default_state)
364
366
 
@@ -389,8 +391,8 @@ class HHModel(object):
389
391
  # Get state variables
390
392
  states = [x for x in component.variables(state=True)]
391
393
 
392
- # Sort by state indice
393
- states.sort(key=lambda x: x.indice())
394
+ # Sort by state index
395
+ states.sort(key=lambda x: x.index())
394
396
 
395
397
  else:
396
398
 
@@ -529,7 +531,7 @@ class HHModel(object):
529
531
  return self._steady_state_function(*inputs)
530
532
 
531
533
 
532
- class AnalyticalSimulation(object):
534
+ class AnalyticalSimulation:
533
535
  """
534
536
  Analytically evaluates a :class:`HHModel`'s state for a given set of points
535
537
  in time.
@@ -579,7 +581,7 @@ class AnalyticalSimulation(object):
579
581
 
580
582
  """
581
583
  def __init__(self, model, protocol=None):
582
- super(AnalyticalSimulation, self).__init__()
584
+ super().__init__()
583
585
 
584
586
  # Check model
585
587
  if not isinstance(model, HHModel):
myokit/lib/markov.py CHANGED
@@ -4,16 +4,14 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
7
  import collections
8
+
11
9
  import numpy as np
12
10
 
13
11
  import myokit
14
12
 
15
13
 
16
- class LinearModel(object):
14
+ class LinearModel:
17
15
  """
18
16
  Represents a linear Markov model of an ion channel extracted from a
19
17
  :class:`myokit.Model`.
@@ -37,7 +35,8 @@ class LinearModel(object):
37
35
  The model variables to treat as parameter are specified by the user when
38
36
  the model is created. Any other variables, for example state variables such
39
37
  as intercellular calcium or constants such as temperature, are fixed when
40
- the markov model is created and can no longer be changed.
38
+ the markov model is created and can no longer be changed. Initial values
39
+ written as expressions are evaluated when the model is made.
41
40
 
42
41
  To create a :class:`Markov`, pass in a :class:`myokit.Model` and select a
43
42
  list of states. All other states will be fixed at their current value and
@@ -119,7 +118,7 @@ class LinearModel(object):
119
118
  # for its default values or newly passed in values, but it never updates
120
119
  # its internal state in any way!
121
120
  def __init__(self, model, states, parameters=None, current=None, vm=None):
122
- super(LinearModel, self).__init__()
121
+ super().__init__()
123
122
 
124
123
  # Get a clone of the model, with all markov models written in full ODE
125
124
  # form.
@@ -205,15 +204,17 @@ class LinearModel(object):
205
204
  'The membrane potential should not be the current variable.')
206
205
  del vm
207
206
 
207
+ # Get values of all states
208
+ # Note: Do this _before_ changing the model!
209
+ s = self._model.initial_values(True)
210
+ self._default_state = np.array(
211
+ [v.initial_value(True) for v in self._states])
212
+
208
213
  #
209
214
  # Demote unnecessary states, remove bindings and validate model.
210
215
  #
211
- # Get values of all states
212
- # Note: Do this _before_ changing the model!
213
- self._default_state = np.array([v.state_value() for v in self._states])
214
216
 
215
217
  # Freeze remaining, non-markov-model states
216
- s = self._model.state() # Get state values before changing anything!
217
218
  for k, state in enumerate(self._model.states()):
218
219
  if state not in self._states:
219
220
  state.demote()
@@ -386,7 +387,7 @@ class LinearModel(object):
386
387
  globl = {'numpy': np, 'n': n}
387
388
  local = {}
388
389
 
389
- myokit._exec(code, globl, local)
390
+ exec(code, globl, local)
390
391
  self._matrix_function = local['matrix_function']
391
392
 
392
393
  #
@@ -405,7 +406,7 @@ class LinearModel(object):
405
406
  code = head + '\n' + '\n'.join([' ' + line for line in body])
406
407
  globl = {'numpy': np}
407
408
  local = {}
408
- myokit._exec(code, globl, local)
409
+ exec(code, globl, local)
409
410
  self._rate_list_function = local['rate_list_function']
410
411
 
411
412
  def current(self):
@@ -460,8 +461,8 @@ class LinearModel(object):
460
461
  # Get state variables
461
462
  states = [x for x in component.variables(state=True)]
462
463
 
463
- # Sort by state indice
464
- states.sort(key=lambda x: x.indice())
464
+ # Sort by state index
465
+ states.sort(key=lambda x: x.index())
465
466
 
466
467
  else:
467
468
 
@@ -632,7 +633,7 @@ class LinearModel(object):
632
633
  return x
633
634
 
634
635
 
635
- class AnalyticalSimulation(object):
636
+ class AnalyticalSimulation:
636
637
  """
637
638
  Analytically evaluates a :class:`LinearModel`'s state over a given set of
638
639
  points in time.
@@ -686,7 +687,7 @@ class AnalyticalSimulation(object):
686
687
 
687
688
  """
688
689
  def __init__(self, model, protocol=None):
689
- super(AnalyticalSimulation, self).__init__()
690
+ super().__init__()
690
691
  # Check model
691
692
  if not isinstance(model, LinearModel):
692
693
  raise ValueError('First parameter must be a `LinearModel`.')
@@ -1090,7 +1091,7 @@ class AnalyticalSimulation(object):
1090
1091
  return list(self._state)
1091
1092
 
1092
1093
 
1093
- class DiscreteSimulation(object):
1094
+ class DiscreteSimulation:
1094
1095
  """
1095
1096
  Performs stochastic simulations of a :class:`LinearModel`'s behavior for a
1096
1097
  finite number of channels.
@@ -1225,7 +1226,7 @@ class DiscreteSimulation(object):
1225
1226
  ' equal 1.')
1226
1227
  y = np.round(x * self._nchannels)
1227
1228
  # To make sure it always sums to 1, correct the value found at the
1228
- # indice with the biggest rounding error.
1229
+ # index with the biggest rounding error.
1229
1230
  i = np.argmax(np.abs(x - y))
1230
1231
  y[i] = 0
1231
1232
  y[i] = self._nchannels - np.sum(y)
@@ -1560,7 +1561,7 @@ class DiscreteSimulation(object):
1560
1561
  return list(self._state)
1561
1562
 
1562
1563
 
1563
- class MarkovModel(object):
1564
+ class MarkovModel:
1564
1565
  """
1565
1566
  **Deprecated**: This class has been replaced by the classes
1566
1567
  :class:`LinearModel` and :class:`AnalyticalSimulation`. Please update your
@@ -1701,7 +1702,7 @@ def _split_factor(term, variables):
1701
1702
  'Non-linear function of ' + str(name) + ' found in '
1702
1703
  + str(term) + '.')
1703
1704
 
1704
- # Finalise multiplier
1705
+ # Finalize multiplier
1705
1706
  if m is None:
1706
1707
  m = myokit.Number(1)
1707
1708
  if not positive:
myokit/lib/multi.py CHANGED
@@ -4,11 +4,9 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
7
+ import os
9
8
 
10
9
  import myokit
11
- import os
12
10
 
13
11
 
14
12
  #
myokit/lib/plots.py CHANGED
@@ -5,10 +5,8 @@
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 numpy as np
9
+
12
10
  # Don't import pyplot yet, this will cause a crash if no window environment
13
11
  # is loaded.
14
12
 
@@ -265,7 +263,8 @@ def current_arrows(log, voltage, currents, axes=None):
265
263
 
266
264
  def cumulative_current(
267
265
  log, currents, axes=None, labels=None, colors=None, integrate=False,
268
- normalise=False, max_currents=None, line_args={}, fill_args={}):
266
+ normalize=False, max_currents=None, line_args={}, fill_args={},
267
+ normalise=None):
269
268
  """
270
269
  Plots a number of currents, one on top of the other, with the positive and
271
270
  negative parts of the current plotted separately.
@@ -291,8 +290,8 @@ def cumulative_current(
291
290
  current.
292
291
  ``integrate``
293
292
  Set this to ``True`` to plot total carried charge instead of currents.
294
- ``normalise``
295
- Set this to ``True`` to normalise the graph at every point, so that the
293
+ ``normalize``
294
+ Set this to ``True`` to normalize the graph at every point, so that the
296
295
  relative contribution of each current is shown.
297
296
  ``max_currents``
298
297
  Set this to any integer n to display only the first n currents, and
@@ -310,6 +309,15 @@ def cumulative_current(
310
309
  import matplotlib
311
310
  import matplotlib.pyplot as plt
312
311
 
312
+ # Deprecated on 2023-06-7
313
+ if normalize is not None:
314
+ import warnings
315
+ warnings.warn(
316
+ 'The keyword argument `normalise` is deprecated. Please use'
317
+ ' `normalize` instead.')
318
+ normalize = normalise
319
+ del normalise
320
+
313
321
  # Get axes
314
322
  if axes is None:
315
323
  axes = plt.gca()
@@ -330,8 +338,8 @@ def cumulative_current(
330
338
  neg = np.minimum(pos, 0)
331
339
  pos = np.maximum(pos, 0)
332
340
 
333
- # Normalise
334
- if normalise:
341
+ # Normalize
342
+ if normalize:
335
343
  pos /= np.maximum(np.sum(pos, axis=0), 1e-99)
336
344
  neg /= -np.minimum(np.sum(neg, axis=0), -1e-99)
337
345
 
@@ -350,7 +358,10 @@ def cumulative_current(
350
358
  colors.extend(colors)
351
359
  else:
352
360
  # Colormap
353
- cmap = matplotlib.cm.get_cmap(name='tab20')
361
+ try:
362
+ cmap = matplotlib.colormaps['tab20']
363
+ except AttributeError: # pragma: no cover
364
+ cmap = matplotlib.cm.get_cmap(name='tab20')
354
365
  colors = [cmap(i) for i in range(nc)]
355
366
 
356
367
  # Line drawing keyword arguments
myokit/pacing.py CHANGED
@@ -4,9 +4,6 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
7
  import myokit
11
8
  """
12
9
  This module contains factory methods to create Protocol objects
myokit/pype.py CHANGED
@@ -4,25 +4,14 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
7
  import ast
8
+ import io
11
9
  import re
12
10
  import sys
13
11
  import traceback
14
12
 
15
- import myokit
16
-
17
- try:
18
- # Python 2
19
- from cStringIO import StringIO
20
- except ImportError:
21
- # Python3
22
- from io import StringIO
23
-
24
13
 
25
- class TemplateEngine(object):
14
+ class TemplateEngine:
26
15
  """
27
16
  A tiny templating engine using a php style syntax.
28
17
 
@@ -40,7 +29,7 @@ class TemplateEngine(object):
40
29
  stream specified by the user.
41
30
  """
42
31
  def __init__(self):
43
- super(TemplateEngine, self).__init__()
32
+ super().__init__()
44
33
  self.stream = None
45
34
  self.error = None
46
35
 
@@ -71,8 +60,8 @@ class TemplateEngine(object):
71
60
  script = self._convert(filename)
72
61
 
73
62
  # Get or create output stream
74
- stdout = self.stream if self.stream else StringIO()
75
- stderr = StringIO()
63
+ stdout = self.stream if self.stream else io.StringIO()
64
+ stderr = io.StringIO()
76
65
 
77
66
  # Run and handle errors
78
67
  error = None
@@ -84,7 +73,7 @@ class TemplateEngine(object):
84
73
  syserr = sys.stderr
85
74
  sys.stdout = stdout
86
75
  sys.stderr = stderr
87
- myokit._exec(script, variables)
76
+ exec(script, variables)
88
77
  except Exception:
89
78
  error = sys.exc_info()
90
79
  finally:
@@ -245,5 +234,5 @@ class PypeError(Exception):
245
234
  *Extends:* Exception
246
235
  """
247
236
  def __init__(self, message):
248
- super(PypeError, self).__init__(message)
237
+ super().__init__(message)
249
238
 
myokit/tests/__init__.py CHANGED
@@ -8,9 +8,6 @@
8
8
  # The TemporaryDirectory class was adapted from Pints
9
9
  # See: https://github.com/pints-team/pints
10
10
  #
11
- from __future__ import absolute_import, division
12
- from __future__ import print_function, unicode_literals
13
-
14
11
  import os
15
12
  import tempfile
16
13
  import warnings
@@ -43,14 +40,14 @@ if OpenCL_FOUND:
43
40
  del info
44
41
 
45
42
 
46
- class TemporaryDirectory(object):
43
+ class TemporaryDirectory:
47
44
  """
48
45
  ContextManager that provides a temporary directory to create temporary
49
46
  files in. Deletes the directory and its contents when the context is
50
47
  exited.
51
48
  """
52
49
  def __init__(self):
53
- super(TemporaryDirectory, self).__init__()
50
+ super().__init__()
54
51
  self._dir = None
55
52
 
56
53
  def __enter__(self):
@@ -138,7 +135,7 @@ class CancellingReporter(myokit.ProgressReporter):
138
135
  return self.okays >= 0
139
136
 
140
137
 
141
- class WarningCollector(object):
138
+ class WarningCollector:
142
139
  """
143
140
  Wrapper around warnings.catch_warnings() that gathers all messages into a
144
141
  single string.
@@ -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
 
13
10
  import myokit
@@ -26,7 +23,7 @@ class AnsicEventBasedPacing(myokit.CModule):
26
23
  _index = 0
27
24
 
28
25
  def __init__(self, protocol):
29
- super(AnsicEventBasedPacing, self).__init__()
26
+ super().__init__()
30
27
 
31
28
  # Unique id
32
29
  AnsicEventBasedPacing._index += 1
@@ -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
 
13
10
  import myokit
@@ -24,8 +21,8 @@ class AnsicFixedFormPacing(myokit.CModule):
24
21
  """
25
22
  _index = 0
26
23
 
27
- def __init__(self, times=None, values=None):
28
- super(AnsicFixedFormPacing, self).__init__()
24
+ def __init__(self, protocol):
25
+ super().__init__()
29
26
 
30
27
  # Unique id
31
28
  AnsicFixedFormPacing._index += 1
@@ -43,7 +40,7 @@ class AnsicFixedFormPacing(myokit.CModule):
43
40
  self._sys = self._compile(module_name, fname, args, libs, libd, incd)
44
41
 
45
42
  # Initialize
46
- self._sys.init(times, values)
43
+ self._sys.init(protocol)
47
44
 
48
45
  def pace(self, time):
49
46
  return self._sys.pace(time)
@@ -2,7 +2,7 @@
2
2
  name: beeler-1977-with-differences
3
3
  desc: """
4
4
  The 1997 Beeler Reuter model of the AP in ventricular myocytes.
5
-
5
+
6
6
  This test version has some differences
7
7
 
8
8
  Reference:
@@ -18,7 +18,7 @@ membrane.V = -84.622
18
18
  calcium.Cai = 2e-7
19
19
  ina.m = 0.01
20
20
  ina.h = 1.0
21
- ina.j = 0.98
21
+ ina.j = 0.97 + 0.01
22
22
  isiz.d = 0.003
23
23
  isiz.f = 1.0
24
24
 
@@ -143,6 +143,7 @@ dot(O) = -O * (a2 + b13 ) + C1 * a13 + IF * b2
143
143
  dot(IF) = -IF * (a4 + b2 + a3) + IS * b4 + O * a2 + C1 * b3
144
144
  dot(IS) = -IS * (b4 ) + IF * a4
145
145
  i = gmax * O * (V - E)
146
+ p = 1e-4
146
147
 
147
148
  [[protocol]]
148
149
  # Level Start Length Period Multiplier