myokit 1.37.1__py3-none-any.whl → 1.37.3__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/_datalog.py +15 -6
- myokit/_myokit_version.py +1 -1
- myokit/_sim/cvodessim.py +3 -3
- myokit/_unit.py +48 -40
- myokit/formats/heka/__init__.py +4 -0
- myokit/formats/heka/_patchmaster.py +128 -100
- 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/tests/test_formats_exporters_run.py +3 -0
- myokit/tests/test_formats_sbml.py +57 -1
- myokit/tests/test_quantity.py +2 -2
- myokit/tests/test_sbml_api.py +90 -0
- myokit/tests/test_sbml_export.py +327 -0
- myokit/tests/test_unit.py +28 -7
- {myokit-1.37.1.dist-info → myokit-1.37.3.dist-info}/LICENSE.txt +1 -1
- {myokit-1.37.1.dist-info → myokit-1.37.3.dist-info}/METADATA +4 -4
- {myokit-1.37.1.dist-info → myokit-1.37.3.dist-info}/RECORD +23 -20
- {myokit-1.37.1.dist-info → myokit-1.37.3.dist-info}/WHEEL +1 -1
- {myokit-1.37.1.dist-info → myokit-1.37.3.dist-info}/entry_points.txt +0 -0
- {myokit-1.37.1.dist-info → myokit-1.37.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#
|
|
3
|
+
# Tests Myokit's SBML support.
|
|
4
|
+
#
|
|
5
|
+
# This file is part of Myokit.
|
|
6
|
+
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
|
+
#
|
|
8
|
+
import unittest
|
|
9
|
+
|
|
10
|
+
import myokit
|
|
11
|
+
import myokit.formats
|
|
12
|
+
|
|
13
|
+
import myokit.formats.sbml
|
|
14
|
+
from myokit.formats.sbml._api import Model
|
|
15
|
+
from myokit.formats.sbml._writer import write_string
|
|
16
|
+
import myokit.formats.sbml as sbml
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestSBMLExport(unittest.TestCase):
|
|
20
|
+
"""
|
|
21
|
+
Unit tests for the SBML export functionality.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def test_empty_model(self):
|
|
25
|
+
# Test exporting an empty model
|
|
26
|
+
model = Model()
|
|
27
|
+
sbml_str = write_string(model).decode("utf8")
|
|
28
|
+
self.assertIn("<sbml", sbml_str)
|
|
29
|
+
self.assertIn("</sbml>", sbml_str)
|
|
30
|
+
self.assertIn('<model id="unnamed_model"/>', sbml_str)
|
|
31
|
+
|
|
32
|
+
def test_time_unit(self):
|
|
33
|
+
# Test setting the time unit
|
|
34
|
+
model = Model()
|
|
35
|
+
model.set_time_units(myokit.units.second)
|
|
36
|
+
sbml_str = write_string(model).decode("utf8")
|
|
37
|
+
self.assertIn('timeUnits="second"', sbml_str)
|
|
38
|
+
|
|
39
|
+
model = Model()
|
|
40
|
+
model.set_time_units(1e3 * myokit.units.second)
|
|
41
|
+
sbml_str = write_string(model).decode("utf8")
|
|
42
|
+
self.assertIn('<listOfUnitDefinitions>', sbml_str)
|
|
43
|
+
self.assertIn('<unitDefinition id="s_times_1e3">', sbml_str)
|
|
44
|
+
|
|
45
|
+
def test_area_unit(self):
|
|
46
|
+
# Test setting the area unit
|
|
47
|
+
model = Model()
|
|
48
|
+
model.set_area_units(myokit.units.metre)
|
|
49
|
+
sbml_str = write_string(model).decode("utf8")
|
|
50
|
+
self.assertIn('areaUnits="metre"', sbml_str)
|
|
51
|
+
|
|
52
|
+
def test_volume_unit(self):
|
|
53
|
+
# Test setting the volume unit
|
|
54
|
+
model = Model()
|
|
55
|
+
model.set_volume_units(myokit.units.litre)
|
|
56
|
+
sbml_str = write_string(model).decode("utf8")
|
|
57
|
+
self.assertIn('volumeUnits="litre"', sbml_str)
|
|
58
|
+
|
|
59
|
+
def test_substance_unit(self):
|
|
60
|
+
# Test setting the substance unit
|
|
61
|
+
model = Model()
|
|
62
|
+
model.set_substance_units(myokit.units.mole)
|
|
63
|
+
sbml_str = write_string(model).decode("utf8")
|
|
64
|
+
self.assertIn('substanceUnits="mole"', sbml_str)
|
|
65
|
+
|
|
66
|
+
def test_extent_unit(self):
|
|
67
|
+
# Test setting the extent unit
|
|
68
|
+
model = Model()
|
|
69
|
+
model.set_extent_units(myokit.units.mole)
|
|
70
|
+
sbml_str = write_string(model).decode("utf8")
|
|
71
|
+
self.assertIn('extentUnits="mole"', sbml_str)
|
|
72
|
+
|
|
73
|
+
def test_length_unit(self):
|
|
74
|
+
# Test setting the length unit
|
|
75
|
+
model = Model()
|
|
76
|
+
model.set_length_units(myokit.units.metre)
|
|
77
|
+
sbml_str = write_string(model).decode("utf8")
|
|
78
|
+
self.assertIn('lengthUnits="metre"', sbml_str)
|
|
79
|
+
|
|
80
|
+
def test_list_of_unit_definitions(self):
|
|
81
|
+
# Test setting a list of unit definitions
|
|
82
|
+
model = Model()
|
|
83
|
+
model.add_unit("my_unit", myokit.units.ampere)
|
|
84
|
+
model.add_unit("my_unit2", 2 * myokit.units.dimensionless)
|
|
85
|
+
sbml_str = write_string(model).decode("utf8")
|
|
86
|
+
self.assertIn("<listOfUnitDefinitions>", sbml_str)
|
|
87
|
+
self.assertIn('<unitDefinition id="my_unit">', sbml_str)
|
|
88
|
+
self.assertIn(
|
|
89
|
+
'<unit kind="ampere" exponent="1.0" multiplier="1.0"/>',
|
|
90
|
+
sbml_str
|
|
91
|
+
)
|
|
92
|
+
self.assertIn('<unitDefinition id="my_unit2">', sbml_str)
|
|
93
|
+
self.assertIn(
|
|
94
|
+
'<unit kind="dimensionless" multiplier="2.0"/>',
|
|
95
|
+
sbml_str
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def test_list_of_compartments(self):
|
|
99
|
+
# Test setting a list of compartments
|
|
100
|
+
model = Model()
|
|
101
|
+
c = model.add_compartment("my_compartment")
|
|
102
|
+
c.set_size_units(myokit.units.litre)
|
|
103
|
+
c.set_spatial_dimensions(3)
|
|
104
|
+
c = model.add_compartment("my_compartment2")
|
|
105
|
+
c.set_size_units(1e3 * myokit.units.metre ** 3)
|
|
106
|
+
sbml_str = write_string(model).decode("utf8")
|
|
107
|
+
self.assertIn("<listOfCompartments>", sbml_str)
|
|
108
|
+
self.assertIn(
|
|
109
|
+
'<compartment id="my_compartment" units="litre" spatialDimensions="3.0"/>', # noqa: E501
|
|
110
|
+
sbml_str
|
|
111
|
+
)
|
|
112
|
+
self.assertIn(
|
|
113
|
+
'<compartment id="my_compartment2" units="m3_times_1e3"/>',
|
|
114
|
+
sbml_str
|
|
115
|
+
)
|
|
116
|
+
self.assertIn("<listOfUnitDefinitions>", sbml_str)
|
|
117
|
+
self.assertIn('<unitDefinition id="m3_times_1e3">', sbml_str)
|
|
118
|
+
|
|
119
|
+
def test_constants_and_literals(self):
|
|
120
|
+
m = myokit.Model()
|
|
121
|
+
c = m.add_component('comp')
|
|
122
|
+
t = c.add_variable('time', rhs=myokit.Number(0))
|
|
123
|
+
t.set_unit(myokit.units.second)
|
|
124
|
+
t.set_binding('time')
|
|
125
|
+
v = c.add_variable('my_parameter')
|
|
126
|
+
v.set_rhs(myokit.Number(1))
|
|
127
|
+
v2 = c.add_variable('my_parameter2')
|
|
128
|
+
v2.set_rhs(myokit.Multiply(myokit.Number(2), myokit.Name(v)))
|
|
129
|
+
|
|
130
|
+
# check that the equation is exported correctly to sbml.Model
|
|
131
|
+
s = sbml.Model.from_myokit_model(m)
|
|
132
|
+
parameter_names = [v.sid() for v in s.parameters()]
|
|
133
|
+
self.assertCountEqual(
|
|
134
|
+
parameter_names, ['my_parameter', 'my_parameter2']
|
|
135
|
+
)
|
|
136
|
+
sbml_v = s.parameter('my_parameter')
|
|
137
|
+
sbml_v2 = s.parameter('my_parameter2')
|
|
138
|
+
self.assertEqual(sbml_v.value(), myokit.Number(1))
|
|
139
|
+
self.assertIsNone(sbml_v.initial_value())
|
|
140
|
+
self.assertEqual(
|
|
141
|
+
sbml_v2.initial_value(),
|
|
142
|
+
myokit.Multiply(myokit.Number(2), myokit.Name(v))
|
|
143
|
+
)
|
|
144
|
+
self.assertIsNone(sbml_v2.value())
|
|
145
|
+
self.assertTrue(sbml_v.is_constant())
|
|
146
|
+
self.assertTrue(sbml_v2.is_constant())
|
|
147
|
+
self.assertFalse(sbml_v2.is_literal())
|
|
148
|
+
self.assertTrue(sbml_v.is_literal())
|
|
149
|
+
|
|
150
|
+
def test_list_of_parameters(self):
|
|
151
|
+
# Test setting a list of parameters
|
|
152
|
+
model = Model()
|
|
153
|
+
p = model.add_parameter("my_parameter")
|
|
154
|
+
p.set_value(myokit.Number(1))
|
|
155
|
+
p = model.add_parameter("my_parameter2")
|
|
156
|
+
p.set_units(1e3 * myokit.units.metre / myokit.units.second)
|
|
157
|
+
p.set_value(myokit.Number(2))
|
|
158
|
+
sbml_str = write_string(model).decode("utf8")
|
|
159
|
+
self.assertIn("<listOfParameters>", sbml_str)
|
|
160
|
+
self.assertIn(
|
|
161
|
+
'<parameter id="my_parameter" constant="true" value="1.0"/>',
|
|
162
|
+
sbml_str
|
|
163
|
+
)
|
|
164
|
+
self.assertIn(
|
|
165
|
+
'<parameter id="my_parameter2" units="m_per_s_times_1e3" constant="true" value="2.0"/>', # noqa: E501
|
|
166
|
+
sbml_str
|
|
167
|
+
)
|
|
168
|
+
self.assertNotIn("<listOfRules>", sbml_str)
|
|
169
|
+
self.assertNotIn("<listOfInitialAssignments>", sbml_str)
|
|
170
|
+
self.assertIn("<listOfUnitDefinitions>", sbml_str)
|
|
171
|
+
self.assertIn('<unitDefinition id="m_per_s_times_1e3">', sbml_str)
|
|
172
|
+
|
|
173
|
+
# Test setting a constant parameter that depends on another parameter
|
|
174
|
+
model = Model()
|
|
175
|
+
p = model.add_parameter("my_parameter")
|
|
176
|
+
p.set_value(myokit.Number(1))
|
|
177
|
+
p = model.add_parameter("my_parameter2")
|
|
178
|
+
p.set_initial_value(
|
|
179
|
+
myokit.Multiply(myokit.Name("my_parameter"), myokit.Number(2))
|
|
180
|
+
)
|
|
181
|
+
sbml_str = write_string(model).decode("utf8")
|
|
182
|
+
self.assertIn("<listOfParameters>", sbml_str)
|
|
183
|
+
self.assertIn(
|
|
184
|
+
'<parameter id="my_parameter" constant="true" value="1.0"/>',
|
|
185
|
+
sbml_str
|
|
186
|
+
)
|
|
187
|
+
self.assertIn(
|
|
188
|
+
'<parameter id="my_parameter2" constant="true"/>', # noqa: E501
|
|
189
|
+
sbml_str
|
|
190
|
+
)
|
|
191
|
+
self.assertNotIn("<listOfRules>", sbml_str)
|
|
192
|
+
self.assertIn("<listOfInitialAssignments>", sbml_str)
|
|
193
|
+
self.assertIn('<initialAssignment symbol="my_parameter2">', sbml_str)
|
|
194
|
+
self.assertIn("<times/>\n <ci>my_parameter</ci>\n <cn>2.0</cn>", sbml_str) # noqa: E501
|
|
195
|
+
|
|
196
|
+
model = Model()
|
|
197
|
+
p = model.add_parameter("my_parameter", is_constant=False)
|
|
198
|
+
p.set_initial_value(myokit.Number(1))
|
|
199
|
+
p.set_value(myokit.Number(2))
|
|
200
|
+
sbml_str = write_string(model).decode("utf8")
|
|
201
|
+
self.assertIn("<listOfRules>", sbml_str)
|
|
202
|
+
self.assertIn('<assignmentRule variable="my_parameter">', sbml_str)
|
|
203
|
+
self.assertIn("<cn>2.0</cn>", sbml_str)
|
|
204
|
+
self.assertIn("<listOfInitialAssignments>", sbml_str)
|
|
205
|
+
self.assertIn('<initialAssignment symbol="my_parameter">', sbml_str)
|
|
206
|
+
self.assertIn("<cn>1.0</cn>", sbml_str)
|
|
207
|
+
|
|
208
|
+
def test_list_of_species(self):
|
|
209
|
+
# Test setting a list of species
|
|
210
|
+
model = Model()
|
|
211
|
+
c = model.add_compartment("my_compartment")
|
|
212
|
+
s = model.add_species(c, "my_species")
|
|
213
|
+
s.set_substance_units(myokit.units.mole / myokit.units.litre)
|
|
214
|
+
s.set_value(myokit.Number(1), True)
|
|
215
|
+
s.set_initial_value(myokit.Number(2))
|
|
216
|
+
s = model.add_species(c, "my_species2")
|
|
217
|
+
s.set_substance_units(myokit.units.mole)
|
|
218
|
+
s.set_value(myokit.Number(1), True)
|
|
219
|
+
s.set_initial_value(myokit.Number(2), in_amount=True)
|
|
220
|
+
s = model.add_species(c, "my_species3", is_amount=True)
|
|
221
|
+
s.set_value(myokit.Number(1), True)
|
|
222
|
+
s.set_initial_value(myokit.Number(2))
|
|
223
|
+
s = model.add_species(c, "my_species4", is_amount=True)
|
|
224
|
+
s.set_value(myokit.Number(1), True)
|
|
225
|
+
s.set_initial_value(myokit.Number(2), in_amount=False)
|
|
226
|
+
s = model.add_species(c, "my_species5")
|
|
227
|
+
s.set_value(myokit.Number(1), False)
|
|
228
|
+
sbml_str = write_string(model).decode("utf8")
|
|
229
|
+
self.assertIn("<listOfSpecies>", sbml_str)
|
|
230
|
+
self.assertIn(
|
|
231
|
+
'<species id="my_species" compartment="my_compartment" initialConcentration="2.0" constant="False" units="M" boundaryCondition="False"/>', # noqa: E501
|
|
232
|
+
sbml_str,
|
|
233
|
+
)
|
|
234
|
+
self.assertIn(
|
|
235
|
+
'<species id="my_species2" compartment="my_compartment" initialAmount="2.0" constant="False" units="mole" boundaryCondition="False"/>', # noqa: E501
|
|
236
|
+
sbml_str,
|
|
237
|
+
)
|
|
238
|
+
self.assertIn(
|
|
239
|
+
'<species id="my_species3" compartment="my_compartment" initialAmount="2.0" constant="False" boundaryCondition="False"/>', # noqa: E501
|
|
240
|
+
sbml_str,
|
|
241
|
+
)
|
|
242
|
+
self.assertIn(
|
|
243
|
+
'<species id="my_species4" compartment="my_compartment" initialConcentration="2.0" constant="False" boundaryCondition="False"/>', # noqa: E501
|
|
244
|
+
sbml_str,
|
|
245
|
+
)
|
|
246
|
+
self.assertIn("<listOfRules>", sbml_str)
|
|
247
|
+
self.assertIn('<rateRule variable="my_species">', sbml_str)
|
|
248
|
+
self.assertIn("<cn>1.0</cn>", sbml_str)
|
|
249
|
+
self.assertIn('<assignmentRule variable="my_species5">', sbml_str)
|
|
250
|
+
|
|
251
|
+
def test_list_of_reactions(self):
|
|
252
|
+
# test kinetic law
|
|
253
|
+
model = Model()
|
|
254
|
+
c = model.add_compartment("my_compartment")
|
|
255
|
+
s = model.add_species(c, "my_species")
|
|
256
|
+
s2 = model.add_species(c, "my_species2")
|
|
257
|
+
r = model.add_reaction("my_reaction")
|
|
258
|
+
r.add_reactant(s, "my_reaction_reactant")
|
|
259
|
+
r.add_product(s)
|
|
260
|
+
r.add_modifier(s)
|
|
261
|
+
r.add_modifier(s2, "my_modifier")
|
|
262
|
+
r.set_kinetic_law(myokit.Number(1))
|
|
263
|
+
sbml_str = write_string(model).decode("utf8")
|
|
264
|
+
self.assertIn("<listOfReactions>", sbml_str)
|
|
265
|
+
self.assertIn('<reaction id="my_reaction">', sbml_str)
|
|
266
|
+
self.assertIn("<listOfReactants>", sbml_str)
|
|
267
|
+
self.assertIn("<listOfProducts>", sbml_str)
|
|
268
|
+
self.assertIn('<speciesReference species="my_species"/>', sbml_str)
|
|
269
|
+
self.assertIn('<speciesReference species="my_species" id="my_reaction_reactant"/>', sbml_str) # noqa: E501
|
|
270
|
+
self.assertIn("<listOfModifiers>", sbml_str)
|
|
271
|
+
self.assertIn(
|
|
272
|
+
'<modifierSpeciesReference species="my_species"/>',
|
|
273
|
+
sbml_str
|
|
274
|
+
)
|
|
275
|
+
self.assertIn(
|
|
276
|
+
'<modifierSpeciesReference species="my_species2" id="my_modifier"/>', # noqa: E501
|
|
277
|
+
sbml_str
|
|
278
|
+
)
|
|
279
|
+
self.assertIn("<kineticLaw>", sbml_str)
|
|
280
|
+
self.assertIn("<cn>1.0</cn>", sbml_str)
|
|
281
|
+
|
|
282
|
+
# test stochoimetry
|
|
283
|
+
model = Model()
|
|
284
|
+
c = model.add_compartment("my_compartment")
|
|
285
|
+
s = model.add_species(c, "my_species")
|
|
286
|
+
r = model.add_reaction("my_reaction")
|
|
287
|
+
react = r.add_reactant(s)
|
|
288
|
+
react.set_value(myokit.Number(1))
|
|
289
|
+
r.add_product(s)
|
|
290
|
+
sbml_str = write_string(model).decode("utf8")
|
|
291
|
+
self.assertIn(
|
|
292
|
+
'<speciesReference species="my_species" stoichiometry="1.0"/>',
|
|
293
|
+
sbml_str
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
def test_expressions_multiple_compartments(self):
|
|
297
|
+
m = myokit.Model()
|
|
298
|
+
c = m.add_component('comp')
|
|
299
|
+
t = c.add_variable('time', rhs=myokit.Number(0))
|
|
300
|
+
t.set_unit(myokit.units.second)
|
|
301
|
+
t.set_binding('time')
|
|
302
|
+
c2 = m.add_component('comp2')
|
|
303
|
+
v = c.add_variable('var', initial_value=3)
|
|
304
|
+
v.set_rhs(myokit.Name(t))
|
|
305
|
+
v2 = c2.add_variable('var', initial_value=3)
|
|
306
|
+
v2.set_rhs(myokit.Name(v))
|
|
307
|
+
|
|
308
|
+
# check that the equation is exported correctly to sbml.Model
|
|
309
|
+
s = sbml.Model.from_myokit_model(m)
|
|
310
|
+
parameter_names = [v.sid() for v in s.parameters()]
|
|
311
|
+
self.assertCountEqual(parameter_names, ['comp_var', 'comp2_var'])
|
|
312
|
+
v2_sbml = s.parameter('comp2_var')
|
|
313
|
+
self.assertEqual(
|
|
314
|
+
v2_sbml.value(),
|
|
315
|
+
myokit.Name(v)
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
# check that the equation is exported correctly to sbml string
|
|
319
|
+
sbml_str = write_string(s).decode("utf8")
|
|
320
|
+
self.assertIn('<rateRule variable="comp2_var">', sbml_str)
|
|
321
|
+
self.assertIn('<ci>comp_var</ci>', sbml_str)
|
|
322
|
+
self.assertIn('<rateRule variable="comp_var">', sbml_str)
|
|
323
|
+
self.assertIn(
|
|
324
|
+
'<ci>http://www.sbml.org/sbml/symbols/time</ci>',
|
|
325
|
+
sbml_str
|
|
326
|
+
)
|
|
327
|
+
|
myokit/tests/test_unit.py
CHANGED
|
@@ -296,24 +296,35 @@ class MyokitUnitTest(unittest.TestCase):
|
|
|
296
296
|
self.assertEqual(x.exponents(), [0, 2, 1.5, 0, 0, 0, -1.23])
|
|
297
297
|
|
|
298
298
|
def test_register_errors(self):
|
|
299
|
-
# Test errors for Unit.register (rest is already used
|
|
300
|
-
|
|
299
|
+
# Test errors for Unit.register (rest of the method is already used
|
|
300
|
+
# throughout other tests).
|
|
301
|
+
self.assertRaises(myokit.InvalidNameError, myokit.Unit.register, 4,
|
|
302
|
+
myokit.Unit())
|
|
301
303
|
self.assertRaises(TypeError, myokit.Unit.register, 'hi', 4)
|
|
302
304
|
|
|
303
305
|
def test_register_preferred_representation(self):
|
|
304
306
|
# Test new representations can be registered
|
|
305
307
|
|
|
306
|
-
u = myokit.units.
|
|
307
|
-
self.assertEqual(str(u), '[m^8]')
|
|
308
|
+
u = myokit.units.K / myokit.units.A
|
|
308
309
|
try:
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
# Register valid unit
|
|
311
|
+
self.assertEqual(str(u), '[K/A]') # also auto registers!
|
|
312
|
+
myokit.Unit.register_preferred_representation('mK/mA', u)
|
|
313
|
+
self.assertEqual(str(u), '[mK/mA]')
|
|
312
314
|
|
|
315
|
+
# Attempt registering something that isn't a unit
|
|
313
316
|
self.assertRaisesRegex(
|
|
314
317
|
ValueError, 'must be a myokit.Unit',
|
|
315
318
|
myokit.Unit.register_preferred_representation, 'x', 123)
|
|
316
319
|
|
|
320
|
+
# Attempt registering a representation that doesn't match the unit
|
|
321
|
+
self.assertRaisesRegex(
|
|
322
|
+
ValueError, r'does not equal \[K/A] when parsed',
|
|
323
|
+
myokit.Unit.register_preferred_representation, 'm', u)
|
|
324
|
+
self.assertRaisesRegex(
|
|
325
|
+
ValueError, r'does not equal \[K/A \(2\)] when parsed',
|
|
326
|
+
myokit.Unit.register_preferred_representation, 'K/A', u * 2)
|
|
327
|
+
|
|
317
328
|
finally:
|
|
318
329
|
# Bypassing the public API, this is bad test design!
|
|
319
330
|
if u in myokit.Unit._preferred_representations:
|
|
@@ -365,6 +376,16 @@ class MyokitUnitTest(unittest.TestCase):
|
|
|
365
376
|
self.assertEqual(str(c), '[V]')
|
|
366
377
|
self.assertEqual(str(d), '[V]')
|
|
367
378
|
|
|
379
|
+
# 1115: Test str() doesn't create representations with more than one
|
|
380
|
+
# multiplier.
|
|
381
|
+
unit1 = myokit.units.mol / (1e3 * myokit.units.g)
|
|
382
|
+
unit2 = 1e-12 * myokit.units.mol / (1e3 * myokit.units.g)
|
|
383
|
+
unit3 = 1e-6 * unit2
|
|
384
|
+
self.assertEqual(str(unit1), '[mol/g (0.001)]')
|
|
385
|
+
self.assertEqual(str(unit2), '[mol/g (1e-15)]')
|
|
386
|
+
# Before fixing 1115, this returned [mol/g (0.001) (1e-12)]
|
|
387
|
+
self.assertEqual(str(unit3), '[mol/g (1e-21)]')
|
|
388
|
+
|
|
368
389
|
def test_repr(self):
|
|
369
390
|
# Test :meth:`Unit.repr()`.
|
|
370
391
|
|
|
@@ -3,7 +3,7 @@ BSD 3-Clause License
|
|
|
3
3
|
Copyright (c) 2011-2017 Maastricht University. All rights reserved.
|
|
4
4
|
Copyright (c) 2017-2020 University of Oxford. All rights reserved.
|
|
5
5
|
(University of Oxford means the Chancellor, Masters and Scholars of the University of Oxford, having an administrative office at Wellington Square, Oxford OX1 2JD, UK).
|
|
6
|
-
Copyright (c) 2020-
|
|
6
|
+
Copyright (c) 2020-2025 University of Nottingham. All rights reserved.
|
|
7
7
|
|
|
8
8
|
Redistribution and use in source and binary forms, with or without
|
|
9
9
|
modification, are permitted provided that the following conditions are met:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: myokit
|
|
3
|
-
Version: 1.37.
|
|
3
|
+
Version: 1.37.3
|
|
4
4
|
Summary: A modeling and simulation tool for cardiac cellular electrophysiology
|
|
5
5
|
Home-page: http://myokit.org
|
|
6
6
|
Author: Michael Clerx
|
|
@@ -25,14 +25,14 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
License-File: LICENSE.txt
|
|
26
26
|
Requires-Dist: configparser
|
|
27
27
|
Requires-Dist: lxml
|
|
28
|
-
Requires-Dist: matplotlib
|
|
28
|
+
Requires-Dist: matplotlib >=2.2
|
|
29
29
|
Requires-Dist: numpy
|
|
30
30
|
Requires-Dist: setuptools
|
|
31
31
|
Provides-Extra: dev
|
|
32
32
|
Requires-Dist: coverage ; extra == 'dev'
|
|
33
|
-
Requires-Dist: flake8
|
|
33
|
+
Requires-Dist: flake8 >=3 ; extra == 'dev'
|
|
34
34
|
Provides-Extra: docs
|
|
35
|
-
Requires-Dist: sphinx
|
|
35
|
+
Requires-Dist: sphinx >=1.7.4 ; extra == 'docs'
|
|
36
36
|
Provides-Extra: gui
|
|
37
37
|
Requires-Dist: pyqt6 ; extra == 'gui'
|
|
38
38
|
Requires-Dist: sip ; extra == 'gui'
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
myokit/__init__.py,sha256=
|
|
1
|
+
myokit/__init__.py,sha256=6Df0drToZtBEqsRWTDtedcU_OMMn8d0oNxRtJaFAkww,13644
|
|
2
2
|
myokit/__main__.py,sha256=VXyt8m2GG62pz32H-qATT4tw988p-LlIKih0mkVYlJk,53688
|
|
3
3
|
myokit/_aux.py,sha256=x8VgBbdKF9yY7bBwi2mbuITyIzN3K7fj-ylCZrJQCJs,23948
|
|
4
4
|
myokit/_config.py,sha256=WoUMTcHOO9oerqtad7AnQgXAND41YO-WfqlSSyCuHgU,11989
|
|
5
5
|
myokit/_datablock.py,sha256=3fWSvnhJAoEUXsauOn8Qc3mC3qNAM2CGvsuBJ2ZCOzA,88717
|
|
6
|
-
myokit/_datalog.py,sha256=
|
|
6
|
+
myokit/_datalog.py,sha256=eWMpgyLa5Nx98RQZO3fK2PZKp2vLsBCddq6nB-9aVK4,77749
|
|
7
7
|
myokit/_err.py,sha256=n8Ggy2VKnyx_h_ySuNe77tIFXzh1yO7sWBvc7YPC2cM,11974
|
|
8
8
|
myokit/_expressions.py,sha256=VpxJAax0OHAWj0AnIH5xkGVWLrmVxBP9tykaccV86BU,109246
|
|
9
9
|
myokit/_io.py,sha256=2ll5Yb-sbP4tvc3pPmzhNuv_PaRMPJlNRWb1TzXfELg,8948
|
|
10
10
|
myokit/_model_api.py,sha256=LRHT-RcqyB2UTNrvg7iMXN0D_lpParrks5YKcVZPJJY,194650
|
|
11
|
-
myokit/_myokit_version.py,sha256=
|
|
11
|
+
myokit/_myokit_version.py,sha256=DpsDatFLxBQC5tRXhL6D6VFWDyhKYOxR0wnzl8CvAT4,726
|
|
12
12
|
myokit/_parsing.py,sha256=GTVUwJvqjkQ3rc6BiwMFnzanLivbSUzW796gHCTJrNg,74065
|
|
13
13
|
myokit/_progress.py,sha256=Mi2QU6Vqj4qudhXc76amXM31iID2Mo8Gljw5OH2COZ4,4410
|
|
14
14
|
myokit/_protocol.py,sha256=_N16LGHppIv4yCSPjy0q2f-Oed0yG1wMk0ipTtXnMck,30756
|
|
15
15
|
myokit/_system.py,sha256=IX3Q7_7f9X9aYsxSL2CXJc9bTcFJsJbfq_e2w-OkhOI,4602
|
|
16
|
-
myokit/_unit.py,sha256=
|
|
16
|
+
myokit/_unit.py,sha256=prEupTNDeoqf2suN_i9ffBDGfVkid49gUDBTWTVzTww,30102
|
|
17
17
|
myokit/float.py,sha256=7-BqdABN5Vm4HIgRMHSgcZ4O4Vd085-5hMB6z8zJZtg,3066
|
|
18
18
|
myokit/pacing.py,sha256=_My0GwIPJh4DuUiK_kYDNBcacUaOKsffjbK5LvgK6z8,4552
|
|
19
19
|
myokit/pype.py,sha256=JTKuoiwxGui6iqBXK4gxNlCdtH_IGY0FiZLtmaJ580c,8230
|
|
@@ -86,7 +86,7 @@ myokit/_sim/cmodel.py,sha256=9amSihccWepI1SGI98b5tvvSq2cmAMLX-ecgHoXnc0Y,15775
|
|
|
86
86
|
myokit/_sim/compiler.c,sha256=yahdqeQhEU4Uduy3xP2NS21k8h2rQXEQTWYpsE6NEFk,4047
|
|
87
87
|
myokit/_sim/compiler.py,sha256=80Qwk7_LOjbu0jt9_aeMLQMEvYj3H4xIoE525zUUEK8,2664
|
|
88
88
|
myokit/_sim/cvodessim.c,sha256=iWXHVSNTN2VqGGu24N8QFRWwpUUxDo17fTIP0Fv0Ikg,78062
|
|
89
|
-
myokit/_sim/cvodessim.py,sha256=
|
|
89
|
+
myokit/_sim/cvodessim.py,sha256=T2vwuSJFtHWTdzJv7xhFRC9l2OJY-7r4L6VVEpnIZI8,46158
|
|
90
90
|
myokit/_sim/differential.hpp,sha256=LiaFNQks_4RkWeNEnUc48XjbdYyGSsxfWo35leygM68,15446
|
|
91
91
|
myokit/_sim/fiber_tissue.c,sha256=mKtNy3Qs2Tg917hgCryaftwJGHqFn7WZAOuJWG3VVpY,47444
|
|
92
92
|
myokit/_sim/fiber_tissue.py,sha256=A3zyGPGHNjFdGgbIzCiKYN8o4L2nq7W_ZjO996jF9Kc,50780
|
|
@@ -140,9 +140,9 @@ myokit/formats/diffsl/_exporter.py,sha256=DljgcXmDenDl6xB86TErVMbJ9Xy60i7fcUTCIG
|
|
|
140
140
|
myokit/formats/easyml/__init__.py,sha256=sWn5_QQTbUzTwEB_RqsqiEGQDhNJwYQEg5ad52P0Ovg,836
|
|
141
141
|
myokit/formats/easyml/_ewriter.py,sha256=5T1GoiMtotlKMY3ZaYKcoWUeUZtWIbh3Xii8x0vis_Y,2597
|
|
142
142
|
myokit/formats/easyml/_exporter.py,sha256=lGUJBO3ZAJfVcbTBQUEkGqUqdmtMXDzfGGtVda54Bx0,15771
|
|
143
|
-
myokit/formats/heka/__init__.py,sha256=
|
|
143
|
+
myokit/formats/heka/__init__.py,sha256=JsHFKPdtzlYDgtCwA4ENODMAhOen9ygl-RwtrPXz-wU,927
|
|
144
144
|
myokit/formats/heka/_importer.py,sha256=4HaxswB8Uvngahsh34eEXaQnE9SYakpugFo3jc6VNrA,1154
|
|
145
|
-
myokit/formats/heka/_patchmaster.py,sha256=
|
|
145
|
+
myokit/formats/heka/_patchmaster.py,sha256=PjUrN6FRbKBeHOplcyR4-uQ6xJQEUDj7iwUb6p7O0sA,116522
|
|
146
146
|
myokit/formats/html/__init__.py,sha256=pFJtVdw_SIaZZO0dfYUH9XyqPO46CuxSTL4iwvcC-4U,457
|
|
147
147
|
myokit/formats/html/_exporter.py,sha256=kWTB_6peG1MoxWPnGjm35Axkmw1tONSX1dCwWt0_arE,2343
|
|
148
148
|
myokit/formats/html/_flatten.py,sha256=kosDcmr6KKrZbaIsXewGNiIAlpVq4N9POdPrKygcvQs,6606
|
|
@@ -172,10 +172,12 @@ myokit/formats/python/__init__.py,sha256=mbDDQu845wQVLwc6t0ycR0yi9muL66q6XXmqMOQ
|
|
|
172
172
|
myokit/formats/python/_ewriter.py,sha256=bdW3YrZLO7a_A_aqfnPQHAnyjU7EQBCG490oUF3JOpo,8251
|
|
173
173
|
myokit/formats/python/_exporter.py,sha256=_qgRV1mFDZxhjhWG5rUsCkhaoGh-mxiZPwYA_6RHNRA,969
|
|
174
174
|
myokit/formats/python/template/sim.py,sha256=HHQMZUFKC0711AFgaA8mgYc75O576PMIsujjm00MZcM,10311
|
|
175
|
-
myokit/formats/sbml/__init__.py,sha256=
|
|
176
|
-
myokit/formats/sbml/_api.py,sha256=
|
|
175
|
+
myokit/formats/sbml/__init__.py,sha256=6JeedBTc4Ct-bc7Tdu_P_adKalmW3AQUj91dM3Pzwnw,944
|
|
176
|
+
myokit/formats/sbml/_api.py,sha256=JCuRzBwdRgBu5Ho8ueAqc4SeLKn3S8tHTqWVm7YVylA,64766
|
|
177
|
+
myokit/formats/sbml/_exporter.py,sha256=_cjogI63t0j_Pt6LrKvYy70_oTvvMXCHtc8j-7WZzhg,1430
|
|
177
178
|
myokit/formats/sbml/_importer.py,sha256=CiejktBXOsVmq6FuP4ayBztUJ6d4peSqjxGltTBvn38,987
|
|
178
179
|
myokit/formats/sbml/_parser.py,sha256=ZEchxxsd7IdS-PDnIDppULiUmCUlvPDYBM98cXkLTzs,29181
|
|
180
|
+
myokit/formats/sbml/_writer.py,sha256=wF9QIWJA4CPj1HiXPNKi4RRu8atsMJtpFfobrLBPpNY,13112
|
|
179
181
|
myokit/formats/stan/__init__.py,sha256=u90KilozTsG00LpWAXUPGBNztYuLfrdRk5T3j8m2z0c,2877
|
|
180
182
|
myokit/formats/stan/_ewriter.py,sha256=ro-4Dc3h_c2IxQYFeggQLOToq6Zxa_je4uAcSCjM1nY,2998
|
|
181
183
|
myokit/formats/stan/_exporter.py,sha256=ROnxBItJm4QnANbvApAyHDNvvoI_pdpsF9AfnB-2Zb0,3745
|
|
@@ -232,7 +234,7 @@ myokit/tests/test_formats_cpp.py,sha256=giVwKzbHmjqx6VZHQBI1OV4oZrBnaKmquBmWlt9i
|
|
|
232
234
|
myokit/tests/test_formats_cuda.py,sha256=wWNKT-crhknPlUoOc5h4c2k8HwJSeXTtjDFThguAw9Y,8356
|
|
233
235
|
myokit/tests/test_formats_diffsl.py,sha256=RyHdgXTPIP1tTXvjcF0BAc274zTajow798P6kZ2gWmE,22167
|
|
234
236
|
myokit/tests/test_formats_easyml.py,sha256=VcWbmNOYEipiTPIV8JUkeymW_CsGzEklU20ofBZTjEY,12947
|
|
235
|
-
myokit/tests/test_formats_exporters_run.py,sha256
|
|
237
|
+
myokit/tests/test_formats_exporters_run.py,sha256=-rOLdQwZ1C4NKn6ePtsG5xeplUXRSLfa1G1DtWHXj1c,6825
|
|
236
238
|
myokit/tests/test_formats_html.py,sha256=k2atyU5L9krTv1fMIcHyRPftjGeRA-axT4SnPjfwkMs,3520
|
|
237
239
|
myokit/tests/test_formats_latex.py,sha256=AR6FhoCYyoiYrgO4PwWnLNpVKXWPKnyDoYX4Bujgzsg,8568
|
|
238
240
|
myokit/tests/test_formats_mathml_content.py,sha256=4QRrvEaaAjw9h8waF4NbAY7ofsx-zNiMq2oO7rhYREs,38093
|
|
@@ -240,7 +242,7 @@ myokit/tests/test_formats_mathml_presentation.py,sha256=cndbxwgNetfYXw8PMbnSbT54
|
|
|
240
242
|
myokit/tests/test_formats_matlab.py,sha256=YhaOqyEb4vmoeq9P3fVSlWUpIu9PFSPpROl2H0WvTIA,7740
|
|
241
243
|
myokit/tests/test_formats_opencl.py,sha256=Zjx6GiQcguvd4kIj4rGvdrEzdnfEZwUGR4G1B_tHQ1o,7555
|
|
242
244
|
myokit/tests/test_formats_python.py,sha256=3WMQ4eO-cMQfQ0Vk3-qwu3SorhQ_MPaX5CII9BzssdM,21961
|
|
243
|
-
myokit/tests/test_formats_sbml.py,sha256=
|
|
245
|
+
myokit/tests/test_formats_sbml.py,sha256=TGMPz_n1sFg1WT2LEr0pE_p7R-UO-RWA8FHVfSgM1OI,6716
|
|
244
246
|
myokit/tests/test_formats_stan.py,sha256=5Ns7WAGWLmrW68ssDyzPJCGVE8Gkz7_AQwii26h5RQY,5831
|
|
245
247
|
myokit/tests/test_formats_sympy.py,sha256=Ue7uwq5mQJY0E3stBDkcLyZMrtbJ0X-IQPlQxioUj7U,10740
|
|
246
248
|
myokit/tests/test_formats_wcp.py,sha256=r_ydb7bFBTIpyhTI_O1W3NVuDOYkaPNJPfYQzr7uH_s,8140
|
|
@@ -266,9 +268,10 @@ myokit/tests/test_protocol.py,sha256=DThz7WImRqUngx91GzVX5niJVhAUy7Z3eOKXNBChLlY
|
|
|
266
268
|
myokit/tests/test_protocol_floating_point.py,sha256=R7It9eIHn1l3T-xHuJNaJw-hnIFOl1TXpmh_xZ5VhCI,12565
|
|
267
269
|
myokit/tests/test_protocol_time_series.py,sha256=ktBkmKNtonorKa--g3nSQZ3nga88IEn_-BHp8n9IflY,2318
|
|
268
270
|
myokit/tests/test_pype.py,sha256=vf3mympasLZwgTUQTSoe8e98Hp31cXo71APjlZEANKE,2402
|
|
269
|
-
myokit/tests/test_quantity.py,sha256=
|
|
271
|
+
myokit/tests/test_quantity.py,sha256=etmbqlqBNt2OZFku_P-s5n8RlA-gxVyRAWjOPq9xD7s,7373
|
|
270
272
|
myokit/tests/test_rhs_benchmarker.py,sha256=Gb3LaAiu8SW__BBM3l0TbMzxML1PpEqm3g8TCteyCZg,3452
|
|
271
|
-
myokit/tests/test_sbml_api.py,sha256=
|
|
273
|
+
myokit/tests/test_sbml_api.py,sha256=9SIwsAT5lyGYnVZvPjW-EOd6mdIbrGMFpB5e981vAxM,74820
|
|
274
|
+
myokit/tests/test_sbml_export.py,sha256=qdhSZ_zht_yOLJ3OfY2yt1-5uwj48nWn2Xtn5nSH8mo,13351
|
|
272
275
|
myokit/tests/test_sbml_parser.py,sha256=ipiFs8VHcXq1-yC_9XUuonMQPLhlrYdkqvQ05BdtYiw,54542
|
|
273
276
|
myokit/tests/test_simulation_1d.py,sha256=YIjqVoyOgxrvAabpSOfLfUAOBR6dIKJoqac92VjL4ww,19281
|
|
274
277
|
myokit/tests/test_simulation_cvodes.py,sha256=wqjp8D8ksINWmC1tyYeSpAaAzGqrpXVOYvqip1FObSI,48408
|
|
@@ -281,7 +284,7 @@ myokit/tests/test_simulation_opencl_vs_cvode.py,sha256=5b-dlUCwh7LieRoAb44OgxvwQ
|
|
|
281
284
|
myokit/tests/test_simulation_opencl_vs_sim1d.py,sha256=QYXZZay_YiHZ1qPO0naGP4U1YtSS0yR1QtEv76GBah0,5216
|
|
282
285
|
myokit/tests/test_system_info.py,sha256=H4vcHTc0HCfVd0mUfVgQDUgwNIwMa9g43rBapGR6NAs,562
|
|
283
286
|
myokit/tests/test_tools.py,sha256=1-Gn7MGrXcINZa1hcgtVevcPYkaksx_bgzgSwwYRNfE,10358
|
|
284
|
-
myokit/tests/test_unit.py,sha256=
|
|
287
|
+
myokit/tests/test_unit.py,sha256=JcfEHnz0fTLm0Bq7RamkxpvjynAE_s4c1Sasfabdesw,14752
|
|
285
288
|
myokit/tests/test_user_functions.py,sha256=r7Xc3eJv-SIELMEGxx77Od2c_eBii5gjTvqarQvgteU,1721
|
|
286
289
|
myokit/tests/test_variable.py,sha256=siV8OKkPpg0QPXeM_FaeQ_aa2dmLGppFCD-PUDacUEY,33331
|
|
287
290
|
myokit/tests/data/beeler-1977-model-compare-a.mmt,sha256=Erkz4rr7irVeOPJRGvDJ-9c0iD1125xq9lLeQ6CwmK8,3022
|
|
@@ -398,9 +401,9 @@ myokit/tests/data/multi/beeler-no-name.mmt,sha256=tBeWcTVag1gAQAvxWlUqH6GQhF1D4D
|
|
|
398
401
|
myokit/tests/data/multi/lr-1991.mmt,sha256=9jzHRAy1nLiBOPioiEpXmsRvIqwEezRY_ve2eHMDbTQ,6013
|
|
399
402
|
myokit/tests/data/multi/not-a-model.csv,sha256=7ek3pQXr2fpjNjFTs-B-T_kEehx8IQ-evdcg24dtMEs,109
|
|
400
403
|
myokit/tests/data/multi/subdir/beeler-no-name.mmt,sha256=tBeWcTVag1gAQAvxWlUqH6GQhF1D4DMnlmuePQn1vBY,3008
|
|
401
|
-
myokit-1.37.
|
|
402
|
-
myokit-1.37.
|
|
403
|
-
myokit-1.37.
|
|
404
|
-
myokit-1.37.
|
|
405
|
-
myokit-1.37.
|
|
406
|
-
myokit-1.37.
|
|
404
|
+
myokit-1.37.3.dist-info/LICENSE.txt,sha256=0WNshB_he7HnJ4ROvVAaX95yz9760DE9ps8PbyvrGvw,1833
|
|
405
|
+
myokit-1.37.3.dist-info/METADATA,sha256=NocrKBZA4t1VCvp0KCNuoSQfAoRzngbbE4XEvtPlkXw,6273
|
|
406
|
+
myokit-1.37.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
407
|
+
myokit-1.37.3.dist-info/entry_points.txt,sha256=yP9wy3w0YAAYUD5PYGliYKhnKvEp5l6p4S_XvXsqreM,48
|
|
408
|
+
myokit-1.37.3.dist-info/top_level.txt,sha256=vopnhGEticqud7tKy6L6dvi_n_AMXoiYBEiboRTnsWY,7
|
|
409
|
+
myokit-1.37.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|