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.
- myokit/__init__.py +2 -2
- myokit/_aux.py +4 -0
- myokit/_datablock.py +10 -10
- myokit/_datalog.py +55 -11
- myokit/_myokit_version.py +1 -1
- myokit/_sim/cvodessim.py +3 -3
- myokit/formats/axon/_abf.py +11 -4
- myokit/formats/diffsl/__init__.py +60 -0
- myokit/formats/diffsl/_ewriter.py +145 -0
- myokit/formats/diffsl/_exporter.py +435 -0
- myokit/formats/heka/__init__.py +4 -0
- myokit/formats/heka/_patchmaster.py +408 -156
- myokit/formats/sbml/__init__.py +21 -1
- myokit/formats/sbml/_api.py +160 -6
- myokit/formats/sbml/_exporter.py +53 -0
- myokit/formats/sbml/_writer.py +355 -0
- myokit/gui/datalog_viewer.py +17 -3
- myokit/tests/data/io/bad1d-2-no-header.zip +0 -0
- myokit/tests/data/io/bad1d-3-no-data.zip +0 -0
- myokit/tests/data/io/bad1d-4-not-a-zip.zip +1 -105
- myokit/tests/data/io/bad1d-5-bad-data-type.zip +0 -0
- myokit/tests/data/io/bad1d-6-time-too-short.zip +0 -0
- myokit/tests/data/io/bad1d-7-0d-too-short.zip +0 -0
- myokit/tests/data/io/bad1d-8-1d-too-short.zip +0 -0
- myokit/tests/data/io/bad2d-2-no-header.zip +0 -0
- myokit/tests/data/io/bad2d-3-no-data.zip +0 -0
- myokit/tests/data/io/bad2d-4-not-a-zip.zip +1 -105
- myokit/tests/data/io/bad2d-5-bad-data-type.zip +0 -0
- myokit/tests/data/io/bad2d-8-2d-too-short.zip +0 -0
- myokit/tests/data/io/block1d.mmt +187 -0
- myokit/tests/data/io/datalog-18-duplicate-keys.csv +4 -0
- myokit/tests/test_aux.py +4 -0
- myokit/tests/test_datablock.py +6 -6
- myokit/tests/test_datalog.py +20 -0
- myokit/tests/test_formats_diffsl.py +728 -0
- myokit/tests/test_formats_exporters_run.py +6 -0
- myokit/tests/test_formats_sbml.py +57 -1
- myokit/tests/test_sbml_api.py +90 -0
- myokit/tests/test_sbml_export.py +327 -0
- {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/LICENSE.txt +1 -1
- {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/METADATA +4 -4
- {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/RECORD +45 -36
- {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/WHEEL +1 -1
- {myokit-1.37.0.dist-info → myokit-1.37.2.dist-info}/entry_points.txt +0 -0
- {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)
|
myokit/gui/datalog_viewer.py
CHANGED
|
@@ -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
|
-
|
|
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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,105 +1 @@
|
|
|
1
|
-
|
|
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
|