myokit 1.37.0__py3-none-any.whl → 1.37.2__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 (45) hide show
  1. myokit/__init__.py +2 -2
  2. myokit/_aux.py +4 -0
  3. myokit/_datablock.py +10 -10
  4. myokit/_datalog.py +55 -11
  5. myokit/_myokit_version.py +1 -1
  6. myokit/_sim/cvodessim.py +3 -3
  7. myokit/formats/axon/_abf.py +11 -4
  8. myokit/formats/diffsl/__init__.py +60 -0
  9. myokit/formats/diffsl/_ewriter.py +145 -0
  10. myokit/formats/diffsl/_exporter.py +435 -0
  11. myokit/formats/heka/__init__.py +4 -0
  12. myokit/formats/heka/_patchmaster.py +408 -156
  13. myokit/formats/sbml/__init__.py +21 -1
  14. myokit/formats/sbml/_api.py +160 -6
  15. myokit/formats/sbml/_exporter.py +53 -0
  16. myokit/formats/sbml/_writer.py +355 -0
  17. myokit/gui/datalog_viewer.py +17 -3
  18. myokit/tests/data/io/bad1d-2-no-header.zip +0 -0
  19. myokit/tests/data/io/bad1d-3-no-data.zip +0 -0
  20. myokit/tests/data/io/bad1d-4-not-a-zip.zip +1 -105
  21. myokit/tests/data/io/bad1d-5-bad-data-type.zip +0 -0
  22. myokit/tests/data/io/bad1d-6-time-too-short.zip +0 -0
  23. myokit/tests/data/io/bad1d-7-0d-too-short.zip +0 -0
  24. myokit/tests/data/io/bad1d-8-1d-too-short.zip +0 -0
  25. myokit/tests/data/io/bad2d-2-no-header.zip +0 -0
  26. myokit/tests/data/io/bad2d-3-no-data.zip +0 -0
  27. myokit/tests/data/io/bad2d-4-not-a-zip.zip +1 -105
  28. myokit/tests/data/io/bad2d-5-bad-data-type.zip +0 -0
  29. myokit/tests/data/io/bad2d-8-2d-too-short.zip +0 -0
  30. myokit/tests/data/io/block1d.mmt +187 -0
  31. myokit/tests/data/io/datalog-18-duplicate-keys.csv +4 -0
  32. myokit/tests/test_aux.py +4 -0
  33. myokit/tests/test_datablock.py +6 -6
  34. myokit/tests/test_datalog.py +20 -0
  35. myokit/tests/test_formats_diffsl.py +728 -0
  36. myokit/tests/test_formats_exporters_run.py +6 -0
  37. myokit/tests/test_formats_sbml.py +57 -1
  38. myokit/tests/test_sbml_api.py +90 -0
  39. myokit/tests/test_sbml_export.py +327 -0
  40. {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/LICENSE.txt +1 -1
  41. {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/METADATA +4 -4
  42. {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/RECORD +45 -36
  43. {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/WHEEL +1 -1
  44. {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/entry_points.txt +0 -0
  45. {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,355 @@
1
+ #
2
+ # SBML Writer: Writes an SBML Model to disk
3
+ #
4
+ # This file is part of Myokit.
5
+ # See http://myokit.org for copyright, sharing, and licensing details.
6
+ #
7
+ from typing import Tuple
8
+ from lxml import etree
9
+
10
+ import myokit
11
+ from myokit._unit import Quantity
12
+ from myokit.formats.mathml._ewriter import MathMLExpressionWriter
13
+ from myokit.formats.sbml._api import (
14
+ Model, Compartment,
15
+ Parameter, Species,
16
+ Reaction, SpeciesReference
17
+ )
18
+
19
+
20
+ def write_file(path: str, model: Model):
21
+ """
22
+ Writes an SBML model to the given path.
23
+ """
24
+ return SBMLWriter.write_file(path, model)
25
+
26
+
27
+ def write_string(model: Model) -> str:
28
+ """
29
+ Writes an SBML model to a string and returns it.
30
+ """
31
+ return SBMLWriter.write_string(model)
32
+
33
+
34
+ class SBMLWriter:
35
+ """
36
+ Writes SBML documents
37
+ """
38
+
39
+ @staticmethod
40
+ def write_file(path: str, model: Model):
41
+ tree = SBMLWriter._model(model)
42
+ # Write to disk
43
+ tree.write(
44
+ path,
45
+ encoding='utf-8',
46
+ method='xml',
47
+ xml_declaration=True,
48
+ pretty_print=True,
49
+ )
50
+
51
+ @staticmethod
52
+ def write_string(model: Model) -> str:
53
+ tree = SBMLWriter._model(model)
54
+ return etree.tostring(
55
+ tree,
56
+ encoding='utf-8',
57
+ method='xml',
58
+ pretty_print=True,
59
+ )
60
+
61
+ @staticmethod
62
+ def _compartment(
63
+ compartment: Compartment,
64
+ unit_to_str: dict
65
+ ) -> etree.Element:
66
+ node = etree.Element('compartment', id=compartment.sid())
67
+ if compartment.size_units() != myokit.units.dimensionless:
68
+ node.attrib['units'] = unit_to_str[compartment.size_units()]
69
+ if compartment.spatial_dimensions() is not None:
70
+ node.attrib['spatialDimensions'] = str(
71
+ compartment.spatial_dimensions()
72
+ )
73
+ return node
74
+
75
+ @staticmethod
76
+ def _unit(sid: str, unit: myokit.Unit) -> etree.Element:
77
+ node = etree.Element('unitDefinition', id=sid)
78
+ kinds = [
79
+ 'gram', 'metre', 'second',
80
+ 'ampere', 'kelvin', 'candela', 'mole'
81
+ ]
82
+ multiplier = unit.multiplier()
83
+ for exponent, kind in zip(unit.exponents(), kinds):
84
+ if exponent != 0:
85
+ child = etree.Element('unit')
86
+ child.attrib['kind'] = kind
87
+ child.attrib['exponent'] = str(exponent)
88
+ if multiplier is not None:
89
+ child.attrib['multiplier'] = str(multiplier)
90
+ multiplier = None
91
+ node.append(child)
92
+ # might also have a dimensionless unit and a multiplier
93
+ if multiplier is not None:
94
+ child = etree.Element('unit')
95
+ child.attrib['kind'] = 'dimensionless'
96
+ child.attrib['multiplier'] = str(multiplier)
97
+ node.append(child)
98
+ return node
99
+
100
+ @staticmethod
101
+ def _parameter(
102
+ parameter: Parameter,
103
+ unit_to_str_map: dict
104
+ ) -> Tuple[etree.Element, etree.Element, etree.Element]:
105
+ """
106
+ returns the XML representation of this parameter as a tuple of
107
+ (parameter, initial_assignment, rule).
108
+ """
109
+ parameter_xml = etree.Element('parameter', id=parameter.sid())
110
+ if (
111
+ parameter.units() is not None and
112
+ parameter.units() != myokit.units.dimensionless
113
+ ):
114
+ parameter_xml.attrib['units'] = unit_to_str_map[parameter.units()]
115
+
116
+ if parameter.is_constant():
117
+ parameter_xml.attrib['constant'] = 'true'
118
+
119
+ if parameter.is_literal():
120
+ value = parameter.value().eval()
121
+ parameter_xml.attrib['value'] = str(value)
122
+ return parameter_xml, None, None
123
+ else:
124
+ initial_assignment, rule = SBMLWriter._quantity(parameter)
125
+ return parameter_xml, initial_assignment, rule
126
+
127
+ @staticmethod
128
+ def _math(expression: myokit.Expression) -> etree.Element:
129
+ math = etree.Element(
130
+ 'math',
131
+ xmlns='http://www.w3.org/1998/Math/MathML'
132
+ )
133
+
134
+ def flhs(lhs):
135
+ var = lhs.var()
136
+ if isinstance(var, str):
137
+ return var
138
+ if var.binding() == 'time':
139
+ return "http://www.sbml.org/sbml/symbols/time"
140
+ return var.uname()
141
+
142
+ mathml_writer = MathMLExpressionWriter()
143
+ mathml_writer.set_lhs_function(flhs)
144
+ mathml_writer.ex(expression, math)
145
+ return math
146
+
147
+ @staticmethod
148
+ def _quantity(quantity: Quantity) -> etree.Element:
149
+ initial_value = quantity.initial_value()
150
+ initial_assignment = None
151
+ if initial_value is not None:
152
+ initial_assignment = etree.Element(
153
+ 'initialAssignment', symbol=quantity.sid()
154
+ )
155
+ math = SBMLWriter._math(initial_value)
156
+ initial_assignment.append(math)
157
+
158
+ value = quantity.value()
159
+ rule = None
160
+ if value is not None:
161
+ if quantity.is_rate():
162
+ rule_type = 'rateRule'
163
+ else:
164
+ rule_type = 'assignmentRule'
165
+ rule = etree.Element(rule_type, variable=quantity.sid())
166
+ math = SBMLWriter._math(quantity.value())
167
+ rule.append(math)
168
+ return initial_assignment, rule
169
+
170
+ @staticmethod
171
+ def _reaction(reaction: Reaction) -> etree.Element:
172
+ reaction_xml = etree.Element('reaction', id=reaction.sid())
173
+ list_of_reactants = etree.Element('listOfReactants')
174
+ for reactant in reaction.reactants():
175
+ node = SBMLWriter._species_reference(reactant)
176
+ list_of_reactants.append(node)
177
+ reaction_xml.append(list_of_reactants)
178
+ list_of_products = etree.Element('listOfProducts')
179
+ for product in reaction.products():
180
+ node = SBMLWriter._species_reference(product)
181
+ list_of_products.append(node)
182
+ reaction_xml.append(list_of_products)
183
+ list_of_modifiers = etree.Element('listOfModifiers')
184
+ for modifier in reaction.modifiers():
185
+ node = SBMLWriter._modifier_species_reference(modifier)
186
+ list_of_modifiers.append(node)
187
+ reaction_xml.append(list_of_modifiers)
188
+ if reaction.kinetic_law() is not None:
189
+ kinetic_law = etree.Element('kineticLaw')
190
+ math = SBMLWriter._math(reaction.kinetic_law())
191
+ kinetic_law.append(math)
192
+ reaction_xml.append(kinetic_law)
193
+ return reaction_xml
194
+
195
+ @staticmethod
196
+ def _species(species: Species, unit_to_str_map: dict) -> Tuple[
197
+ etree.Element, etree.Element
198
+ ]:
199
+ """
200
+ Returns the XML representation of this species as a tuple of
201
+ (species, rule).
202
+ """
203
+ species_xml = etree.Element('species', id=species.sid())
204
+ species_xml.attrib['compartment'] = species.compartment().sid()
205
+ initial_value, initial_value_in_amount = species.initial_value()
206
+ if initial_value_in_amount is None:
207
+ if species.is_amount():
208
+ attrib_name = 'initialAmount'
209
+ else:
210
+ attrib_name = 'initialConcentration'
211
+ else:
212
+ if initial_value_in_amount:
213
+ attrib_name = 'initialAmount'
214
+ else:
215
+ attrib_name = 'initialConcentration'
216
+ if initial_value is not None:
217
+ initial_value_eval = initial_value.eval()
218
+ species_xml.attrib[attrib_name] = str(initial_value_eval)
219
+ species_xml.attrib['constant'] = str(species.is_constant())
220
+ if species.substance_units() != myokit.units.dimensionless:
221
+ species_xml.attrib['units'] = unit_to_str_map[
222
+ species.substance_units()
223
+ ]
224
+ species_xml.attrib['boundaryCondition'] = str(species.is_boundary())
225
+
226
+ if species.value() is None:
227
+ return species_xml, None
228
+
229
+ if species.is_rate():
230
+ rule_type = 'rateRule'
231
+ else:
232
+ rule_type = 'assignmentRule'
233
+ rule = etree.Element(rule_type, variable=species.sid())
234
+ math = SBMLWriter._math(species.value())
235
+ rule.append(math)
236
+ return species_xml, rule
237
+
238
+ @staticmethod
239
+ def _species_reference(ref: SpeciesReference) -> etree.Element:
240
+ species_reference = etree.Element(
241
+ 'speciesReference',
242
+ species=ref.species().sid()
243
+ )
244
+ if ref.sid() is not None:
245
+ species_reference.attrib['id'] = ref.sid()
246
+ value = ref.value()
247
+ if value is not None:
248
+ value_eval = value.eval()
249
+ species_reference.attrib['stoichiometry'] = str(value_eval)
250
+ return species_reference
251
+
252
+ @staticmethod
253
+ def _modifier_species_reference(ref: SpeciesReference) -> etree.Element:
254
+ species_reference = etree.Element(
255
+ 'modifierSpeciesReference',
256
+ species=ref.species().sid()
257
+ )
258
+ if ref.sid() is not None:
259
+ species_reference.attrib['id'] = ref.sid()
260
+ return species_reference
261
+
262
+ @staticmethod
263
+ def _model(model: Model) -> etree.ElementTree:
264
+ root = etree.Element(
265
+ 'sbml',
266
+ xmlns='http://www.sbml.org/sbml/level3/version2/core',
267
+ level='3',
268
+ version='2'
269
+ )
270
+
271
+ # setup a map from unit to string
272
+ unit_map_to_str = {
273
+ unit: string for string, unit in Model.base_units.items()
274
+ }
275
+ for unitid, unit in model.units().items():
276
+ unit_map_to_str[unit] = unitid
277
+
278
+ name = model.name() if model.name() else 'unnamed_model'
279
+ model_root = etree.Element('model', id=name)
280
+ if model.time_units() != myokit.units.dimensionless:
281
+ model_root.attrib['timeUnits'] = unit_map_to_str[
282
+ model.time_units()
283
+ ]
284
+ if model.area_units() != myokit.units.dimensionless:
285
+ model_root.attrib['areaUnits'] = unit_map_to_str[
286
+ model.area_units()
287
+ ]
288
+ if model.length_units() != myokit.units.dimensionless:
289
+ model_root.attrib['lengthUnits'] = unit_map_to_str[
290
+ model.length_units()
291
+ ]
292
+ if model.substance_units() != myokit.units.dimensionless:
293
+ model_root.attrib['substanceUnits'] = unit_map_to_str[
294
+ model.substance_units()
295
+ ]
296
+ if model.extent_units() != myokit.units.dimensionless:
297
+ model_root.attrib['extentUnits'] = unit_map_to_str[
298
+ model.extent_units()
299
+ ]
300
+ if model.volume_units() != myokit.units.dimensionless:
301
+ model_root.attrib['volumeUnits'] = unit_map_to_str[
302
+ model.volume_units()
303
+ ]
304
+
305
+ if model.has_units():
306
+ list_of_units = etree.Element('listOfUnitDefinitions')
307
+ for sid, unit in model.units().items():
308
+ node = SBMLWriter._unit(sid, unit)
309
+ list_of_units.append(node)
310
+ model_root.append(list_of_units)
311
+ if model.compartments():
312
+ list_of_compartments = etree.Element('listOfCompartments')
313
+ for compartment in model.compartments():
314
+ node = SBMLWriter._compartment(compartment, unit_map_to_str)
315
+ list_of_compartments.append(node)
316
+ model_root.append(list_of_compartments)
317
+ list_of_rules = etree.Element('listOfRules')
318
+ list_of_initial_assignments = etree.Element('listOfInitialAssignments')
319
+ if model.parameters():
320
+ list_of_parameters = etree.Element('listOfParameters')
321
+ for parameter in model.parameters():
322
+ param_node, initial_value_node, rule_node = \
323
+ SBMLWriter._parameter(parameter, unit_map_to_str)
324
+ list_of_parameters.append(param_node)
325
+ if initial_value_node is not None:
326
+ list_of_initial_assignments.append(initial_value_node)
327
+ if rule_node is not None:
328
+ list_of_rules.append(rule_node)
329
+ model_root.append(list_of_parameters)
330
+ if model.species_list():
331
+ list_of_species = etree.Element('listOfSpecies')
332
+ for species in model.species_list():
333
+ species_node, rule_node = SBMLWriter._species(
334
+ species,
335
+ unit_map_to_str
336
+ )
337
+ if rule_node is not None:
338
+ list_of_rules.append(rule_node)
339
+ list_of_species.append(species_node)
340
+ model_root.append(list_of_species)
341
+ if model.reactions():
342
+ list_of_reactions = etree.Element('listOfReactions')
343
+ for reaction in model.reactions():
344
+ node = SBMLWriter._reaction(reaction)
345
+ list_of_reactions.append(node)
346
+ model_root.append(list_of_reactions)
347
+
348
+ if len(list_of_initial_assignments) > 0:
349
+ model_root.append(list_of_initial_assignments)
350
+
351
+ if len(list_of_rules) > 0:
352
+ model_root.append(list_of_rules)
353
+
354
+ root.append(model_root)
355
+ return etree.ElementTree(root)
@@ -851,6 +851,10 @@ class CsvTab(GraphTabWidget):
851
851
  for k in keys:
852
852
  self.addTab(self.create_graph_tab(k, groups.get(k)), k)
853
853
 
854
+ # Add meta data tab
855
+ if log.meta:
856
+ self.addTab(self.create_meta_tab(log.meta), 'info')
857
+
854
858
  def create_graph_tab(self, key, indices=None):
855
859
  """ Creates a widget displaying the data stored under ``key``. """
856
860
  widget = QtWidgets.QWidget(self)
@@ -880,6 +884,18 @@ class CsvTab(GraphTabWidget):
880
884
  self._axes.append(axes)
881
885
  return widget
882
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
+
883
899
 
884
900
  class MatTab(GraphTabWidget):
885
901
  """ A widget displaying a .mat file. """
@@ -997,9 +1013,7 @@ class TxtTab(GraphTabWidget):
997
1013
  return
998
1014
 
999
1015
  def create_graph_tab(self, time, data):
1000
- """
1001
- Creates a widget displaying a time series.
1002
- """
1016
+ """ Creates a widget displaying a time series. """
1003
1017
  widget = QtWidgets.QWidget(self)
1004
1018
  # Create figure
1005
1019
  figure = matplotlib.figure.Figure()
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
+ ;