myokit 1.34.0__py3-none-any.whl → 1.35.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- myokit/__init__.py +5 -23
- myokit/__main__.py +70 -117
- myokit/_aux.py +5 -8
- myokit/_config.py +22 -31
- myokit/_datablock.py +26 -70
- myokit/_datalog.py +23 -53
- myokit/_err.py +13 -15
- myokit/_expressions.py +35 -55
- myokit/_io.py +5 -22
- myokit/_model_api.py +34 -47
- myokit/_myokit_version.py +1 -5
- myokit/_parsing.py +17 -25
- myokit/_progress.py +4 -7
- myokit/_protocol.py +6 -9
- myokit/_sim/__init__.py +7 -24
- myokit/_sim/cable.c +1 -3
- myokit/_sim/cable.py +3 -5
- myokit/_sim/cmodel.h +1 -3
- myokit/_sim/cmodel.py +1 -4
- myokit/_sim/compiler.py +1 -4
- myokit/_sim/cvodessim.c +1 -4
- myokit/_sim/cvodessim.py +1 -4
- myokit/_sim/fiber_tissue.c +2 -6
- myokit/_sim/fiber_tissue.py +3 -5
- myokit/_sim/jacobian.py +6 -7
- myokit/_sim/mcl.h +51 -53
- myokit/_sim/opencl.py +9 -22
- myokit/_sim/openclsim.c +2 -6
- myokit/_sim/openclsim.py +6 -6
- myokit/_sim/pacing.h +2 -6
- myokit/_sim/rhs.c +3 -10
- myokit/_sim/rhs.py +4 -13
- myokit/_sim/sundials.py +1 -4
- myokit/_system.py +10 -16
- myokit/_unit.py +3 -12
- myokit/float.py +0 -3
- myokit/formats/__init__.py +8 -10
- myokit/formats/ansic/__init__.py +0 -3
- myokit/formats/ansic/_ewriter.py +2 -4
- myokit/formats/ansic/_exporter.py +0 -3
- myokit/formats/axon/__init__.py +1 -3
- myokit/formats/axon/_abf.py +12 -15
- myokit/formats/axon/_atf.py +5 -6
- myokit/formats/axon/_importer.py +0 -3
- myokit/formats/cellml/__init__.py +0 -3
- myokit/formats/cellml/_ewriter.py +3 -6
- myokit/formats/cellml/_exporter.py +3 -6
- myokit/formats/cellml/_importer.py +1 -4
- myokit/formats/cellml/v1/__init__.py +0 -4
- myokit/formats/cellml/v1/_api.py +7 -10
- myokit/formats/cellml/v1/_parser.py +2 -5
- myokit/formats/cellml/v1/_writer.py +2 -11
- myokit/formats/cellml/v2/__init__.py +0 -3
- myokit/formats/cellml/v2/_api.py +7 -16
- myokit/formats/cellml/v2/_parser.py +2 -5
- myokit/formats/cellml/v2/_writer.py +1 -4
- myokit/formats/channelml/__init__.py +0 -3
- myokit/formats/channelml/_importer.py +4 -14
- myokit/formats/cpp/__init__.py +1 -3
- myokit/formats/cpp/_ewriter.py +0 -3
- myokit/formats/cuda/__init__.py +0 -3
- myokit/formats/cuda/_ewriter.py +2 -4
- myokit/formats/cuda/_exporter.py +0 -3
- myokit/formats/easyml/__init__.py +0 -3
- myokit/formats/easyml/_ewriter.py +9 -11
- myokit/formats/easyml/_exporter.py +0 -3
- myokit/formats/html/__init__.py +0 -3
- myokit/formats/html/_exporter.py +0 -3
- myokit/formats/html/_flatten.py +5 -21
- myokit/formats/latex/__init__.py +0 -3
- myokit/formats/latex/_ewriter.py +1 -4
- myokit/formats/latex/_exporter.py +3 -5
- myokit/formats/mathml/__init__.py +0 -3
- myokit/formats/mathml/_ewriter.py +2 -11
- myokit/formats/mathml/_parser.py +3 -5
- myokit/formats/matlab/__init__.py +0 -3
- myokit/formats/matlab/_ewriter.py +1 -4
- myokit/formats/matlab/_exporter.py +0 -3
- myokit/formats/opencl/__init__.py +0 -3
- myokit/formats/opencl/_ewriter.py +2 -4
- myokit/formats/opencl/_exporter.py +0 -3
- myokit/formats/python/__init__.py +0 -3
- myokit/formats/python/_ewriter.py +2 -5
- myokit/formats/python/_exporter.py +0 -3
- myokit/formats/python/template/sim.py +10 -10
- myokit/formats/sbml/__init__.py +0 -3
- myokit/formats/sbml/_api.py +17 -11
- myokit/formats/sbml/_importer.py +1 -4
- myokit/formats/sbml/_parser.py +2 -5
- myokit/formats/stan/__init__.py +0 -3
- myokit/formats/stan/_ewriter.py +2 -4
- myokit/formats/stan/_exporter.py +1 -4
- myokit/formats/sympy/__init__.py +0 -3
- myokit/formats/sympy/_ereader.py +1 -4
- myokit/formats/sympy/_ewriter.py +2 -5
- myokit/formats/wcp/__init__.py +0 -3
- myokit/formats/wcp/_wcp.py +1 -7
- myokit/formats/xml/__init__.py +0 -3
- myokit/formats/xml/_exporter.py +0 -3
- myokit/formats/xml/_split.py +0 -3
- myokit/gui/__init__.py +75 -247
- myokit/gui/datablock_viewer.py +100 -83
- myokit/gui/datalog_viewer.py +32 -44
- myokit/gui/explorer.py +15 -21
- myokit/gui/ide.py +105 -125
- myokit/gui/progress.py +9 -9
- myokit/gui/source.py +405 -374
- myokit/gui/vargrapher.py +2 -12
- myokit/lib/deps.py +7 -8
- myokit/lib/guess.py +1 -2
- myokit/lib/hh.py +5 -7
- myokit/lib/markov.py +9 -11
- myokit/lib/multi.py +1 -3
- myokit/lib/plots.py +1 -3
- myokit/pacing.py +0 -3
- myokit/pype.py +7 -18
- myokit/tests/__init__.py +3 -6
- myokit/tests/ansic_event_based_pacing.py +1 -4
- myokit/tests/ansic_fixed_form_pacing.py +1 -4
- myokit/tests/test_aux.py +9 -23
- myokit/tests/test_cellml_v1_api.py +1 -16
- myokit/tests/test_cellml_v1_parser.py +0 -15
- myokit/tests/test_cellml_v1_writer.py +0 -9
- myokit/tests/test_cellml_v2_api.py +1 -16
- myokit/tests/test_cellml_v2_parser.py +0 -15
- myokit/tests/test_cellml_v2_writer.py +0 -9
- myokit/tests/test_cmodel.py +0 -9
- myokit/tests/test_compiler_detection.py +1 -11
- myokit/tests/test_component.py +0 -10
- myokit/tests/test_config.py +33 -66
- myokit/tests/test_datablock.py +1 -9
- myokit/tests/test_datalog.py +4 -21
- myokit/tests/test_dependency_checking.py +8 -23
- myokit/tests/test_expressions.py +0 -9
- myokit/tests/test_float.py +1 -5
- myokit/tests/test_formats.py +0 -9
- myokit/tests/test_formats_axon.py +1 -9
- myokit/tests/test_formats_cellml.py +0 -15
- myokit/tests/test_formats_channelml.py +0 -15
- myokit/tests/test_formats_easyml.py +0 -14
- myokit/tests/test_formats_exporters.py +1 -16
- myokit/tests/test_formats_expression_writers.py +1 -17
- myokit/tests/test_formats_html.py +0 -3
- myokit/tests/test_formats_importers.py +1 -16
- myokit/tests/test_formats_mathml_content.py +0 -9
- myokit/tests/test_formats_mathml_presentation.py +0 -9
- myokit/tests/test_formats_opencl.py +0 -10
- myokit/tests/test_formats_sbml.py +0 -15
- myokit/tests/test_formats_sympy.py +0 -9
- myokit/tests/test_formats_wcp.py +1 -3
- myokit/tests/test_io.py +6 -14
- myokit/tests/test_jacobian_calculator.py +1 -9
- myokit/tests/test_jacobian_tracer.py +0 -9
- myokit/tests/test_lib_deps.py +0 -9
- myokit/tests/test_lib_guess.py +0 -9
- myokit/tests/test_lib_hh.py +1 -9
- myokit/tests/test_lib_markov.py +1 -9
- myokit/tests/test_lib_multi.py +0 -9
- myokit/tests/test_lib_plots.py +0 -3
- myokit/tests/test_meta.py +0 -3
- myokit/tests/test_model.py +0 -10
- myokit/tests/test_model_building.py +2 -17
- myokit/tests/test_opencl_info.py +5 -14
- myokit/tests/test_pacing_factory.py +0 -3
- myokit/tests/test_pacing_system_c.py +0 -9
- myokit/tests/test_pacing_system_py.py +0 -9
- myokit/tests/test_parsing.py +5 -20
- myokit/tests/test_progress_reporters.py +0 -3
- myokit/tests/test_protocol.py +0 -9
- myokit/tests/test_protocol_floating_point.py +0 -9
- myokit/tests/test_protocol_time_series.py +0 -10
- myokit/tests/test_pype.py +0 -9
- myokit/tests/test_quantity.py +0 -9
- myokit/tests/test_rhs_benchmarker.py +1 -9
- myokit/tests/test_sbml_api.py +0 -15
- myokit/tests/test_sbml_parser.py +0 -15
- myokit/tests/test_simulation_1d.py +1 -10
- myokit/tests/test_simulation_cvodes.py +8 -16
- myokit/tests/test_simulation_cvodes_from_disk.py +0 -3
- myokit/tests/test_simulation_fiber_tissue.py +1 -10
- myokit/tests/test_simulation_log_interval.py +0 -9
- myokit/tests/test_simulation_opencl.py +1 -10
- myokit/tests/test_simulation_opencl_log_interval.py +1 -3
- myokit/tests/test_simulation_opencl_vs_cvode.py +1 -10
- myokit/tests/test_simulation_opencl_vs_sim1d.py +1 -10
- myokit/tests/test_system_info.py +1 -11
- myokit/tests/test_tools.py +0 -9
- myokit/tests/test_unit.py +0 -9
- myokit/tests/test_user_functions.py +0 -10
- myokit/tests/test_variable.py +0 -10
- myokit/tools.py +5 -21
- myokit/units.py +0 -3
- {myokit-1.34.0.dist-info → myokit-1.35.0.dist-info}/METADATA +7 -7
- {myokit-1.34.0.dist-info → myokit-1.35.0.dist-info}/RECORD +198 -200
- myokit/_exec_new.py +0 -15
- myokit/_exec_old.py +0 -15
- {myokit-1.34.0.dist-info → myokit-1.35.0.dist-info}/LICENSE.txt +0 -0
- {myokit-1.34.0.dist-info → myokit-1.35.0.dist-info}/WHEEL +0 -0
- {myokit-1.34.0.dist-info → myokit-1.35.0.dist-info}/entry_points.txt +0 -0
- {myokit-1.34.0.dist-info → myokit-1.35.0.dist-info}/top_level.txt +0 -0
myokit/_expressions.py
CHANGED
|
@@ -5,26 +5,14 @@
|
|
|
5
5
|
# This file is part of Myokit.
|
|
6
6
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
7
7
|
#
|
|
8
|
-
|
|
9
|
-
from __future__ import print_function, unicode_literals
|
|
10
|
-
|
|
8
|
+
import io
|
|
11
9
|
import math
|
|
12
10
|
import numpy
|
|
13
11
|
|
|
14
12
|
import myokit
|
|
15
|
-
from myokit import IntegrityError
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
try:
|
|
19
|
-
from cStringIO import StringIO
|
|
20
|
-
except ImportError:
|
|
21
|
-
from io import StringIO
|
|
14
|
+
from myokit import IntegrityError
|
|
22
15
|
|
|
23
|
-
# Strings in Python 2 and 3
|
|
24
|
-
try:
|
|
25
|
-
basestring
|
|
26
|
-
except NameError: # pragma: no python 2 cover
|
|
27
|
-
basestring = str
|
|
28
16
|
|
|
29
17
|
# Expression precedence levels
|
|
30
18
|
FUNCTION_CALL = 70
|
|
@@ -37,7 +25,7 @@ CONDITION_AND = 10
|
|
|
37
25
|
LITERAL = 0
|
|
38
26
|
|
|
39
27
|
|
|
40
|
-
class Expression
|
|
28
|
+
class Expression:
|
|
41
29
|
"""
|
|
42
30
|
Myokit's most generic interface for expressions. All expressions extend
|
|
43
31
|
this class.
|
|
@@ -85,8 +73,8 @@ class Expression(object):
|
|
|
85
73
|
self._cached_unit_tolerant = None
|
|
86
74
|
self._cached_unit_strict = None
|
|
87
75
|
|
|
88
|
-
def __bool__(self):
|
|
89
|
-
|
|
76
|
+
def __bool__(self):
|
|
77
|
+
# Determines the outcome of "if expression".
|
|
90
78
|
return True
|
|
91
79
|
|
|
92
80
|
def bracket(self, op=None):
|
|
@@ -142,7 +130,7 @@ class Expression(object):
|
|
|
142
130
|
"""
|
|
143
131
|
# Note: Because variable and component names can change, the output of
|
|
144
132
|
# code can not be cached (for non-literal expressions).
|
|
145
|
-
b = StringIO()
|
|
133
|
+
b = io.StringIO()
|
|
146
134
|
self._code(b, component)
|
|
147
135
|
return b.getvalue()
|
|
148
136
|
|
|
@@ -540,8 +528,6 @@ class Expression(object):
|
|
|
540
528
|
raise NotImplementedError
|
|
541
529
|
|
|
542
530
|
def __float__(self):
|
|
543
|
-
# Cast to float is required in Python 3: numpy float etc. are ok, but
|
|
544
|
-
# this is deprecated.
|
|
545
531
|
return float(self.eval())
|
|
546
532
|
|
|
547
533
|
def __getitem__(self, key):
|
|
@@ -551,9 +537,7 @@ class Expression(object):
|
|
|
551
537
|
if self._cached_hash is None:
|
|
552
538
|
self._cached_hash = hash(self._polish())
|
|
553
539
|
return self._cached_hash
|
|
554
|
-
# Note
|
|
555
|
-
# In Python3, anything that has an __eq__ stops inheriting this hash
|
|
556
|
-
# method!
|
|
540
|
+
# Note: anything that has an __eq__ stops inheriting this hash method!
|
|
557
541
|
# From: https://docs.python.org/3.1/reference/datamodel.html
|
|
558
542
|
# > If a class that overrides __eq__() needs to retain the
|
|
559
543
|
# implementation of __hash__() from a parent class, the interpreter
|
|
@@ -631,10 +615,6 @@ class Expression(object):
|
|
|
631
615
|
def __ne__(self, other):
|
|
632
616
|
return not self.__eq__(other)
|
|
633
617
|
|
|
634
|
-
def __nonzero__(self): # pragma: no python 3 cover
|
|
635
|
-
""" Python 2 method to determine the outcome of "if expression". """
|
|
636
|
-
return True
|
|
637
|
-
|
|
638
618
|
def operator_rep(self):
|
|
639
619
|
"""
|
|
640
620
|
Returns a representation of this expression's type. (For example '+' or
|
|
@@ -653,7 +633,7 @@ class Expression(object):
|
|
|
653
633
|
variable id is immutable in the expression's lifetime.
|
|
654
634
|
"""
|
|
655
635
|
if self._cached_polish is None:
|
|
656
|
-
b = StringIO()
|
|
636
|
+
b = io.StringIO()
|
|
657
637
|
self._polishb(b)
|
|
658
638
|
self._cached_polish = b.getvalue()
|
|
659
639
|
return self._cached_polish
|
|
@@ -670,7 +650,7 @@ class Expression(object):
|
|
|
670
650
|
|
|
671
651
|
def pyfunc(self, use_numpy=True):
|
|
672
652
|
"""
|
|
673
|
-
Converts this expression to
|
|
653
|
+
Converts this expression to Python and returns the new function's
|
|
674
654
|
handle.
|
|
675
655
|
|
|
676
656
|
By default, when converting mathematical functions such as ``log``, the
|
|
@@ -691,19 +671,19 @@ class Expression(object):
|
|
|
691
671
|
# Create function
|
|
692
672
|
local = {}
|
|
693
673
|
if use_numpy:
|
|
694
|
-
|
|
674
|
+
exec(c, {'numpy': numpy}, local)
|
|
695
675
|
else:
|
|
696
|
-
|
|
676
|
+
exec(c, {'math': math}, local)
|
|
697
677
|
|
|
698
678
|
# Return
|
|
699
679
|
return local['ex_pyfunc_generated']
|
|
700
680
|
|
|
701
681
|
def pystr(self, use_numpy=False):
|
|
702
682
|
"""
|
|
703
|
-
Returns a string representing this expression in
|
|
683
|
+
Returns a string representing this expression in Python syntax.
|
|
704
684
|
|
|
705
685
|
By default, built-in functions such as 'exp' are converted to the
|
|
706
|
-
|
|
686
|
+
Python version 'math.exp'. To use the numpy versions, set
|
|
707
687
|
``numpy=True``.
|
|
708
688
|
"""
|
|
709
689
|
# Get expression writer
|
|
@@ -742,7 +722,7 @@ class Expression(object):
|
|
|
742
722
|
Returns a string representing the parse tree corresponding to this
|
|
743
723
|
expression.
|
|
744
724
|
"""
|
|
745
|
-
b = StringIO()
|
|
725
|
+
b = io.StringIO()
|
|
746
726
|
self._tree_str(b, 0)
|
|
747
727
|
return b.getvalue()
|
|
748
728
|
|
|
@@ -855,7 +835,7 @@ class Number(Expression):
|
|
|
855
835
|
_rbp = LITERAL
|
|
856
836
|
|
|
857
837
|
def __init__(self, value, unit=None):
|
|
858
|
-
super(
|
|
838
|
+
super().__init__()
|
|
859
839
|
if isinstance(value, myokit.Quantity):
|
|
860
840
|
# Conversion from Quantity class
|
|
861
841
|
if unit is not None:
|
|
@@ -869,7 +849,7 @@ class Number(Expression):
|
|
|
869
849
|
self._value = float(value) if value else 0.0
|
|
870
850
|
if unit is None or isinstance(unit, myokit.Unit):
|
|
871
851
|
self._unit = unit
|
|
872
|
-
elif isinstance(unit,
|
|
852
|
+
elif isinstance(unit, str):
|
|
873
853
|
self._unit = myokit.parse_unit(unit)
|
|
874
854
|
else:
|
|
875
855
|
raise ValueError(
|
|
@@ -1013,10 +993,10 @@ class Name(LhsExpression):
|
|
|
1013
993
|
*Extends:* :class:`LhsExpression`
|
|
1014
994
|
"""
|
|
1015
995
|
_rbp = LITERAL
|
|
1016
|
-
__hash__ = LhsExpression.__hash__
|
|
996
|
+
__hash__ = LhsExpression.__hash__
|
|
1017
997
|
|
|
1018
998
|
def __init__(self, value):
|
|
1019
|
-
super(
|
|
999
|
+
super().__init__()
|
|
1020
1000
|
self._value = value
|
|
1021
1001
|
self._references = set([self])
|
|
1022
1002
|
self._proper = isinstance(self._value, myokit.Variable)
|
|
@@ -1054,7 +1034,7 @@ class Name(LhsExpression):
|
|
|
1054
1034
|
except KeyError:
|
|
1055
1035
|
pass
|
|
1056
1036
|
b.write(self._value.qname(c))
|
|
1057
|
-
elif isinstance(self._value,
|
|
1037
|
+
elif isinstance(self._value, str):
|
|
1058
1038
|
# Allow strings for debugging
|
|
1059
1039
|
b.write('str:' + str(self._value))
|
|
1060
1040
|
else:
|
|
@@ -1125,7 +1105,7 @@ class Name(LhsExpression):
|
|
|
1125
1105
|
return self._proper and self._value.is_state()
|
|
1126
1106
|
|
|
1127
1107
|
def _polishb(self, b):
|
|
1128
|
-
if isinstance(self._value,
|
|
1108
|
+
if isinstance(self._value, str):
|
|
1129
1109
|
# Allow an exception for strings
|
|
1130
1110
|
b.write('str:')
|
|
1131
1111
|
b.write(self._value)
|
|
@@ -1153,7 +1133,7 @@ class Name(LhsExpression):
|
|
|
1153
1133
|
b.write(' ' * n + str(self._value) + '\n')
|
|
1154
1134
|
|
|
1155
1135
|
def _validate(self, trail):
|
|
1156
|
-
super(
|
|
1136
|
+
super()._validate(trail)
|
|
1157
1137
|
# Check value: String is allowed at construction for debugging, but
|
|
1158
1138
|
# not here!
|
|
1159
1139
|
if not self._proper:
|
|
@@ -1174,10 +1154,10 @@ class Derivative(LhsExpression):
|
|
|
1174
1154
|
"""
|
|
1175
1155
|
_rbp = FUNCTION_CALL
|
|
1176
1156
|
_nargs = [1] # Allows parsing as a function
|
|
1177
|
-
__hash__ = LhsExpression.__hash__
|
|
1157
|
+
__hash__ = LhsExpression.__hash__
|
|
1178
1158
|
|
|
1179
1159
|
def __init__(self, op):
|
|
1180
|
-
super(
|
|
1160
|
+
super().__init__((op,))
|
|
1181
1161
|
if not isinstance(op, Name):
|
|
1182
1162
|
raise IntegrityError(
|
|
1183
1163
|
'The dot() operator can only be used on variables.',
|
|
@@ -1274,7 +1254,7 @@ class Derivative(LhsExpression):
|
|
|
1274
1254
|
return self._op._value
|
|
1275
1255
|
|
|
1276
1256
|
def _validate(self, trail):
|
|
1277
|
-
super(
|
|
1257
|
+
super()._validate(trail)
|
|
1278
1258
|
# Check that value is a variable has already been performed by name
|
|
1279
1259
|
# Check if value is the name of a state variable
|
|
1280
1260
|
if not self._op._value.is_state():
|
|
@@ -1295,7 +1275,7 @@ class PartialDerivative(LhsExpression):
|
|
|
1295
1275
|
"""
|
|
1296
1276
|
_rbp = FUNCTION_CALL
|
|
1297
1277
|
_nargs = [2] # Allows parsing as a function
|
|
1298
|
-
__hash__ = LhsExpression.__hash__
|
|
1278
|
+
__hash__ = LhsExpression.__hash__
|
|
1299
1279
|
|
|
1300
1280
|
def __init__(self, var1, var2):
|
|
1301
1281
|
if not isinstance(var1, (Name, Derivative)):
|
|
@@ -1306,7 +1286,7 @@ class PartialDerivative(LhsExpression):
|
|
|
1306
1286
|
raise IntegrityError(
|
|
1307
1287
|
'The second argument to a partial derivative must be a'
|
|
1308
1288
|
' variable name or an initial value.')
|
|
1309
|
-
super(
|
|
1289
|
+
super().__init__((var1, var2))
|
|
1310
1290
|
|
|
1311
1291
|
self._var1 = var1
|
|
1312
1292
|
self._var2 = var2
|
|
@@ -1406,10 +1386,10 @@ class InitialValue(LhsExpression):
|
|
|
1406
1386
|
"""
|
|
1407
1387
|
_rbp = FUNCTION_CALL
|
|
1408
1388
|
_nargs = [1] # Allows parsing as a function
|
|
1409
|
-
__hash__ = LhsExpression.__hash__
|
|
1389
|
+
__hash__ = LhsExpression.__hash__
|
|
1410
1390
|
|
|
1411
1391
|
def __init__(self, var):
|
|
1412
|
-
super(
|
|
1392
|
+
super().__init__((var, ))
|
|
1413
1393
|
if not isinstance(var, Name):
|
|
1414
1394
|
raise IntegrityError(
|
|
1415
1395
|
'The first argument to an initial value must be a variable'
|
|
@@ -1468,7 +1448,7 @@ class InitialValue(LhsExpression):
|
|
|
1468
1448
|
return self._var._value
|
|
1469
1449
|
|
|
1470
1450
|
def _validate(self, trail):
|
|
1471
|
-
super(
|
|
1451
|
+
super()._validate(trail)
|
|
1472
1452
|
# Check if value is the name of a state variable
|
|
1473
1453
|
var = self._var._value
|
|
1474
1454
|
if not (isinstance(var, myokit.Variable) and var.is_state()):
|
|
@@ -1487,7 +1467,7 @@ class PrefixExpression(Expression):
|
|
|
1487
1467
|
_rep = None
|
|
1488
1468
|
|
|
1489
1469
|
def __init__(self, op):
|
|
1490
|
-
super(
|
|
1470
|
+
super().__init__((op,))
|
|
1491
1471
|
self._op = op
|
|
1492
1472
|
|
|
1493
1473
|
def bracket(self, op):
|
|
@@ -1586,7 +1566,7 @@ class InfixExpression(Expression):
|
|
|
1586
1566
|
_spaces_round_operator = True
|
|
1587
1567
|
|
|
1588
1568
|
def __init__(self, left, right):
|
|
1589
|
-
super(
|
|
1569
|
+
super().__init__((left, right))
|
|
1590
1570
|
self._op1 = left
|
|
1591
1571
|
self._op2 = right
|
|
1592
1572
|
|
|
@@ -2089,7 +2069,7 @@ class Function(Expression):
|
|
|
2089
2069
|
_rbp = FUNCTION_CALL
|
|
2090
2070
|
|
|
2091
2071
|
def __init__(self, *ops):
|
|
2092
|
-
super(
|
|
2072
|
+
super().__init__(ops)
|
|
2093
2073
|
if self._nargs is not None:
|
|
2094
2074
|
if not len(ops) in self._nargs:
|
|
2095
2075
|
raise IntegrityError(
|
|
@@ -2660,7 +2640,7 @@ class If(Function):
|
|
|
2660
2640
|
_fname = 'if'
|
|
2661
2641
|
|
|
2662
2642
|
def __init__(self, i, t, e):
|
|
2663
|
-
super(
|
|
2643
|
+
super().__init__(i, t, e)
|
|
2664
2644
|
self._i = i # if
|
|
2665
2645
|
self._t = t # then
|
|
2666
2646
|
self._e = e # else
|
|
@@ -2766,7 +2746,7 @@ class Piecewise(Function):
|
|
|
2766
2746
|
_fname = 'piecewise'
|
|
2767
2747
|
|
|
2768
2748
|
def __init__(self, *ops):
|
|
2769
|
-
super(
|
|
2749
|
+
super().__init__(*ops)
|
|
2770
2750
|
|
|
2771
2751
|
# Check number of arguments
|
|
2772
2752
|
n = len(self._operands)
|
|
@@ -2854,7 +2834,7 @@ class Piecewise(Function):
|
|
|
2854
2834
|
return iter(self._e)
|
|
2855
2835
|
|
|
2856
2836
|
|
|
2857
|
-
class Condition
|
|
2837
|
+
class Condition:
|
|
2858
2838
|
"""
|
|
2859
2839
|
*Abstract class*
|
|
2860
2840
|
|
myokit/_io.py
CHANGED
|
@@ -6,19 +6,11 @@
|
|
|
6
6
|
# This file is part of Myokit.
|
|
7
7
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
8
8
|
#
|
|
9
|
-
from __future__ import absolute_import, division
|
|
10
|
-
from __future__ import print_function, unicode_literals
|
|
11
|
-
|
|
12
9
|
import array
|
|
10
|
+
import io
|
|
13
11
|
import os
|
|
14
12
|
import sys
|
|
15
13
|
|
|
16
|
-
# StringIO in Python 2 and 3
|
|
17
|
-
try:
|
|
18
|
-
from cStringIO import StringIO
|
|
19
|
-
except ImportError: # pragma: no python 2 cover
|
|
20
|
-
from io import StringIO
|
|
21
|
-
|
|
22
14
|
import myokit
|
|
23
15
|
|
|
24
16
|
|
|
@@ -145,8 +137,6 @@ def load_state_bin(filename):
|
|
|
145
137
|
code = parts[1]
|
|
146
138
|
if code not in ['d', 'f']: # pragma: no cover
|
|
147
139
|
raise Exception('Invalid state file format [40].')
|
|
148
|
-
# Convert code to str for Python 2.7.10 (see #225)
|
|
149
|
-
code = str(code)
|
|
150
140
|
|
|
151
141
|
size = int(parts[2])
|
|
152
142
|
if size < 0: # pragma: no cover
|
|
@@ -154,10 +144,7 @@ def load_state_bin(filename):
|
|
|
154
144
|
|
|
155
145
|
# Create array, read bytes into array
|
|
156
146
|
ar = array.array(code)
|
|
157
|
-
|
|
158
|
-
ar.frombytes(f.read(info))
|
|
159
|
-
except AttributeError: # pragma: no python 3 cover
|
|
160
|
-
ar.fromstring(f.read(info))
|
|
147
|
+
ar.frombytes(f.read(info))
|
|
161
148
|
|
|
162
149
|
# Always store as little endian
|
|
163
150
|
if sys.byteorder == 'big': # pragma: no cover
|
|
@@ -184,7 +171,7 @@ def save(filename=None, model=None, protocol=None, script=None):
|
|
|
184
171
|
filename = os.path.expanduser(filename)
|
|
185
172
|
f = open(filename, 'w')
|
|
186
173
|
else:
|
|
187
|
-
f = StringIO()
|
|
174
|
+
f = io.StringIO()
|
|
188
175
|
out = None
|
|
189
176
|
try:
|
|
190
177
|
if model is not None:
|
|
@@ -297,8 +284,7 @@ def save_state_bin(filename, state, precision=myokit.DOUBLE_PRECISION):
|
|
|
297
284
|
'This method requires the `zlib` module to be installed.')
|
|
298
285
|
|
|
299
286
|
# Data type
|
|
300
|
-
|
|
301
|
-
code = str('d' if precision == myokit.DOUBLE_PRECISION else 'f')
|
|
287
|
+
code = 'd' if precision == myokit.DOUBLE_PRECISION else 'f'
|
|
302
288
|
|
|
303
289
|
# Create array, ensure it's little-endian
|
|
304
290
|
ar = array.array(code, state)
|
|
@@ -311,10 +297,7 @@ def save_state_bin(filename, state, precision=myokit.DOUBLE_PRECISION):
|
|
|
311
297
|
info.compress_type = zipfile.ZIP_DEFLATED
|
|
312
298
|
|
|
313
299
|
# Write to compressed file
|
|
314
|
-
|
|
315
|
-
ar = ar.tobytes()
|
|
316
|
-
except AttributeError: # pragma: no python 3 cover
|
|
317
|
-
ar = ar.tostring()
|
|
300
|
+
ar = ar.tobytes()
|
|
318
301
|
with zipfile.ZipFile(filename, 'w') as f:
|
|
319
302
|
f.writestr(info, ar)
|
|
320
303
|
|
myokit/_model_api.py
CHANGED
|
@@ -4,25 +4,14 @@
|
|
|
4
4
|
# This file is part of Myokit.
|
|
5
5
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
6
6
|
#
|
|
7
|
-
|
|
8
|
-
from __future__ import print_function, unicode_literals
|
|
9
|
-
|
|
10
|
-
from collections import OrderedDict
|
|
7
|
+
import io
|
|
11
8
|
import math
|
|
12
9
|
import re
|
|
13
|
-
import myokit
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
except ImportError:
|
|
19
|
-
from io import StringIO
|
|
11
|
+
from collections import OrderedDict
|
|
12
|
+
|
|
13
|
+
import myokit
|
|
20
14
|
|
|
21
|
-
# Strings in Python 2 and 3
|
|
22
|
-
try:
|
|
23
|
-
basestring
|
|
24
|
-
except NameError: # pragma: no cover
|
|
25
|
-
basestring = str
|
|
26
15
|
|
|
27
16
|
TAB = ' ' * 4
|
|
28
17
|
NAME = re.compile(r'^[a-zA-Z]\w*$')
|
|
@@ -34,8 +23,6 @@ def check_name(name):
|
|
|
34
23
|
Tests if the given name is a valid myokit name and raises a
|
|
35
24
|
:class:`myokit.InvalidNameError` if it isn't.
|
|
36
25
|
"""
|
|
37
|
-
# Note: Names are stored as str (so unicode in Python3)
|
|
38
|
-
# But the regex restriction means their format is compatible with ascii.
|
|
39
26
|
# Check str compatibility
|
|
40
27
|
name = str(name)
|
|
41
28
|
|
|
@@ -65,7 +52,7 @@ class MetaDataContainer(dict):
|
|
|
65
52
|
raise myokit.InvalidMetaDataNameError(
|
|
66
53
|
'The key <' + str(key) + '>'
|
|
67
54
|
' is not a valid meta-data property identifier.')
|
|
68
|
-
return super(
|
|
55
|
+
return super().__getitem__(key)
|
|
69
56
|
|
|
70
57
|
def __setitem__(self, key, item):
|
|
71
58
|
# Check item
|
|
@@ -75,10 +62,10 @@ class MetaDataContainer(dict):
|
|
|
75
62
|
raise myokit.InvalidMetaDataNameError(
|
|
76
63
|
'The key <' + str(key) + '>'
|
|
77
64
|
' is not a valid meta-data property identifier.')
|
|
78
|
-
super(
|
|
65
|
+
super().__setitem__(key, item)
|
|
79
66
|
|
|
80
67
|
|
|
81
|
-
class ObjectWithMeta
|
|
68
|
+
class ObjectWithMeta:
|
|
82
69
|
"""
|
|
83
70
|
Base class for objects with meta data.
|
|
84
71
|
|
|
@@ -87,7 +74,7 @@ class ObjectWithMeta(object):
|
|
|
87
74
|
"""
|
|
88
75
|
|
|
89
76
|
def __init__(self):
|
|
90
|
-
super(
|
|
77
|
+
super().__init__()
|
|
91
78
|
self.meta = MetaDataContainer()
|
|
92
79
|
|
|
93
80
|
def _clone_metadata(self, clone):
|
|
@@ -135,7 +122,7 @@ class ModelPart(ObjectWithMeta):
|
|
|
135
122
|
The given parent should be a ModelPart or None. The name should be
|
|
136
123
|
unique within the set of children for the given parent.
|
|
137
124
|
"""
|
|
138
|
-
super(
|
|
125
|
+
super().__init__()
|
|
139
126
|
self._parent = parent # This object's parent
|
|
140
127
|
self._model = None # The model this object belongs to
|
|
141
128
|
self._name = str(name) # Local name
|
|
@@ -153,7 +140,7 @@ class ModelPart(ObjectWithMeta):
|
|
|
153
140
|
"""
|
|
154
141
|
Returns this object in ``mmt`` syntax.
|
|
155
142
|
"""
|
|
156
|
-
b = StringIO()
|
|
143
|
+
b = io.StringIO()
|
|
157
144
|
self._code(b, 0)
|
|
158
145
|
return b.getvalue()
|
|
159
146
|
|
|
@@ -162,7 +149,7 @@ class ModelPart(ObjectWithMeta):
|
|
|
162
149
|
Internal version of _code(), to be implemented by all subclasses.
|
|
163
150
|
|
|
164
151
|
The argument ``t`` specifies the number of tabs to indent the code
|
|
165
|
-
with. The argument ``b`` is a
|
|
152
|
+
with. The argument ``b`` is a StringIO buffer.
|
|
166
153
|
"""
|
|
167
154
|
raise NotImplementedError
|
|
168
155
|
|
|
@@ -249,7 +236,7 @@ class ModelPart(ObjectWithMeta):
|
|
|
249
236
|
return self._uname
|
|
250
237
|
|
|
251
238
|
|
|
252
|
-
class VarProvider
|
|
239
|
+
class VarProvider:
|
|
253
240
|
"""
|
|
254
241
|
*Abstract class*
|
|
255
242
|
|
|
@@ -463,7 +450,7 @@ class VarOwner(ModelPart, VarProvider):
|
|
|
463
450
|
"""
|
|
464
451
|
|
|
465
452
|
def __init__(self, parent, name):
|
|
466
|
-
super(
|
|
453
|
+
super().__init__(parent, name)
|
|
467
454
|
self._variables = {}
|
|
468
455
|
# Set component
|
|
469
456
|
self._component = self
|
|
@@ -789,7 +776,7 @@ class Model(ObjectWithMeta, VarProvider):
|
|
|
789
776
|
"""
|
|
790
777
|
|
|
791
778
|
def __init__(self, name=None):
|
|
792
|
-
super(
|
|
779
|
+
super().__init__()
|
|
793
780
|
|
|
794
781
|
# A dictionary of components
|
|
795
782
|
self._components = {}
|
|
@@ -1124,7 +1111,7 @@ class Model(ObjectWithMeta, VarProvider):
|
|
|
1124
1111
|
|
|
1125
1112
|
Line numbers can be added by setting ``line_numbers=True``.
|
|
1126
1113
|
"""
|
|
1127
|
-
b = StringIO()
|
|
1114
|
+
b = io.StringIO()
|
|
1128
1115
|
b.write('[[model]]\n')
|
|
1129
1116
|
self._code(b, 0)
|
|
1130
1117
|
if line_numbers:
|
|
@@ -1749,7 +1736,7 @@ class Model(ObjectWithMeta, VarProvider):
|
|
|
1749
1736
|
'as external_component, or a string if only one '
|
|
1750
1737
|
'component is provided'
|
|
1751
1738
|
)
|
|
1752
|
-
if isinstance(new_name,
|
|
1739
|
+
if isinstance(new_name, str):
|
|
1753
1740
|
if len(external_component) != 1:
|
|
1754
1741
|
raise TypeError(new_name_error_str)
|
|
1755
1742
|
new_name = [new_name]
|
|
@@ -1757,7 +1744,7 @@ class Model(ObjectWithMeta, VarProvider):
|
|
|
1757
1744
|
try:
|
|
1758
1745
|
ok = (
|
|
1759
1746
|
len(new_name) == len(external_component) and
|
|
1760
|
-
all(isinstance(name,
|
|
1747
|
+
all(isinstance(name, str) for name in new_name)
|
|
1761
1748
|
)
|
|
1762
1749
|
if not ok:
|
|
1763
1750
|
raise TypeError(new_name_error_str)
|
|
@@ -1836,7 +1823,7 @@ class Model(ObjectWithMeta, VarProvider):
|
|
|
1836
1823
|
'The variable <' + self_var.qname() + '> in the'
|
|
1837
1824
|
' given var_map\'s values is not part of this'
|
|
1838
1825
|
' model.')
|
|
1839
|
-
elif isinstance(self_var,
|
|
1826
|
+
elif isinstance(self_var, str):
|
|
1840
1827
|
try:
|
|
1841
1828
|
self_var = self.var(self_var)
|
|
1842
1829
|
except KeyError:
|
|
@@ -1858,7 +1845,7 @@ class Model(ObjectWithMeta, VarProvider):
|
|
|
1858
1845
|
'The variable <' + ext_var.qname() + '> in the'
|
|
1859
1846
|
' given var_map\'s keys but is not part of the'
|
|
1860
1847
|
' source model.')
|
|
1861
|
-
elif isinstance(ext_var,
|
|
1848
|
+
elif isinstance(ext_var, str):
|
|
1862
1849
|
try:
|
|
1863
1850
|
ext_var = ext_model.var(ext_var)
|
|
1864
1851
|
except KeyError:
|
|
@@ -2597,7 +2584,7 @@ class Model(ObjectWithMeta, VarProvider):
|
|
|
2597
2584
|
|
|
2598
2585
|
"""
|
|
2599
2586
|
n = self.count_states()
|
|
2600
|
-
if isinstance(state,
|
|
2587
|
+
if isinstance(state, str):
|
|
2601
2588
|
# String given. Parse into name:float map or list
|
|
2602
2589
|
state = myokit.parse_state(state)
|
|
2603
2590
|
if isinstance(state, dict):
|
|
@@ -2912,7 +2899,7 @@ class Model(ObjectWithMeta, VarProvider):
|
|
|
2912
2899
|
accepted by :meth:`map_to_state`.
|
|
2913
2900
|
"""
|
|
2914
2901
|
# Use map to state?
|
|
2915
|
-
if isinstance(values,
|
|
2902
|
+
if isinstance(values, str) or isinstance(values, dict):
|
|
2916
2903
|
self._state_init = [
|
|
2917
2904
|
myokit.Number(x) for x in self.map_to_state(values)]
|
|
2918
2905
|
elif len(values) != len(self._state_vars):
|
|
@@ -3655,7 +3642,7 @@ class Component(VarOwner):
|
|
|
3655
3642
|
"""
|
|
3656
3643
|
|
|
3657
3644
|
def __init__(self, model, name):
|
|
3658
|
-
super(
|
|
3645
|
+
super().__init__(model, name)
|
|
3659
3646
|
self._alias_map = {} # Maps variable names to other variables names
|
|
3660
3647
|
|
|
3661
3648
|
def _clone1(self, model, new_name=None):
|
|
@@ -3741,7 +3728,7 @@ class Component(VarOwner):
|
|
|
3741
3728
|
var._delete(recursive=True, ignore_siblings=True)
|
|
3742
3729
|
|
|
3743
3730
|
# Delete links to parent
|
|
3744
|
-
super(
|
|
3731
|
+
super()._delete()
|
|
3745
3732
|
|
|
3746
3733
|
def alias(self, name):
|
|
3747
3734
|
"""
|
|
@@ -3873,7 +3860,7 @@ class Variable(VarOwner):
|
|
|
3873
3860
|
"""
|
|
3874
3861
|
|
|
3875
3862
|
def __init__(self, parent, name):
|
|
3876
|
-
super(
|
|
3863
|
+
super().__init__(parent, name)
|
|
3877
3864
|
|
|
3878
3865
|
# Index, only set if this is a state variable
|
|
3879
3866
|
self._index = None
|
|
@@ -4280,7 +4267,7 @@ class Variable(VarOwner):
|
|
|
4280
4267
|
self._remove_variable_internal(kid)
|
|
4281
4268
|
|
|
4282
4269
|
# Remove parent links
|
|
4283
|
-
super(
|
|
4270
|
+
super()._delete()
|
|
4284
4271
|
|
|
4285
4272
|
def demote(self):
|
|
4286
4273
|
"""
|
|
@@ -4498,7 +4485,7 @@ class Variable(VarOwner):
|
|
|
4498
4485
|
# Handle string and number rhs's
|
|
4499
4486
|
model = self.model()
|
|
4500
4487
|
if not isinstance(initial_value, myokit.Expression):
|
|
4501
|
-
if isinstance(initial_value,
|
|
4488
|
+
if isinstance(initial_value, str):
|
|
4502
4489
|
# Expressions are evaluated in model context
|
|
4503
4490
|
initial_value = myokit.parse_expression(
|
|
4504
4491
|
initial_value, context=model)
|
|
@@ -4588,9 +4575,9 @@ class Variable(VarOwner):
|
|
|
4588
4575
|
# Create function
|
|
4589
4576
|
local = {}
|
|
4590
4577
|
if use_numpy:
|
|
4591
|
-
|
|
4578
|
+
exec(func, {'numpy': numpy}, local)
|
|
4592
4579
|
else:
|
|
4593
|
-
|
|
4580
|
+
exec(func, {'math': math}, local)
|
|
4594
4581
|
handle = local['var_pyfunc_generated']
|
|
4595
4582
|
|
|
4596
4583
|
# Return
|
|
@@ -4766,7 +4753,7 @@ class Variable(VarOwner):
|
|
|
4766
4753
|
# Handle strings and floats
|
|
4767
4754
|
model = self.model()
|
|
4768
4755
|
if not isinstance(value, myokit.Expression):
|
|
4769
|
-
if isinstance(value,
|
|
4756
|
+
if isinstance(value, str):
|
|
4770
4757
|
value = myokit.parse_expression(value, context=model)
|
|
4771
4758
|
else:
|
|
4772
4759
|
value = myokit.Number(value)
|
|
@@ -4834,7 +4821,7 @@ class Variable(VarOwner):
|
|
|
4834
4821
|
"""
|
|
4835
4822
|
# Handle string and number rhs's
|
|
4836
4823
|
if not isinstance(rhs, myokit.Expression):
|
|
4837
|
-
if isinstance(rhs,
|
|
4824
|
+
if isinstance(rhs, str):
|
|
4838
4825
|
rhs = myokit.parse_expression(rhs, context=self)
|
|
4839
4826
|
elif rhs is not None:
|
|
4840
4827
|
rhs = myokit.Number(rhs)
|
|
@@ -4885,7 +4872,7 @@ class Variable(VarOwner):
|
|
|
4885
4872
|
"""
|
|
4886
4873
|
if unit is None or isinstance(unit, myokit.Unit):
|
|
4887
4874
|
self._unit = unit
|
|
4888
|
-
elif isinstance(unit,
|
|
4875
|
+
elif isinstance(unit, str):
|
|
4889
4876
|
self._unit = myokit.parse_unit(unit)
|
|
4890
4877
|
else:
|
|
4891
4878
|
raise TypeError('Method set_unit() expects a myokit.Unit or None.')
|
|
@@ -5068,7 +5055,7 @@ class Variable(VarOwner):
|
|
|
5068
5055
|
return self._rhs.eval()
|
|
5069
5056
|
|
|
5070
5057
|
|
|
5071
|
-
class Equation
|
|
5058
|
+
class Equation:
|
|
5072
5059
|
"""
|
|
5073
5060
|
Defines an equation: a statement that a left-hand side (LHS) is equal to a
|
|
5074
5061
|
right-hand side (RHS) expression.
|
|
@@ -5103,7 +5090,7 @@ class Equation(object):
|
|
|
5103
5090
|
|
|
5104
5091
|
def code(self):
|
|
5105
5092
|
""" Returns an ``.mmt`` representation of this equation. """
|
|
5106
|
-
b = StringIO()
|
|
5093
|
+
b = io.StringIO()
|
|
5107
5094
|
self._lhs._code(b, None)
|
|
5108
5095
|
b.write(' = ')
|
|
5109
5096
|
self._rhs._code(b, None)
|
|
@@ -5149,7 +5136,7 @@ class EquationList(list, VarProvider):
|
|
|
5149
5136
|
return stream(self)
|
|
5150
5137
|
|
|
5151
5138
|
|
|
5152
|
-
class UserFunction
|
|
5139
|
+
class UserFunction:
|
|
5153
5140
|
"""
|
|
5154
5141
|
Represents a user function.
|
|
5155
5142
|
|
myokit/_myokit_version.py
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
# This file is part of Myokit.
|
|
5
5
|
# See http://myokit.org for copyright, sharing, and licensing details.
|
|
6
6
|
#
|
|
7
|
-
import sys
|
|
8
7
|
|
|
9
8
|
# True if this is a release, False for a development version
|
|
10
9
|
__release__ = True
|
|
@@ -15,7 +14,7 @@ __release__ = True
|
|
|
15
14
|
# incompatibility
|
|
16
15
|
# - Changes to revision indicate bugfixes, tiny new features
|
|
17
16
|
# - There is no significance to odd/even numbers
|
|
18
|
-
__version_tuple__ = 1,
|
|
17
|
+
__version_tuple__ = 1, 35, 0
|
|
19
18
|
|
|
20
19
|
# String version of the version number
|
|
21
20
|
__version__ = '.'.join([str(x) for x in __version_tuple__])
|
|
@@ -23,6 +22,3 @@ if not __release__: # pragma: no cover
|
|
|
23
22
|
__version_tuple__ += ('dev', )
|
|
24
23
|
__version__ += '.dev'
|
|
25
24
|
|
|
26
|
-
# Don't expose x on Python2
|
|
27
|
-
if sys.hexversion < 0x03000000: # pragma: no python 3 cover
|
|
28
|
-
del x
|