myokit 1.33.9__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 +9 -36
- myokit/__main__.py +76 -142
- myokit/_aux.py +62 -16
- myokit/_bin/example.mmt +1 -2
- myokit/_bin/install-win/menu.json +7 -7
- myokit/_config.py +22 -31
- myokit/_datablock.py +30 -74
- myokit/_datalog.py +49 -72
- myokit/_err.py +25 -24
- myokit/_expressions.py +50 -68
- myokit/_io.py +15 -27
- myokit/_model_api.py +453 -249
- myokit/_myokit_version.py +1 -5
- myokit/_parsing.py +38 -44
- myokit/_progress.py +5 -8
- myokit/_protocol.py +99 -9
- myokit/_sim/__init__.py +7 -24
- myokit/_sim/cable.c +6 -8
- myokit/_sim/cable.py +6 -8
- myokit/_sim/cmodel.h +125 -70
- myokit/_sim/cmodel.py +12 -14
- myokit/_sim/compiler.py +1 -4
- myokit/_sim/cvodessim.c +196 -118
- myokit/_sim/cvodessim.py +130 -103
- myokit/_sim/differential.hpp +4 -4
- myokit/_sim/fiber_tissue.c +4 -8
- myokit/_sim/fiber_tissue.py +11 -13
- myokit/_sim/jacobian.cpp +2 -2
- myokit/_sim/jacobian.py +11 -8
- myokit/_sim/mcl.h +53 -55
- myokit/_sim/opencl.py +21 -27
- myokit/_sim/openclsim.c +3 -7
- myokit/_sim/openclsim.cl +3 -3
- myokit/_sim/openclsim.py +49 -40
- myokit/_sim/pacing.h +36 -16
- myokit/_sim/rhs.c +6 -13
- myokit/_sim/rhs.py +5 -14
- myokit/_sim/sundials.py +1 -4
- myokit/_system.py +10 -16
- myokit/_unit.py +4 -13
- 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 +1 -4
- myokit/formats/ansic/template/cable.c +4 -4
- myokit/formats/ansic/template/euler.c +5 -5
- myokit/formats/ansic/template/sim.c +6 -6
- myokit/formats/axon/__init__.py +1 -3
- myokit/formats/axon/_abf.py +12 -17
- 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 +8 -11
- 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 +8 -17
- 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 +11 -21
- 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/cuda/template/kernel.cu +8 -5
- myokit/formats/easyml/__init__.py +0 -3
- myokit/formats/easyml/_ewriter.py +9 -11
- myokit/formats/easyml/_exporter.py +2 -5
- 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 +4 -6
- myokit/formats/mathml/__init__.py +0 -3
- myokit/formats/mathml/_ewriter.py +2 -11
- myokit/formats/mathml/_parser.py +4 -6
- myokit/formats/matlab/__init__.py +0 -3
- myokit/formats/matlab/_ewriter.py +1 -4
- myokit/formats/matlab/_exporter.py +2 -5
- myokit/formats/matlab/template/main.m +3 -2
- myokit/formats/opencl/__init__.py +0 -3
- myokit/formats/opencl/_ewriter.py +2 -4
- myokit/formats/opencl/_exporter.py +2 -5
- myokit/formats/opencl/template/cable.c +10 -10
- myokit/formats/opencl/template/kernel.cl +1 -1
- myokit/formats/opencl/template/minilog.py +1 -1
- 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 +14 -14
- myokit/formats/sbml/__init__.py +0 -3
- myokit/formats/sbml/_api.py +50 -44
- 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 +2 -5
- myokit/formats/stan/template/cell.stan +3 -3
- 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 +2 -8
- 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 +80 -246
- myokit/gui/datablock_viewer.py +103 -86
- myokit/gui/datalog_viewer.py +214 -66
- myokit/gui/explorer.py +15 -21
- myokit/gui/ide.py +171 -144
- myokit/gui/progress.py +9 -9
- myokit/gui/source.py +406 -375
- myokit/gui/vargrapher.py +2 -12
- myokit/lib/deps.py +12 -13
- myokit/lib/guess.py +3 -4
- myokit/lib/hh.py +20 -18
- myokit/lib/markov.py +21 -20
- myokit/lib/multi.py +1 -3
- myokit/lib/plots.py +20 -9
- 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 +3 -6
- myokit/tests/data/beeler-1977-model-compare-b.mmt +2 -2
- myokit/tests/data/clancy-1999-fitting.mmt +1 -0
- myokit/tests/test_aux.py +13 -28
- myokit/tests/test_cellml_v1_api.py +4 -19
- 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 +4 -19
- myokit/tests/test_cellml_v2_parser.py +0 -15
- myokit/tests/test_cellml_v2_writer.py +0 -9
- myokit/tests/test_cmodel.py +16 -22
- myokit/tests/test_compiler_detection.py +1 -11
- myokit/tests/test_component.py +108 -56
- myokit/tests/test_config.py +34 -67
- myokit/tests/test_datablock.py +1 -9
- myokit/tests/test_datalog.py +19 -24
- 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 +27 -27
- myokit/tests/test_jacobian_calculator.py +6 -14
- 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 +18 -12
- myokit/tests/test_lib_markov.py +21 -13
- myokit/tests/test_lib_multi.py +0 -9
- myokit/tests/test_lib_plots.py +13 -8
- myokit/tests/test_meta.py +0 -3
- myokit/tests/test_model.py +390 -96
- myokit/tests/test_model_building.py +44 -96
- myokit/tests/test_opencl_info.py +5 -14
- myokit/tests/test_pacing_factory.py +0 -3
- myokit/tests/test_pacing_system_c.py +1 -23
- myokit/tests/test_pacing_system_py.py +0 -9
- myokit/tests/test_parsing.py +139 -56
- myokit/tests/test_progress_reporters.py +0 -3
- myokit/tests/test_protocol.py +0 -9
- myokit/tests/test_protocol_floating_point.py +1 -10
- myokit/tests/test_protocol_time_series.py +82 -0
- 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 +27 -42
- myokit/tests/test_sbml_parser.py +4 -19
- myokit/tests/test_simulation_1d.py +45 -25
- myokit/tests/test_simulation_cvodes.py +321 -55
- myokit/tests/test_simulation_cvodes_from_disk.py +0 -3
- myokit/tests/test_simulation_fiber_tissue.py +39 -12
- myokit/tests/test_simulation_log_interval.py +1 -431
- myokit/tests/test_simulation_opencl.py +69 -48
- 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 +1 -10
- myokit/tests/test_user_functions.py +0 -10
- myokit/tests/test_variable.py +231 -27
- myokit/tools.py +5 -21
- myokit/units.py +5 -3
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/METADATA +12 -15
- myokit-1.35.0.dist-info/RECORD +391 -0
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/WHEEL +1 -1
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/entry_points.txt +0 -1
- myokit/_exec_new.py +0 -15
- myokit/_exec_old.py +0 -15
- myokit/_sim/cvodesim.c +0 -1551
- myokit/_sim/cvodesim.py +0 -674
- myokit/_sim/icsim.cpp +0 -563
- myokit/_sim/icsim.py +0 -363
- myokit/_sim/psim.cpp +0 -656
- myokit/_sim/psim.py +0 -493
- myokit/lib/common.py +0 -1094
- myokit/tests/test_lib_common.py +0 -130
- myokit/tests/test_simulation_cvode.py +0 -612
- myokit/tests/test_simulation_ic.py +0 -108
- myokit/tests/test_simulation_p.py +0 -223
- myokit-1.33.9.dist-info/RECORD +0 -403
- /myokit/formats/opencl/template/{test → test.sh} +0 -0
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/LICENSE.txt +0 -0
- {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/top_level.txt +0 -0
myokit/__init__.py
CHANGED
|
@@ -20,24 +20,11 @@ and then a myokit.Simulation which you can .run() to obtain simulated results.
|
|
|
20
20
|
# Without an explicit __all__, importing * will result in importing all
|
|
21
21
|
# functions and classes described below. No submodules of myokit will be
|
|
22
22
|
# loaded!
|
|
23
|
-
|
|
24
|
-
|
|
25
23
|
#
|
|
26
24
|
# GUI and graphical modules should not be auto-included because they define a
|
|
27
25
|
# matplotlib backend to use. If the user requires a different backend, this
|
|
28
26
|
# will generate an error.
|
|
29
27
|
#
|
|
30
|
-
from __future__ import absolute_import, division
|
|
31
|
-
from __future__ import print_function, unicode_literals
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
#
|
|
35
|
-
# Configure logging
|
|
36
|
-
#
|
|
37
|
-
import logging # noqa (not at top of file)
|
|
38
|
-
logging.basicConfig()
|
|
39
|
-
del logging
|
|
40
|
-
|
|
41
28
|
|
|
42
29
|
#
|
|
43
30
|
# Check python version
|
|
@@ -52,27 +39,14 @@ del logging
|
|
|
52
39
|
#
|
|
53
40
|
import sys # noqa
|
|
54
41
|
if sys.hexversion < 0x03000000: # pragma: no cover
|
|
42
|
+
raise Exception('This version of Myokit does not support Python 2.')
|
|
43
|
+
elif sys.hexversion < 0x03070000: # pragma: no cover
|
|
55
44
|
import logging # noqa
|
|
56
45
|
log = logging.getLogger(__name__)
|
|
57
46
|
log.warning(
|
|
58
|
-
'Myokit
|
|
59
|
-
' Please upgrade as soon as possible! Detected Python version: '
|
|
60
|
-
+ sys.version)
|
|
61
|
-
del logging, log
|
|
62
|
-
elif sys.hexversion < 0x03060000: # pragma: no cover
|
|
63
|
-
import logging # noqa
|
|
64
|
-
log = logging.getLogger(__name__)
|
|
65
|
-
log.warning(
|
|
66
|
-
'Myokit is not tested on Python 3 versions older than 3.6. Detected'
|
|
47
|
+
'Myokit is not tested on Python 3 versions older than 3.7. Detected'
|
|
67
48
|
' Python version: ' + sys.version)
|
|
68
49
|
del logging, log
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
# Exec() that works with Python 2 versions before 2.7.9
|
|
72
|
-
if sys.hexversion < 0x020709F0: # pragma: no python 3 cover
|
|
73
|
-
from ._exec_old import _exec # noqa
|
|
74
|
-
else:
|
|
75
|
-
from ._exec_new import _exec # noqa
|
|
76
50
|
del sys
|
|
77
51
|
|
|
78
52
|
|
|
@@ -295,11 +269,11 @@ DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
|
|
|
295
269
|
TIME_FORMAT = '%H:%M:%S'
|
|
296
270
|
|
|
297
271
|
#
|
|
298
|
-
# GUI:
|
|
272
|
+
# GUI: Favor PySide or PyQt
|
|
299
273
|
#
|
|
274
|
+
FORCE_PYQT6 = False
|
|
300
275
|
FORCE_PYQT5 = False
|
|
301
|
-
|
|
302
|
-
FORCE_PYSIDE = False
|
|
276
|
+
FORCE_PYSIDE6 = False
|
|
303
277
|
FORCE_PYSIDE2 = False
|
|
304
278
|
|
|
305
279
|
|
|
@@ -341,6 +315,7 @@ from ._err import ( # noqa
|
|
|
341
315
|
GenerationError,
|
|
342
316
|
IllegalAliasError,
|
|
343
317
|
IllegalReferenceError,
|
|
318
|
+
IllegalReferenceInInitialValueError,
|
|
344
319
|
ImportError,
|
|
345
320
|
IncompatibleModelError,
|
|
346
321
|
IncompatibleUnitError,
|
|
@@ -354,7 +329,6 @@ from ._err import ( # noqa
|
|
|
354
329
|
MissingRhsError,
|
|
355
330
|
MissingTimeVariableError,
|
|
356
331
|
MyokitError,
|
|
357
|
-
NonLiteralValueError,
|
|
358
332
|
NumericalError,
|
|
359
333
|
ParseError,
|
|
360
334
|
ProtocolEventError,
|
|
@@ -462,6 +436,7 @@ from ._protocol import ( # noqa
|
|
|
462
436
|
PacingSystem,
|
|
463
437
|
Protocol,
|
|
464
438
|
ProtocolEvent,
|
|
439
|
+
TimeSeriesProtocol,
|
|
465
440
|
)
|
|
466
441
|
from . import pacing # noqa
|
|
467
442
|
|
|
@@ -505,6 +480,7 @@ from ._aux import ( # noqa
|
|
|
505
480
|
default_script,
|
|
506
481
|
ModelComparison,
|
|
507
482
|
numpy_writer,
|
|
483
|
+
_prepare_bindings,
|
|
508
484
|
python_writer,
|
|
509
485
|
run,
|
|
510
486
|
step,
|
|
@@ -564,11 +540,8 @@ from ._sim.opencl import ( # noqa
|
|
|
564
540
|
)
|
|
565
541
|
from ._sim.cmodel import CModel # noqa
|
|
566
542
|
from ._sim.cvodessim import Simulation # noqa
|
|
567
|
-
from ._sim.cvodesim import Simulation as LegacySimulation # noqa
|
|
568
543
|
from ._sim.cable import Simulation1d # noqa
|
|
569
544
|
from ._sim.rhs import RhsBenchmarker # noqa
|
|
570
|
-
from ._sim.icsim import ICSimulation # noqa
|
|
571
|
-
from ._sim.psim import PSimulation # noqa
|
|
572
545
|
from ._sim.jacobian import JacobianTracer, JacobianCalculator # noqa
|
|
573
546
|
from ._sim.openclsim import SimulationOpenCL # noqa
|
|
574
547
|
from ._sim.fiber_tissue import FiberTissueSimulation # noqa
|
myokit/__main__.py
CHANGED
|
@@ -4,9 +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
|
-
from __future__ import absolute_import, division
|
|
8
|
-
from __future__ import print_function, unicode_literals
|
|
9
|
-
|
|
10
7
|
import warnings
|
|
11
8
|
|
|
12
9
|
_line_width = 79
|
|
@@ -29,6 +26,55 @@ def colored(color, text):
|
|
|
29
26
|
return colors[color] + str(text) + colors['normal']
|
|
30
27
|
|
|
31
28
|
|
|
29
|
+
def qtforce(pyqt6=False, pyqt5=False, pyside6=False, pyside2=False):
|
|
30
|
+
""" Enforce a chosen Qt version. """
|
|
31
|
+
|
|
32
|
+
if pyqt6 or pyqt5 or pyside6 or pyside2:
|
|
33
|
+
import myokit
|
|
34
|
+
|
|
35
|
+
myokit.FORCE_PYQT6 = False
|
|
36
|
+
myokit.FORCE_PYQT5 = False
|
|
37
|
+
myokit.FORCE_PYSIDE6 = False
|
|
38
|
+
myokit.FORCE_PYSIDE2 = False
|
|
39
|
+
|
|
40
|
+
if pyqt6:
|
|
41
|
+
myokit.FORCE_PYQT6 = True
|
|
42
|
+
elif pyside6:
|
|
43
|
+
myokit.FORCE_PYSIDE6 = True
|
|
44
|
+
elif pyqt5:
|
|
45
|
+
myokit.FORCE_PYQT5 = True
|
|
46
|
+
elif pyside2:
|
|
47
|
+
myokit.FORCE_PYSIDE2 = True
|
|
48
|
+
|
|
49
|
+
import myokit.gui
|
|
50
|
+
print('Using backend: ' + myokit.gui.backend)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def add_qtforce_arguments(parser):
|
|
54
|
+
""" Updates a parser with arguments to force a Qt version. """
|
|
55
|
+
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
'--pyqt6',
|
|
58
|
+
action='store_true',
|
|
59
|
+
help='Run using the PyQt6 backend.',
|
|
60
|
+
)
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
'--pyqt5',
|
|
63
|
+
action='store_true',
|
|
64
|
+
help='Run using the PyQt5 backend.',
|
|
65
|
+
)
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
'--pyside6',
|
|
68
|
+
action='store_true',
|
|
69
|
+
help='Run using the PySide6 backend.',
|
|
70
|
+
)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
'--pyside2',
|
|
73
|
+
action='store_true',
|
|
74
|
+
help='Run using the PySide2 backend.',
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
32
78
|
def main():
|
|
33
79
|
"""
|
|
34
80
|
Parses command line arguments.
|
|
@@ -88,36 +134,13 @@ def main():
|
|
|
88
134
|
#
|
|
89
135
|
# Data block viewer
|
|
90
136
|
#
|
|
91
|
-
|
|
92
|
-
def block(filename, pyqt4=False, pyqt5=False, pyside=False, pyside2=False):
|
|
137
|
+
def block(filename, pyqt6=False, pyqt5=False, pyside6=False, pyside2=False):
|
|
93
138
|
"""
|
|
94
139
|
Runs the DataBlock viewer.
|
|
95
140
|
"""
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
myokit.FORCE_PYQT5 = True
|
|
99
|
-
myokit.FORCE_PYQT4 = False
|
|
100
|
-
myokit.FORCE_PYSIDE = False
|
|
101
|
-
myokit.FORCE_PYSIDE2 = False
|
|
102
|
-
elif pyqt4:
|
|
103
|
-
myokit.FORCE_PYQT5 = False
|
|
104
|
-
myokit.FORCE_PYQT4 = True
|
|
105
|
-
myokit.FORCE_PYSIDE = False
|
|
106
|
-
myokit.FORCE_PYSIDE2 = False
|
|
107
|
-
elif pyside:
|
|
108
|
-
myokit.FORCE_PYQT5 = False
|
|
109
|
-
myokit.FORCE_PYQT4 = False
|
|
110
|
-
myokit.FORCE_PYSIDE = True
|
|
111
|
-
myokit.FORCE_PYSIDE2 = False
|
|
112
|
-
elif pyside2:
|
|
113
|
-
myokit.FORCE_PYQT5 = False
|
|
114
|
-
myokit.FORCE_PYQT4 = False
|
|
115
|
-
myokit.FORCE_PYSIDE = False
|
|
116
|
-
myokit.FORCE_PYSIDE2 = True
|
|
117
|
-
import myokit.gui
|
|
141
|
+
qtforce(pyqt6, pyqt5, pyside6, pyside2)
|
|
142
|
+
|
|
118
143
|
import myokit.gui.datablock_viewer
|
|
119
|
-
if pyqt5 or pyqt4 or pyside or pyside2:
|
|
120
|
-
print('Using backend: ' + myokit.gui.backend)
|
|
121
144
|
myokit.gui.run(myokit.gui.datablock_viewer.DataBlockViewer, filename)
|
|
122
145
|
|
|
123
146
|
|
|
@@ -137,26 +160,7 @@ def add_block_parser(subparsers):
|
|
|
137
160
|
metavar='filename',
|
|
138
161
|
help='The DataBlock zip file to open (optional).',
|
|
139
162
|
)
|
|
140
|
-
parser
|
|
141
|
-
'--pyqt5',
|
|
142
|
-
action='store_true',
|
|
143
|
-
help='Run the DataBlock Viewer using the PyQt5 backend.',
|
|
144
|
-
)
|
|
145
|
-
parser.add_argument(
|
|
146
|
-
'--pyqt4',
|
|
147
|
-
action='store_true',
|
|
148
|
-
help='Run the DataBlock Viewer using the PyQt4 backend.',
|
|
149
|
-
)
|
|
150
|
-
parser.add_argument(
|
|
151
|
-
'--pyside',
|
|
152
|
-
action='store_true',
|
|
153
|
-
help='Run the DataBlock Viewer using the PySide backend.',
|
|
154
|
-
)
|
|
155
|
-
parser.add_argument(
|
|
156
|
-
'--pyside2',
|
|
157
|
-
action='store_true',
|
|
158
|
-
help='Run the DataBlock Viewer using the PySide2 backend.',
|
|
159
|
-
)
|
|
163
|
+
add_qtforce_arguments(parser)
|
|
160
164
|
parser.set_defaults(func=block)
|
|
161
165
|
|
|
162
166
|
|
|
@@ -240,7 +244,7 @@ def add_compiler_parser(subparsers):
|
|
|
240
244
|
|
|
241
245
|
def debug(source, variable, deps=False):
|
|
242
246
|
"""
|
|
243
|
-
Shows how a single variable is calculated from the initial
|
|
247
|
+
Shows how a single variable is calculated from the initial values.
|
|
244
248
|
"""
|
|
245
249
|
import myokit
|
|
246
250
|
|
|
@@ -261,8 +265,8 @@ def add_debug_parser(subparsers):
|
|
|
261
265
|
parser = subparsers.add_parser(
|
|
262
266
|
'debug',
|
|
263
267
|
description='Shows how a single variable is calculated from the '
|
|
264
|
-
'initial
|
|
265
|
-
'
|
|
268
|
+
' initial values. The variable\'s equation and value are'
|
|
269
|
+
' displayed, along with the value and formula of any'
|
|
266
270
|
' nested variables and the values of all dependencies.',
|
|
267
271
|
help='Shows how a single variable is calculated.',
|
|
268
272
|
)
|
|
@@ -421,10 +425,7 @@ def install():
|
|
|
421
425
|
if plat == 'Linux':
|
|
422
426
|
yesno = \
|
|
423
427
|
'Install launcher icons and file type associations for Gnome/KDE? '
|
|
424
|
-
|
|
425
|
-
yesno = raw_input(yesno)
|
|
426
|
-
except NameError: # pragma: no python 2 cover
|
|
427
|
-
yesno = input(yesno)
|
|
428
|
+
yesno = input(yesno)
|
|
428
429
|
yesno = (yesno.strip().lower())[:1] == 'y'
|
|
429
430
|
|
|
430
431
|
if yesno:
|
|
@@ -432,10 +433,7 @@ def install():
|
|
|
432
433
|
|
|
433
434
|
elif plat == 'Windows':
|
|
434
435
|
yesno = 'Install start menu shortcuts? '
|
|
435
|
-
|
|
436
|
-
yesno = raw_input(yesno)
|
|
437
|
-
except NameError: # pragma: no python 2 cover
|
|
438
|
-
yesno = input(yesno)
|
|
436
|
+
yesno = input(yesno)
|
|
439
437
|
yesno = (yesno.strip().lower())[:1] == 'y'
|
|
440
438
|
|
|
441
439
|
if yesno:
|
|
@@ -587,38 +585,17 @@ def add_icon_parser(subparsers):
|
|
|
587
585
|
# IDE
|
|
588
586
|
#
|
|
589
587
|
|
|
590
|
-
def ide(filename,
|
|
588
|
+
def ide(filename, pyqt6=False, pyqt5=False, pyside6=False, pyside2=False):
|
|
591
589
|
"""
|
|
592
590
|
Runs the Myokit IDE.
|
|
593
591
|
"""
|
|
592
|
+
qtforce(pyqt6, pyqt5, pyside6, pyside2)
|
|
593
|
+
|
|
594
594
|
import os
|
|
595
|
-
import myokit
|
|
596
|
-
if pyqt5:
|
|
597
|
-
myokit.FORCE_PYQT5 = True
|
|
598
|
-
myokit.FORCE_PYQT4 = False
|
|
599
|
-
myokit.FORCE_PYSIDE = False
|
|
600
|
-
myokit.FORCE_PYSIDE2 = False
|
|
601
|
-
elif pyqt4:
|
|
602
|
-
myokit.FORCE_PYQT5 = False
|
|
603
|
-
myokit.FORCE_PYQT4 = True
|
|
604
|
-
myokit.FORCE_PYSIDE = False
|
|
605
|
-
myokit.FORCE_PYSIDE2 = False
|
|
606
|
-
elif pyside:
|
|
607
|
-
myokit.FORCE_PYQT5 = False
|
|
608
|
-
myokit.FORCE_PYQT4 = False
|
|
609
|
-
myokit.FORCE_PYSIDE = True
|
|
610
|
-
myokit.FORCE_PYSIDE2 = False
|
|
611
|
-
elif pyside2:
|
|
612
|
-
myokit.FORCE_PYQT5 = False
|
|
613
|
-
myokit.FORCE_PYQT4 = False
|
|
614
|
-
myokit.FORCE_PYSIDE = False
|
|
615
|
-
myokit.FORCE_PYSIDE2 = True
|
|
616
|
-
import myokit.gui
|
|
617
|
-
import myokit.gui.ide
|
|
618
|
-
if pyqt5 or pyqt4 or pyside or pyside2:
|
|
619
|
-
print('Using backend: ' + myokit.gui.backend)
|
|
620
595
|
if filename is not None:
|
|
621
596
|
filename = os.path.abspath(os.path.expanduser(filename))
|
|
597
|
+
|
|
598
|
+
import myokit.gui.ide
|
|
622
599
|
myokit.gui.run(myokit.gui.ide.MyokitIDE, filename)
|
|
623
600
|
|
|
624
601
|
|
|
@@ -638,26 +615,7 @@ def add_ide_parser(subparsers):
|
|
|
638
615
|
metavar='filename',
|
|
639
616
|
help='The mmt file to open (optional).',
|
|
640
617
|
)
|
|
641
|
-
parser
|
|
642
|
-
'--pyqt5',
|
|
643
|
-
action='store_true',
|
|
644
|
-
help='Run the IDE using the PyQt5 backend.',
|
|
645
|
-
)
|
|
646
|
-
parser.add_argument(
|
|
647
|
-
'--pyqt4',
|
|
648
|
-
action='store_true',
|
|
649
|
-
help='Run the IDE using the PyQt4 backend.',
|
|
650
|
-
)
|
|
651
|
-
parser.add_argument(
|
|
652
|
-
'--pyside',
|
|
653
|
-
action='store_true',
|
|
654
|
-
help='Run the IDE using the PySide backend.',
|
|
655
|
-
)
|
|
656
|
-
parser.add_argument(
|
|
657
|
-
'--pyside2',
|
|
658
|
-
action='store_true',
|
|
659
|
-
help='Run the DataBlock Viewer using the PySide2 backend.',
|
|
660
|
-
)
|
|
618
|
+
add_qtforce_arguments(parser)
|
|
661
619
|
parser.set_defaults(func=ide)
|
|
662
620
|
|
|
663
621
|
|
|
@@ -741,11 +699,12 @@ def add_import_parser(subparsers):
|
|
|
741
699
|
# Log viewer
|
|
742
700
|
#
|
|
743
701
|
|
|
744
|
-
def log(filenames):
|
|
702
|
+
def log(filenames, pyqt6=False, pyqt5=False, pyside6=False, pyside2=False):
|
|
745
703
|
"""
|
|
746
704
|
Runs the DataLog Viewer.
|
|
747
705
|
"""
|
|
748
|
-
|
|
706
|
+
qtforce(pyqt6, pyqt5, pyside6, pyside2)
|
|
707
|
+
|
|
749
708
|
import myokit.gui.datalog_viewer
|
|
750
709
|
myokit.gui.run(myokit.gui.datalog_viewer.DataLogViewer, *filenames)
|
|
751
710
|
|
|
@@ -761,6 +720,7 @@ def add_log_parser(subparsers):
|
|
|
761
720
|
description='Runs the DataLog Viewer (PROTOTYPE).',
|
|
762
721
|
help='Runs the DataLog Viewer (PROTOTYPE).',
|
|
763
722
|
)
|
|
723
|
+
add_qtforce_arguments(parser)
|
|
764
724
|
parser.add_argument(
|
|
765
725
|
'filenames',
|
|
766
726
|
default=None,
|
|
@@ -867,10 +827,7 @@ def opencl_select():
|
|
|
867
827
|
try:
|
|
868
828
|
while True:
|
|
869
829
|
x = 'Select device: '
|
|
870
|
-
|
|
871
|
-
x = raw_input(x)
|
|
872
|
-
except NameError: # pragma: no python 2 cover
|
|
873
|
-
x = input(x) # lgtm [py/use-of-input]
|
|
830
|
+
x = input(x)
|
|
874
831
|
x = x.strip()
|
|
875
832
|
if x == '':
|
|
876
833
|
x = None
|
|
@@ -932,10 +889,7 @@ def reset(force=False):
|
|
|
932
889
|
remove = True
|
|
933
890
|
else:
|
|
934
891
|
yesno = 'Remove all Myokit settings files? '
|
|
935
|
-
|
|
936
|
-
yesno = raw_input(yesno)
|
|
937
|
-
except NameError: # pragma: no python 2 cover
|
|
938
|
-
yesno = input(yesno) # lgtm [py/use-of-input]
|
|
892
|
+
yesno = input(yesno)
|
|
939
893
|
yesno = yesno.strip().lower()
|
|
940
894
|
remove = (yesno[:1] == 'y')
|
|
941
895
|
if remove:
|
|
@@ -1290,11 +1244,6 @@ def add_test_parser(subparsers):
|
|
|
1290
1244
|
'examples', help='Test example notebooks.')
|
|
1291
1245
|
example_parser.set_defaults(testfunc=test_examples)
|
|
1292
1246
|
|
|
1293
|
-
# Publication examples
|
|
1294
|
-
pub_parser = subparsers.add_parser(
|
|
1295
|
-
'pub', help='Run publication examples.')
|
|
1296
|
-
pub_parser.set_defaults(testfunc=test_examples_pub)
|
|
1297
|
-
|
|
1298
1247
|
# Style tests
|
|
1299
1248
|
style_parser = subparsers.add_parser('style', help='Run code style tests.')
|
|
1300
1249
|
style_parser.set_defaults(testfunc=test_style)
|
|
@@ -1334,7 +1283,7 @@ def test_coverage(args):
|
|
|
1334
1283
|
try:
|
|
1335
1284
|
print('Gathering coverage data')
|
|
1336
1285
|
p = subprocess.Popen([
|
|
1337
|
-
|
|
1286
|
+
sys.executable,
|
|
1338
1287
|
'-m',
|
|
1339
1288
|
'coverage',
|
|
1340
1289
|
'run',
|
|
@@ -1358,7 +1307,7 @@ def test_coverage(args):
|
|
|
1358
1307
|
|
|
1359
1308
|
print('Generating coverage report.')
|
|
1360
1309
|
p = subprocess.Popen([
|
|
1361
|
-
|
|
1310
|
+
sys.executable,
|
|
1362
1311
|
'-m',
|
|
1363
1312
|
'coverage',
|
|
1364
1313
|
'report',
|
|
@@ -1789,8 +1738,7 @@ def test_examples_single(root, path):
|
|
|
1789
1738
|
p = subprocess.Popen(
|
|
1790
1739
|
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env
|
|
1791
1740
|
)
|
|
1792
|
-
stdout, stderr = p.communicate()
|
|
1793
|
-
# TODO: Use p.communicate(timeout=3600) if Python3 only
|
|
1741
|
+
stdout, stderr = p.communicate(timeout=3600)
|
|
1794
1742
|
if p.returncode != 0:
|
|
1795
1743
|
# Show failing code, output and errors before returning
|
|
1796
1744
|
print('ERROR')
|
|
@@ -1840,23 +1788,6 @@ def test_examples_all(root, books):
|
|
|
1840
1788
|
print('ok: Successfully ran all (' + str(len(books)) + ') notebooks.')
|
|
1841
1789
|
|
|
1842
1790
|
|
|
1843
|
-
def test_examples_pub(args):
|
|
1844
|
-
"""
|
|
1845
|
-
Runs all publication examples, exits if one of them fails.
|
|
1846
|
-
"""
|
|
1847
|
-
import os
|
|
1848
|
-
import sys
|
|
1849
|
-
import myokit
|
|
1850
|
-
|
|
1851
|
-
# Get publications directory
|
|
1852
|
-
path = os.path.join(myokit.DIR_MYOKIT, 'tests', 'publications')
|
|
1853
|
-
|
|
1854
|
-
# PBMB 2016. Myokit: A simple interface to cardiac cellular
|
|
1855
|
-
# electrophysiology
|
|
1856
|
-
if test_mmt_files(os.path.join(path, 'pbmb-2016')):
|
|
1857
|
-
sys.exit(1)
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
1791
|
def test_examples_web(args):
|
|
1861
1792
|
"""
|
|
1862
1793
|
Runs all web examples, exits if one of them fails.
|
|
@@ -2209,4 +2140,7 @@ def add_video_parser(subparsers):
|
|
|
2209
2140
|
|
|
2210
2141
|
|
|
2211
2142
|
if __name__ == '__main__':
|
|
2143
|
+
import logging
|
|
2144
|
+
logging.basicConfig()
|
|
2145
|
+
|
|
2212
2146
|
main()
|
myokit/_aux.py
CHANGED
|
@@ -6,9 +6,6 @@
|
|
|
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 myokit
|
|
13
10
|
|
|
14
11
|
import sys
|
|
@@ -29,7 +26,7 @@ class Benchmarker(myokit.tools.Benchmarker):
|
|
|
29
26
|
warnings.warn(
|
|
30
27
|
'The class `myokit.Benchmarker` is deprecated.'
|
|
31
28
|
' Please use `myokit.tools.Benchmarker` instead.')
|
|
32
|
-
super(
|
|
29
|
+
super().__init__()
|
|
33
30
|
|
|
34
31
|
|
|
35
32
|
def date():
|
|
@@ -150,7 +147,7 @@ def format_path(path, root='.'):
|
|
|
150
147
|
return myokit.tools.format_path(path, root)
|
|
151
148
|
|
|
152
149
|
|
|
153
|
-
class ModelComparison
|
|
150
|
+
class ModelComparison:
|
|
154
151
|
"""
|
|
155
152
|
Compares two models.
|
|
156
153
|
|
|
@@ -281,12 +278,12 @@ class ModelComparison(object):
|
|
|
281
278
|
|
|
282
279
|
def _state(self, m1, m2):
|
|
283
280
|
"""
|
|
284
|
-
Compares two models' states.
|
|
281
|
+
Compares two models' states and initial values.
|
|
285
282
|
"""
|
|
286
283
|
s1 = iter([v.qname() for v in m1.states()])
|
|
287
284
|
s2 = iter([v.qname() for v in m2.states()])
|
|
288
|
-
c1 = m1.
|
|
289
|
-
c2 = m2.
|
|
285
|
+
c1 = m1.initial_values()
|
|
286
|
+
c2 = m2.initial_values()
|
|
290
287
|
for k, v1 in enumerate(s1):
|
|
291
288
|
try:
|
|
292
289
|
v2 = next(s2)
|
|
@@ -298,7 +295,7 @@ class ModelComparison(object):
|
|
|
298
295
|
'[x] Mismatched State at position ' + str(k) + ': [1]<'
|
|
299
296
|
+ v1 + '> [2]<' + v2 + '>')
|
|
300
297
|
continue
|
|
301
|
-
if c1[k] != c2[k]:
|
|
298
|
+
if c1[k].code() != c2[k].code():
|
|
302
299
|
self._write('[x] Mismatched Initial value for <' + v1 + '>')
|
|
303
300
|
n = m2.count_states()
|
|
304
301
|
for k, v2 in enumerate(s2):
|
|
@@ -434,6 +431,50 @@ def python_writer():
|
|
|
434
431
|
return _pywriter_
|
|
435
432
|
|
|
436
433
|
|
|
434
|
+
def _prepare_bindings(model, labels):
|
|
435
|
+
"""
|
|
436
|
+
Takes a mapping of binding labels to internal references and returns a map
|
|
437
|
+
from variable instances to the same internal references.
|
|
438
|
+
|
|
439
|
+
This method also modifies ``model``: All bindings that are not mapped to
|
|
440
|
+
an internal reference will be removed.
|
|
441
|
+
|
|
442
|
+
The argument ``mapping`` should take the form::
|
|
443
|
+
|
|
444
|
+
labels = {
|
|
445
|
+
binding_label_1 : internal_name_1,
|
|
446
|
+
binding_label_2 : internal_name_2,
|
|
447
|
+
...
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
The returned dictionary will have the form::
|
|
451
|
+
|
|
452
|
+
variables = {
|
|
453
|
+
variable_x : internal_name_1,
|
|
454
|
+
variable_y : internal_name_2,
|
|
455
|
+
...
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
Unsupported bindings (i.e. bindings not appearing in ``labels``) will
|
|
459
|
+
be ignored.
|
|
460
|
+
"""
|
|
461
|
+
unused = []
|
|
462
|
+
variables = {}
|
|
463
|
+
for label, var in model.bindings():
|
|
464
|
+
try:
|
|
465
|
+
variables[var] = labels[label]
|
|
466
|
+
except KeyError:
|
|
467
|
+
unused.append(var)
|
|
468
|
+
continue
|
|
469
|
+
# TODO: Remove this line; https://github.com/myokit/myokit/issues/320
|
|
470
|
+
var.set_rhs(0)
|
|
471
|
+
|
|
472
|
+
for var in unused:
|
|
473
|
+
var.set_binding(None)
|
|
474
|
+
|
|
475
|
+
return variables
|
|
476
|
+
|
|
477
|
+
|
|
437
478
|
def run(model, protocol, script, stdout=None, stderr=None, progress=None):
|
|
438
479
|
"""
|
|
439
480
|
Runs a python ``script`` using the given ``model`` and ``protocol``.
|
|
@@ -476,9 +517,9 @@ def run(model, protocol, script, stdout=None, stderr=None, progress=None):
|
|
|
476
517
|
script = '\n' + script
|
|
477
518
|
|
|
478
519
|
# Class to run scripts
|
|
479
|
-
class Runner
|
|
520
|
+
class Runner:
|
|
480
521
|
def __init__(self, model, protocol, script, stdout, stderr, progress):
|
|
481
|
-
super(
|
|
522
|
+
super().__init__()
|
|
482
523
|
self.model = model
|
|
483
524
|
self.protocol = protocol
|
|
484
525
|
self.script = script
|
|
@@ -511,7 +552,7 @@ def run(model, protocol, script, stdout=None, stderr=None, progress=None):
|
|
|
511
552
|
'get_model': get_model,
|
|
512
553
|
'get_protocol': get_protocol,
|
|
513
554
|
}
|
|
514
|
-
|
|
555
|
+
exec(self.script, environment)
|
|
515
556
|
finally:
|
|
516
557
|
if oldstdout is not None:
|
|
517
558
|
sys.stdout = oldstdout
|
|
@@ -549,7 +590,7 @@ def step(model, initial=None, reference=None, ignore_errors=False):
|
|
|
549
590
|
"""
|
|
550
591
|
# Get initial state
|
|
551
592
|
if initial is None:
|
|
552
|
-
initial = model.
|
|
593
|
+
initial = model.initial_values(as_floats=True)
|
|
553
594
|
|
|
554
595
|
# Get evaluation at initial state
|
|
555
596
|
values = model.evaluate_derivatives(
|
|
@@ -620,8 +661,13 @@ def step(model, initial=None, reference=None, ignore_errors=False):
|
|
|
620
661
|
# Large error, small error, or no error
|
|
621
662
|
else:
|
|
622
663
|
mark_error = False
|
|
623
|
-
|
|
624
|
-
if
|
|
664
|
+
abs_err = abs(x - y)
|
|
665
|
+
if abs_err:
|
|
666
|
+
rel_err = abs(x - y) / max(abs(x), abs(y))
|
|
667
|
+
n_eps = rel_err / sys.float_info.epsilon
|
|
668
|
+
else:
|
|
669
|
+
n_eps = rel_err = 0
|
|
670
|
+
if n_eps > 1e6:
|
|
625
671
|
# "Large" error
|
|
626
672
|
errors += 1
|
|
627
673
|
line += ' X'
|
|
@@ -664,7 +710,7 @@ def step(model, initial=None, reference=None, ignore_errors=False):
|
|
|
664
710
|
if warnings > 0:
|
|
665
711
|
log.append('Found (' + str(warnings) + ') small mismatches.')
|
|
666
712
|
|
|
667
|
-
#
|
|
713
|
+
# Finalize and return
|
|
668
714
|
log.append('-' * line_width)
|
|
669
715
|
return '\n'.join(log)
|
|
670
716
|
|
myokit/_bin/example.mmt
CHANGED
|
@@ -3,7 +3,6 @@ name: Luo-Rudy 1991
|
|
|
3
3
|
desc: """
|
|
4
4
|
Implementation of the Luo-Rudy model I for the ventricular myocyte.
|
|
5
5
|
Based on an updated formulation downloaded from http://rudylab.wustl.edu
|
|
6
|
-
and licensed under a GNU GPL license version 2.
|
|
7
6
|
"""
|
|
8
7
|
# Initial conditions
|
|
9
8
|
membrane.V = -84.5286
|
|
@@ -19,7 +18,7 @@ ica.Ca_i = 0.0002
|
|
|
19
18
|
desc: """
|
|
20
19
|
Membrane potential and stimulus
|
|
21
20
|
"""
|
|
22
|
-
C = 1
|
|
21
|
+
C = 1 [uF/cm^2]
|
|
23
22
|
in [uF/cm^2]
|
|
24
23
|
dot(V) = - (1/C) * (i_ion + i_diff + i_stim) in [mV]
|
|
25
24
|
label membrane_potential
|
|
@@ -9,13 +9,6 @@ icons = icons.replace('\\', '/')
|
|
|
9
9
|
"menu_name": "Myokit",
|
|
10
10
|
"menu_items":
|
|
11
11
|
[
|
|
12
|
-
{
|
|
13
|
-
"name": "Myokit IDE",
|
|
14
|
-
"script": "${PYTHON_SCRIPTS}/myokit.exe",
|
|
15
|
-
"scriptarguments": ["ide"],
|
|
16
|
-
"workdir": "${PREFIX}",
|
|
17
|
-
"icon": "<?=icons?>/icon-ide.ico"
|
|
18
|
-
},
|
|
19
12
|
{
|
|
20
13
|
"name": "DataLog viewer",
|
|
21
14
|
"script": "${PYTHON_SCRIPTS}/myokit.exe",
|
|
@@ -29,6 +22,13 @@ icons = icons.replace('\\', '/')
|
|
|
29
22
|
"scriptarguments": ["block"],
|
|
30
23
|
"workdir": "${PREFIX}",
|
|
31
24
|
"icon": "<?=icons?>/icon-datablock-viewer.ico"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "Myokit IDE",
|
|
28
|
+
"script": "${PYTHON_SCRIPTS}/myokit.exe",
|
|
29
|
+
"scriptarguments": ["ide"],
|
|
30
|
+
"workdir": "${PREFIX}",
|
|
31
|
+
"icon": "<?=icons?>/icon-ide.ico"
|
|
32
32
|
}
|
|
33
33
|
]
|
|
34
34
|
}
|