myokit 1.38.0__py3-none-any.whl → 1.39.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.
- myokit/__init__.py +5 -0
- myokit/_datablock.py +6 -5
- myokit/_expressions.py +6 -1
- myokit/_model_api.py +44 -18
- myokit/_myokit_version.py +1 -1
- myokit/_parsing.py +8 -2
- myokit/_sim/cvodessim.py +26 -0
- myokit/formats/__init__.py +37 -0
- myokit/formats/ansic/_ewriter.py +1 -1
- myokit/formats/axon/_abf.py +43 -9
- myokit/formats/cellml/v1/__init__.py +5 -5
- myokit/formats/cellml/v1/_api.py +220 -122
- myokit/formats/cellml/v1/_parser.py +91 -87
- myokit/formats/cellml/v1/_writer.py +13 -6
- myokit/formats/cellml/v2/__init__.py +5 -8
- myokit/formats/cellml/v2/_api.py +182 -106
- myokit/formats/cellml/v2/_parser.py +68 -64
- myokit/formats/cellml/v2/_writer.py +7 -3
- myokit/formats/heka/_patchmaster.py +71 -14
- myokit/formats/mathml/_parser.py +106 -67
- myokit/gui/source.py +18 -12
- myokit/lib/hh.py +21 -37
- myokit/tests/test_cellml_v1_api.py +227 -33
- myokit/tests/test_cellml_v1_parser.py +48 -17
- myokit/tests/test_cellml_v1_writer.py +14 -4
- myokit/tests/test_cellml_v2_api.py +132 -114
- myokit/tests/test_cellml_v2_parser.py +31 -1
- myokit/tests/test_cellml_v2_writer.py +8 -1
- myokit/tests/test_datalog.py +17 -0
- myokit/tests/test_expressions.py +61 -0
- myokit/tests/test_formats.py +99 -0
- myokit/tests/test_formats_mathml_content.py +97 -37
- myokit/tests/test_formats_python.py +1 -1
- myokit/tests/test_model_building.py +2 -0
- myokit/tests/test_parsing.py +32 -0
- myokit/tests/test_simulation_cvodes.py +10 -4
- myokit/tests/test_variable.py +10 -7
- {myokit-1.38.0.dist-info → myokit-1.39.0.dist-info}/METADATA +22 -7
- {myokit-1.38.0.dist-info → myokit-1.39.0.dist-info}/RECORD +43 -43
- {myokit-1.38.0.dist-info → myokit-1.39.0.dist-info}/WHEEL +1 -1
- {myokit-1.38.0.dist-info → myokit-1.39.0.dist-info}/entry_points.txt +0 -0
- {myokit-1.38.0.dist-info → myokit-1.39.0.dist-info/licenses}/LICENSE.txt +0 -0
- {myokit-1.38.0.dist-info → myokit-1.39.0.dist-info}/top_level.txt +0 -0
|
@@ -410,6 +410,8 @@ class TestCellML1Model(unittest.TestCase):
|
|
|
410
410
|
# Tests Model creation
|
|
411
411
|
|
|
412
412
|
m = cellml.Model('hiya')
|
|
413
|
+
self.assertEqual(m.name(), 'hiya')
|
|
414
|
+
self.assertEqual(m.version(), '1.1')
|
|
413
415
|
|
|
414
416
|
# Test bad name
|
|
415
417
|
self.assertRaisesRegex(
|
|
@@ -674,6 +676,94 @@ class TestCellML1ModelConversion(unittest.TestCase):
|
|
|
674
676
|
mm = cm.myokit_model()
|
|
675
677
|
self.assertEqual(mm.get('c.y').eval(), 6.2)
|
|
676
678
|
|
|
679
|
+
def test_m2c_initial_values(self):
|
|
680
|
+
# Test conversion of initial values
|
|
681
|
+
|
|
682
|
+
m = myokit.parse_model('''
|
|
683
|
+
[[model]]
|
|
684
|
+
x.a = 1e3
|
|
685
|
+
x.b = -1 # parsed as PrefixMinus(Number(1))
|
|
686
|
+
x.c = --+-+-5 # extreme case of same
|
|
687
|
+
x.d = 1 + sqrt(4)
|
|
688
|
+
x.e = x.p
|
|
689
|
+
x.f = x.p + 3
|
|
690
|
+
x.g = y.q
|
|
691
|
+
|
|
692
|
+
[x]
|
|
693
|
+
t = 0 bind time
|
|
694
|
+
dot(a) = 0
|
|
695
|
+
dot(b) = 1
|
|
696
|
+
dot(c) = 2
|
|
697
|
+
dot(d) = 3
|
|
698
|
+
dot(e) = 4
|
|
699
|
+
dot(f) = 5
|
|
700
|
+
dot(g) = 6
|
|
701
|
+
p = 12
|
|
702
|
+
g_init = 0
|
|
703
|
+
|
|
704
|
+
[y]
|
|
705
|
+
q = 13
|
|
706
|
+
''')
|
|
707
|
+
self.assertIsInstance(m.get('x.b').initial_value(), myokit.PrefixMinus)
|
|
708
|
+
|
|
709
|
+
# CellML 1.1
|
|
710
|
+
with WarningCollector() as w:
|
|
711
|
+
cm = cellml.Model.from_myokit_model(m, version='1.1')
|
|
712
|
+
self.assertFalse(w.has_warnings())
|
|
713
|
+
a, b, c, d, e, f, g, p = [cm['x'][i] for i in 'abcdefgp']
|
|
714
|
+
di = cm['x']['d_init']
|
|
715
|
+
fi = cm['x']['f_init']
|
|
716
|
+
gi = cm['x']['g_init_1']
|
|
717
|
+
self.assertEqual(a.initial_value(), myokit.Number(1e3))
|
|
718
|
+
self.assertEqual(b.initial_value(), myokit.Number(-1))
|
|
719
|
+
self.assertEqual(c.initial_value(), myokit.Number(5))
|
|
720
|
+
self.assertEqual(d.initial_value(), myokit.Name(di))
|
|
721
|
+
self.assertEqual(e.initial_value(), myokit.Name(p))
|
|
722
|
+
self.assertEqual(f.initial_value(), myokit.Name(fi))
|
|
723
|
+
self.assertEqual(g.initial_value(), myokit.Name(gi))
|
|
724
|
+
self.assertEqual(
|
|
725
|
+
fi.rhs(), myokit.Plus(myokit.Name(p), myokit.Number(3)))
|
|
726
|
+
# Note: ei has rhs x.q, not y.q, because connections!
|
|
727
|
+
self.assertEqual(gi.rhs(), myokit.Name(cm['x']['q']))
|
|
728
|
+
self.assertEqual(cm['x']['q'].public_interface(), 'in')
|
|
729
|
+
self.assertEqual(a.rhs(), myokit.Number(0))
|
|
730
|
+
self.assertEqual(b.rhs(), myokit.Number(1))
|
|
731
|
+
self.assertEqual(c.rhs(), myokit.Number(2))
|
|
732
|
+
self.assertEqual(d.rhs(), myokit.Number(3))
|
|
733
|
+
self.assertEqual(e.rhs(), myokit.Number(4))
|
|
734
|
+
self.assertEqual(f.rhs(), myokit.Number(5))
|
|
735
|
+
self.assertEqual(g.rhs(), myokit.Number(6))
|
|
736
|
+
cm.validate()
|
|
737
|
+
del di, fi, gi
|
|
738
|
+
|
|
739
|
+
# CellML 1.0
|
|
740
|
+
#self.assertEqual(cm['c']['x'].initial_value(), myokit.Number(2))
|
|
741
|
+
|
|
742
|
+
# Variable is OK in 1.1, but not 1.0
|
|
743
|
+
with WarningCollector() as w:
|
|
744
|
+
cm = cellml.Model.from_myokit_model(m, version='1.0')
|
|
745
|
+
self.assertEqual(w.count(), 3)
|
|
746
|
+
for warning in w.warnings():
|
|
747
|
+
self.assertIn('Incompatible expression', str(warning))
|
|
748
|
+
a, b, c, d, e, f, g, p = [cm['x'][i] for i in 'abcdefgp']
|
|
749
|
+
self.assertNotIn('f_init', cm['x'])
|
|
750
|
+
self.assertNotIn('g_init_1', cm['x'])
|
|
751
|
+
self.assertNotIn('q', cm['x'])
|
|
752
|
+
self.assertEqual(a.initial_value(), myokit.Number(1e3))
|
|
753
|
+
self.assertEqual(b.initial_value(), myokit.Number(-1))
|
|
754
|
+
self.assertEqual(c.initial_value(), myokit.Number(5))
|
|
755
|
+
self.assertEqual(d.initial_value(), myokit.Number(3))
|
|
756
|
+
self.assertEqual(e.initial_value(), myokit.Number(12))
|
|
757
|
+
self.assertEqual(f.initial_value(), myokit.Number(15))
|
|
758
|
+
self.assertEqual(g.initial_value(), myokit.Number(13))
|
|
759
|
+
self.assertEqual(a.rhs(), myokit.Number(0))
|
|
760
|
+
self.assertEqual(b.rhs(), myokit.Number(1))
|
|
761
|
+
self.assertEqual(c.rhs(), myokit.Number(2))
|
|
762
|
+
self.assertEqual(d.rhs(), myokit.Number(3))
|
|
763
|
+
self.assertEqual(e.rhs(), myokit.Number(4))
|
|
764
|
+
self.assertEqual(f.rhs(), myokit.Number(5))
|
|
765
|
+
cm.validate()
|
|
766
|
+
|
|
677
767
|
def test_m2c_oxmeta(self):
|
|
678
768
|
# Test that oxmeta data is passed on when creating a CellML model.
|
|
679
769
|
|
|
@@ -769,7 +859,7 @@ class TestCellML1ModelConversion(unittest.TestCase):
|
|
|
769
859
|
self.assertEqual(mm.name(), 'm')
|
|
770
860
|
|
|
771
861
|
# Check meta data is added
|
|
772
|
-
self.assertIn('
|
|
862
|
+
self.assertIn('mmt_authors', mm.meta)
|
|
773
863
|
|
|
774
864
|
# Check meta data is passed on
|
|
775
865
|
self.assertIn('documentation', mm.meta)
|
|
@@ -811,7 +901,7 @@ class TestCellML1ModelConversion(unittest.TestCase):
|
|
|
811
901
|
self.assertEqual(
|
|
812
902
|
mz.rhs(),
|
|
813
903
|
myokit.Plus(myokit.Number(3, myokit.units.volt), myokit.Name(mx)))
|
|
814
|
-
self.assertEqual(mz2.rhs(), myokit.Number(4
|
|
904
|
+
self.assertEqual(mz2.rhs(), myokit.Number(4))
|
|
815
905
|
|
|
816
906
|
# Check state
|
|
817
907
|
self.assertTrue(mx.is_state())
|
|
@@ -820,6 +910,62 @@ class TestCellML1ModelConversion(unittest.TestCase):
|
|
|
820
910
|
# Check binding
|
|
821
911
|
self.assertEqual(mt.binding(), 'time')
|
|
822
912
|
|
|
913
|
+
def test_c2m_initial_values(self):
|
|
914
|
+
# Test conversion of initial values as variables
|
|
915
|
+
|
|
916
|
+
# Create model
|
|
917
|
+
m = cellml.Model('m')
|
|
918
|
+
a = m.add_component('a')
|
|
919
|
+
t = a.add_variable('t', 'dimensionless')
|
|
920
|
+
m.set_free_variable(t)
|
|
921
|
+
x = a.add_variable('x', 'volt')
|
|
922
|
+
x.set_initial_value(myokit.Number(1))
|
|
923
|
+
y = a.add_variable('y', 'volt')
|
|
924
|
+
y.set_initial_value(myokit.Name(x))
|
|
925
|
+
z = a.add_variable('z', 'volt')
|
|
926
|
+
z.set_is_state(True)
|
|
927
|
+
z.set_rhs(myokit.Number(2))
|
|
928
|
+
z.set_initial_value(myokit.Name(y))
|
|
929
|
+
|
|
930
|
+
# Convert and test
|
|
931
|
+
mm = m.myokit_model()
|
|
932
|
+
mx, my, mz = mm.get('a.x'), mm.get('a.y'), mm.get('a.z')
|
|
933
|
+
self.assertEqual(mx.rhs(), myokit.Number(1))
|
|
934
|
+
self.assertEqual(my.rhs(), myokit.Name(mx))
|
|
935
|
+
self.assertEqual(mz.rhs(), myokit.Number(2))
|
|
936
|
+
self.assertEqual(mz.initial_value(), myokit.Name(my))
|
|
937
|
+
|
|
938
|
+
# Initial value in other component
|
|
939
|
+
m = cellml.Model('m')
|
|
940
|
+
a = m.add_component('a')
|
|
941
|
+
t = a.add_variable('t', 'dimensionless')
|
|
942
|
+
m.set_free_variable(t)
|
|
943
|
+
ax = a.add_variable('x', 'volt', public_interface='in')
|
|
944
|
+
y = a.add_variable('y', 'volt')
|
|
945
|
+
y.set_initial_value(myokit.Name(ax))
|
|
946
|
+
y.set_is_state(True)
|
|
947
|
+
y.set_rhs(myokit.Number(12))
|
|
948
|
+
b = m.add_component('b')
|
|
949
|
+
bx = b.add_variable('x', 'volt', public_interface='out')
|
|
950
|
+
bx.set_initial_value(3)
|
|
951
|
+
m.add_connection(ax, bx)
|
|
952
|
+
|
|
953
|
+
# Convert and test
|
|
954
|
+
mm = m.myokit_model()
|
|
955
|
+
mx, my = mm.get('b.x'), mm.get('a.y')
|
|
956
|
+
self.assertEqual(mx.rhs(), myokit.Number(3))
|
|
957
|
+
self.assertEqual(my.rhs(), myokit.Number(12))
|
|
958
|
+
self.assertEqual(my.initial_value(), myokit.Name(mx))
|
|
959
|
+
|
|
960
|
+
# Missing initial values
|
|
961
|
+
y.set_initial_value(None)
|
|
962
|
+
bx.set_initial_value(None)
|
|
963
|
+
with WarningCollector() as w:
|
|
964
|
+
mm = m.myokit_model()
|
|
965
|
+
mx, my = mm.get('b.x'), mm.get('a.y')
|
|
966
|
+
self.assertEqual(my.initial_value(), myokit.Number(0))
|
|
967
|
+
self.assertEqual(mx.rhs(), myokit.Number(0, myokit.units.volt))
|
|
968
|
+
|
|
823
969
|
def test_c2m_pass_through_variables(self):
|
|
824
970
|
# Test support for variables used only to pass a value through a
|
|
825
971
|
# hierarchical CellML structure.
|
|
@@ -1014,25 +1160,25 @@ class TestCellML1Variable(unittest.TestCase):
|
|
|
1014
1160
|
self.assertIs(v.model(), m)
|
|
1015
1161
|
|
|
1016
1162
|
def test_initial_value(self):
|
|
1017
|
-
# Tests getting and setting
|
|
1163
|
+
# Tests getting and setting initial values
|
|
1018
1164
|
|
|
1165
|
+
# Test setting and changing with numbers
|
|
1019
1166
|
v = cellml.Model('m').add_component('c').add_variable('v', 'volt')
|
|
1020
1167
|
self.assertIsNone(v.initial_value())
|
|
1021
|
-
|
|
1022
|
-
# Test setting and changing
|
|
1023
1168
|
v.set_initial_value(4)
|
|
1024
|
-
self.assertEqual(v.initial_value(), 4)
|
|
1025
|
-
|
|
1026
|
-
|
|
1169
|
+
self.assertEqual(v.initial_value(), myokit.Number(4))
|
|
1170
|
+
e = myokit.Number(-1.2e9)
|
|
1171
|
+
v.set_initial_value(e)
|
|
1172
|
+
self.assertEqual(v.initial_value(), e)
|
|
1173
|
+
|
|
1174
|
+
# Test units are stripped
|
|
1175
|
+
v.set_initial_value(myokit.Number(3, myokit.units.volt))
|
|
1176
|
+
self.assertEqual(v.initial_value(), myokit.Number(3))
|
|
1027
1177
|
|
|
1028
1178
|
# Test unsetting
|
|
1029
1179
|
v.set_initial_value(None)
|
|
1030
1180
|
self.assertIsNone(v.initial_value())
|
|
1031
1181
|
|
|
1032
|
-
# Bad value
|
|
1033
|
-
self.assertRaisesRegex(
|
|
1034
|
-
cellml.CellMLError, 'real number', v.set_initial_value, 'blue')
|
|
1035
|
-
|
|
1036
1182
|
# Bad interface
|
|
1037
1183
|
w = v.component().add_variable('w', 'volt', private_interface='in')
|
|
1038
1184
|
self.assertRaisesRegex(
|
|
@@ -1041,7 +1187,51 @@ class TestCellML1Variable(unittest.TestCase):
|
|
|
1041
1187
|
x = v.component().add_variable('x', 'volt', public_interface='in')
|
|
1042
1188
|
self.assertRaisesRegex(
|
|
1043
1189
|
cellml.CellMLError, 'public_interface="in"',
|
|
1044
|
-
x.set_initial_value,
|
|
1190
|
+
x.set_initial_value, 2)
|
|
1191
|
+
|
|
1192
|
+
# In 1.1, can be a local variable
|
|
1193
|
+
c = cellml.Model('m', version='1.1').add_component('c')
|
|
1194
|
+
v = c.add_variable('v', 'volt')
|
|
1195
|
+
w = c.add_variable('w', 'ampere')
|
|
1196
|
+
v.set_initial_value(myokit.Name(w))
|
|
1197
|
+
self.assertEqual(v.initial_value(), myokit.Name(w))
|
|
1198
|
+
|
|
1199
|
+
# But has to be a local variable
|
|
1200
|
+
z = c.model().add_component('d').add_variable('z', 'newton')
|
|
1201
|
+
self.assertRaisesRegex(
|
|
1202
|
+
cellml.CellMLError, 'from the same component',
|
|
1203
|
+
v.set_initial_value, myokit.Name(z))
|
|
1204
|
+
|
|
1205
|
+
# Can't be any other type of expression
|
|
1206
|
+
self.assertRaisesRegex(
|
|
1207
|
+
cellml.CellMLError, r'Initial value \(if set\)',
|
|
1208
|
+
v.set_initial_value,
|
|
1209
|
+
myokit.Plus(myokit.Number(1), myokit.Number(2)))
|
|
1210
|
+
# or a random object type
|
|
1211
|
+
self.assertRaisesRegex(
|
|
1212
|
+
cellml.CellMLError, r'Initial value \(if set\)',
|
|
1213
|
+
v.set_initial_value, self)
|
|
1214
|
+
|
|
1215
|
+
# In 1.0, can only be a number
|
|
1216
|
+
c = cellml.Model('m', version='1.0').add_component('c')
|
|
1217
|
+
v = c.add_variable('v', 'volt')
|
|
1218
|
+
w = c.add_variable('w', 'ampere')
|
|
1219
|
+
self.assertRaisesRegex(
|
|
1220
|
+
cellml.CellMLError, r'In CellML 1.0, an initial value \(if set\)',
|
|
1221
|
+
v.set_initial_value, myokit.Name(w))
|
|
1222
|
+
|
|
1223
|
+
# In 1.1, can also be a string
|
|
1224
|
+
c = cellml.Model('m', version='1.1').add_component('c')
|
|
1225
|
+
v = c.add_variable('v', 'volt')
|
|
1226
|
+
w = c.add_variable('w', 'ampere')
|
|
1227
|
+
v.set_initial_value('w')
|
|
1228
|
+
self.assertEqual(v.initial_value(), myokit.Name(w))
|
|
1229
|
+
c = cellml.Model('m', version='1.0').add_component('c')
|
|
1230
|
+
v = c.add_variable('v', 'volt')
|
|
1231
|
+
w = c.add_variable('w', 'ampere')
|
|
1232
|
+
self.assertRaisesRegex(
|
|
1233
|
+
cellml.CellMLError, 'In CellML 1.0, an initial value',
|
|
1234
|
+
v.set_initial_value, 'w')
|
|
1045
1235
|
|
|
1046
1236
|
def test_is_local_and_source(self):
|
|
1047
1237
|
# Tests Variable.is_local() and Variable.source() and
|
|
@@ -1099,17 +1289,16 @@ class TestCellML1Variable(unittest.TestCase):
|
|
|
1099
1289
|
v = cellml.Model('m').add_component('c').add_variable('bert', 'meter')
|
|
1100
1290
|
self.assertIsNone(v.rhs_or_initial_value())
|
|
1101
1291
|
|
|
1102
|
-
# Test initial value is returned
|
|
1103
|
-
v.set_initial_value(3)
|
|
1104
|
-
|
|
1105
|
-
self.assertEqual(v.rhs_or_initial_value(), i)
|
|
1292
|
+
# Test initial value is returned (but with units stripped)
|
|
1293
|
+
v.set_initial_value(myokit.Number(3, myokit.units.meter))
|
|
1294
|
+
self.assertEqual(v.rhs_or_initial_value(), myokit.Number(3))
|
|
1106
1295
|
|
|
1107
1296
|
# RHS takes precedence over initial value
|
|
1108
1297
|
r = myokit.Number(18, myokit.units.meter)
|
|
1109
1298
|
v.set_rhs(r)
|
|
1110
1299
|
self.assertEqual(v.rhs_or_initial_value(), r)
|
|
1111
1300
|
v.set_rhs(None)
|
|
1112
|
-
self.assertEqual(v.rhs_or_initial_value(),
|
|
1301
|
+
self.assertEqual(v.rhs_or_initial_value(), v.initial_value())
|
|
1113
1302
|
|
|
1114
1303
|
# State never returns initial value
|
|
1115
1304
|
v.set_is_state(True)
|
|
@@ -1126,6 +1315,11 @@ class TestCellML1Variable(unittest.TestCase):
|
|
|
1126
1315
|
v.set_rhs(None)
|
|
1127
1316
|
self.assertIsNone(v.rhs())
|
|
1128
1317
|
|
|
1318
|
+
# Must be an expression
|
|
1319
|
+
self.assertRaises(ValueError, v.set_rhs, 'a')
|
|
1320
|
+
self.assertRaises(ValueError, v.set_rhs, '1 + 2')
|
|
1321
|
+
self.assertRaises(ValueError, v.set_rhs, 13)
|
|
1322
|
+
|
|
1129
1323
|
# Bad interface
|
|
1130
1324
|
w = v.component().add_variable('w', 'volt', 'in')
|
|
1131
1325
|
self.assertRaisesRegex(
|
|
@@ -1564,21 +1758,21 @@ class TestCellML1Methods(unittest.TestCase):
|
|
|
1564
1758
|
u = myokit.units.meter ** 2
|
|
1565
1759
|
self.assertEqual(cellml.create_unit_name(u), 'm2')
|
|
1566
1760
|
|
|
1567
|
-
def
|
|
1568
|
-
# Tests
|
|
1569
|
-
|
|
1570
|
-
self.assertTrue(cellml.
|
|
1571
|
-
self.assertTrue(cellml.
|
|
1572
|
-
self.assertTrue(cellml.
|
|
1573
|
-
self.assertTrue(cellml.
|
|
1574
|
-
self.assertTrue(cellml.
|
|
1575
|
-
self.assertTrue(cellml.
|
|
1576
|
-
|
|
1577
|
-
self.assertFalse(cellml.
|
|
1578
|
-
self.assertFalse(cellml.
|
|
1579
|
-
self.assertFalse(cellml.
|
|
1580
|
-
self.assertFalse(cellml.
|
|
1581
|
-
self.assertFalse(cellml.
|
|
1761
|
+
def test_is_identifier(self):
|
|
1762
|
+
# Tests is_identifier().
|
|
1763
|
+
|
|
1764
|
+
self.assertTrue(cellml.is_identifier('hello'))
|
|
1765
|
+
self.assertTrue(cellml.is_identifier('h_e_l_l_o'))
|
|
1766
|
+
self.assertTrue(cellml.is_identifier('X123'))
|
|
1767
|
+
self.assertTrue(cellml.is_identifier('ZAa123_lo_2'))
|
|
1768
|
+
self.assertTrue(cellml.is_identifier('a'))
|
|
1769
|
+
self.assertTrue(cellml.is_identifier('_a'))
|
|
1770
|
+
|
|
1771
|
+
self.assertFalse(cellml.is_identifier('_'))
|
|
1772
|
+
self.assertFalse(cellml.is_identifier('123'))
|
|
1773
|
+
self.assertFalse(cellml.is_identifier('1e3'))
|
|
1774
|
+
self.assertFalse(cellml.is_identifier('3'))
|
|
1775
|
+
self.assertFalse(cellml.is_identifier(''))
|
|
1582
1776
|
|
|
1583
1777
|
|
|
1584
1778
|
if __name__ == '__main__':
|
|
@@ -537,6 +537,52 @@ class TestCellMLParser(unittest.TestCase):
|
|
|
537
537
|
self.assertBad(
|
|
538
538
|
'<import />', 'Imports are not supported', version='1.1')
|
|
539
539
|
|
|
540
|
+
def test_initial_value(self):
|
|
541
|
+
# Test setting a variable as initial value, allowed in 1.1
|
|
542
|
+
|
|
543
|
+
x = ('<component name="a">'
|
|
544
|
+
' <variable name="p" units="volt" initial_value="q" />'
|
|
545
|
+
' <variable name="q" units="volt" initial_value="12.3" />'
|
|
546
|
+
'</component>')
|
|
547
|
+
|
|
548
|
+
# Not allowed in 1.0
|
|
549
|
+
self.assertBad(x, 'In CellML 1.0, an initial', version='1.0')
|
|
550
|
+
|
|
551
|
+
# But supported in 1.1
|
|
552
|
+
m = self.parse(x, version='1.1')
|
|
553
|
+
self.assertEqual(m['a']['p'].initial_value(), myokit.Name(m['a']['q']))
|
|
554
|
+
self.assertEqual(m['a']['q'].initial_value(), myokit.Number(12.3))
|
|
555
|
+
|
|
556
|
+
# Unknown variable, or non-local (API check)
|
|
557
|
+
x = ('<component name="a">'
|
|
558
|
+
' <variable name="p" units="volt" initial_value="q" />'
|
|
559
|
+
'</component>')
|
|
560
|
+
self.assertBad(x, r'Initial value \(if set\)', version='1.1')
|
|
561
|
+
x = ('<component name="a">'
|
|
562
|
+
' <variable name="p" units="volt" initial_value="q" />'
|
|
563
|
+
'</component>'
|
|
564
|
+
'<component name="b">'
|
|
565
|
+
' <variable name="q" units="volt" initial_value="1" />'
|
|
566
|
+
'</component>')
|
|
567
|
+
self.assertBad(x, r'Initial value \(if set\)', version='1.1')
|
|
568
|
+
|
|
569
|
+
# Invalid attributes in either version (API check)
|
|
570
|
+
x = ('<component name="a">'
|
|
571
|
+
' <variable name="p" units="volt" initial_value="@" />'
|
|
572
|
+
'</component>')
|
|
573
|
+
self.assertBad(x, r'Initial value \(if set\)', version='1.1')
|
|
574
|
+
x = ('<component name="a">'
|
|
575
|
+
' <variable name="p" units="volt" initial_value="-inf" />'
|
|
576
|
+
'</component>')
|
|
577
|
+
self.assertBad(x, r'Initial value \(if set\)', version='1.1')
|
|
578
|
+
|
|
579
|
+
# Shouldn't have initial value (API check)
|
|
580
|
+
x = ('<component name="a">'
|
|
581
|
+
' <variable name="p" units="volt" initial_value="1"'
|
|
582
|
+
' public_interface="in" />'
|
|
583
|
+
'</component>')
|
|
584
|
+
self.assertBad(x, 'An initial value cannot be set', version='1.1')
|
|
585
|
+
|
|
540
586
|
def test_math(self):
|
|
541
587
|
# Tests parsing math elements
|
|
542
588
|
x = ('<component name="a">'
|
|
@@ -581,7 +627,7 @@ class TestCellMLParser(unittest.TestCase):
|
|
|
581
627
|
|
|
582
628
|
# Non-existent units
|
|
583
629
|
y = '<apply><eq /><ci>x</ci><cn cellml:units="vlop">-80</cn></apply>'
|
|
584
|
-
self.assertBad(x + y + z, 'Unknown
|
|
630
|
+
self.assertBad(x + y + z, 'Unknown units "vlop" referenced')
|
|
585
631
|
|
|
586
632
|
# Unsupported units: Warning
|
|
587
633
|
y = '<apply><eq /><ci>x</ci><cn cellml:units="celsius">2</cn></apply>'
|
|
@@ -630,21 +676,6 @@ class TestCellMLParser(unittest.TestCase):
|
|
|
630
676
|
'Unexpected attribute mathml:name',
|
|
631
677
|
)
|
|
632
678
|
|
|
633
|
-
def test_maths_1_1(self):
|
|
634
|
-
# Test setting a variable as initial value, allowed in 1.1
|
|
635
|
-
|
|
636
|
-
# Legal case in 1.1
|
|
637
|
-
x = ('<component name="a">'
|
|
638
|
-
' <variable name="p" units="volt" initial_value="q" />'
|
|
639
|
-
' <variable name="q" units="volt" initial_value="12.3" />'
|
|
640
|
-
'</component>')
|
|
641
|
-
|
|
642
|
-
# Not allowed in 1.0
|
|
643
|
-
self.assertBad(x, r'a real number \(3.4.3.7\)', version='1.0')
|
|
644
|
-
|
|
645
|
-
# Not supported in 1.1
|
|
646
|
-
self.assertBad(x, 'not supported', version='1.1')
|
|
647
|
-
|
|
648
679
|
def test_model(self):
|
|
649
680
|
# Tests parsing a model element.
|
|
650
681
|
|
|
@@ -741,7 +772,7 @@ class TestCellMLParser(unittest.TestCase):
|
|
|
741
772
|
m = self.parse(x + a + z)
|
|
742
773
|
v = m['a']['x']
|
|
743
774
|
self.assertEqual(v.rhs(), myokit.Number(3))
|
|
744
|
-
self.assertEqual(v.initial_value(), 2)
|
|
775
|
+
self.assertEqual(v.initial_value(), myokit.Number(2))
|
|
745
776
|
|
|
746
777
|
# Initial value and equation for a non-state
|
|
747
778
|
b = (' <apply>'
|
|
@@ -125,7 +125,7 @@ class TestCellMLWriter(unittest.TestCase):
|
|
|
125
125
|
self.assertIs(c.parent(), e)
|
|
126
126
|
self.assertIs(b.parent(), c)
|
|
127
127
|
|
|
128
|
-
def
|
|
128
|
+
def test_initial_values(self):
|
|
129
129
|
# Test the way initial values are represented in generated CellML code
|
|
130
130
|
|
|
131
131
|
def find(xml):
|
|
@@ -155,6 +155,16 @@ class TestCellMLWriter(unittest.TestCase):
|
|
|
155
155
|
x = find(cellml.write_string(m))
|
|
156
156
|
self.assertEqual(x, '1.23424352342422994')
|
|
157
157
|
|
|
158
|
+
# Variables (in 1.1)
|
|
159
|
+
m = cellml.Model('m', '1.1')
|
|
160
|
+
c = m.add_component('c')
|
|
161
|
+
p = c.add_variable('p', 'mole')
|
|
162
|
+
q = c.add_variable('q', 'mole')
|
|
163
|
+
q.set_rhs(myokit.Number(1))
|
|
164
|
+
p.set_initial_value(myokit.Name(q))
|
|
165
|
+
x = find(cellml.write_string(m))
|
|
166
|
+
self.assertEqual(x, 'q')
|
|
167
|
+
|
|
158
168
|
def test_maths(self):
|
|
159
169
|
# Test maths is written
|
|
160
170
|
|
|
@@ -202,7 +212,7 @@ class TestCellMLWriter(unittest.TestCase):
|
|
|
202
212
|
er2 = er1.clone(subst)
|
|
203
213
|
self.assertEqual(q2.rhs(), eq2)
|
|
204
214
|
self.assertEqual(r2.rhs(), er2)
|
|
205
|
-
self.assertEqual(s2.initial_value(), 1.23)
|
|
215
|
+
self.assertEqual(s2.initial_value(), myokit.Number(1.23))
|
|
206
216
|
self.assertFalse(p2.is_state())
|
|
207
217
|
self.assertFalse(q2.is_state())
|
|
208
218
|
self.assertTrue(r2.is_state())
|
|
@@ -323,7 +333,7 @@ class TestCellMLWriter(unittest.TestCase):
|
|
|
323
333
|
p = c.add_variable('p', 'mole')
|
|
324
334
|
q = c.add_variable('q', 'kelvin', public_interface='in')
|
|
325
335
|
r = c.add_variable('r', 'ampere', private_interface='out')
|
|
326
|
-
p.set_initial_value(1)
|
|
336
|
+
p.set_initial_value(myokit.Number(1, 'volt'))
|
|
327
337
|
|
|
328
338
|
with WarningCollector():
|
|
329
339
|
xml = cellml.write_string(m1)
|
|
@@ -339,7 +349,7 @@ class TestCellMLWriter(unittest.TestCase):
|
|
|
339
349
|
self.assertEqual(p.private_interface(), 'none')
|
|
340
350
|
self.assertEqual(q.private_interface(), 'none')
|
|
341
351
|
self.assertEqual(r.private_interface(), 'out')
|
|
342
|
-
self.assertEqual(p.initial_value(), 1)
|
|
352
|
+
self.assertEqual(p.initial_value(), myokit.Number(1))
|
|
343
353
|
self.assertEqual(q.initial_value(), None)
|
|
344
354
|
self.assertEqual(r.initial_value(), None)
|
|
345
355
|
|