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/formats/stan/__init__.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
|
from ._exporter import StanExporter
|
|
11
8
|
from ._ewriter import StanExpressionWriter
|
|
12
9
|
|
myokit/formats/stan/_ewriter.py
CHANGED
|
@@ -6,10 +6,8 @@
|
|
|
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
|
|
10
|
+
|
|
13
11
|
from myokit.formats.python import PythonExpressionWriter
|
|
14
12
|
|
|
15
13
|
|
|
@@ -19,7 +17,7 @@ class StanExpressionWriter(PythonExpressionWriter):
|
|
|
19
17
|
Myokit:class:`expressions <myokit.Expression>` to a Stan syntax.
|
|
20
18
|
"""
|
|
21
19
|
def __init__(self):
|
|
22
|
-
super(
|
|
20
|
+
super().__init__()
|
|
23
21
|
self._function_prefix = ''
|
|
24
22
|
|
|
25
23
|
self._fcond = None
|
myokit/formats/stan/_exporter.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 os
|
|
11
8
|
|
|
12
9
|
import myokit.formats
|
|
@@ -61,7 +58,7 @@ class StanExporter(myokit.formats.TemplatedRunnableExporter):
|
|
|
61
58
|
ion current).
|
|
62
59
|
|
|
63
60
|
"""
|
|
64
|
-
super(
|
|
61
|
+
super().runnable(
|
|
65
62
|
path, model, protocol, parameters, output)
|
|
66
63
|
|
|
67
64
|
def _vars(self, model, protocol, parameters, output):
|
myokit/formats/sympy/__init__.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
|
from ._ereader import SymPyExpressionReader
|
|
11
8
|
from ._ewriter import SymPyExpressionWriter
|
|
12
9
|
|
myokit/formats/sympy/_ereader.py
CHANGED
|
@@ -4,14 +4,11 @@
|
|
|
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 myokit
|
|
11
8
|
import myokit.formats
|
|
12
9
|
|
|
13
10
|
|
|
14
|
-
class SymPyExpressionReader
|
|
11
|
+
class SymPyExpressionReader:
|
|
15
12
|
"""
|
|
16
13
|
Converts Sympy expressions to Myokit expressions.
|
|
17
14
|
|
myokit/formats/sympy/_ewriter.py
CHANGED
|
@@ -4,16 +4,13 @@
|
|
|
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
|
|
7
|
+
import myokit.formats
|
|
9
8
|
|
|
10
9
|
try:
|
|
11
10
|
import sympy as sp
|
|
12
11
|
except ImportError:
|
|
13
12
|
pass
|
|
14
13
|
|
|
15
|
-
import myokit.formats
|
|
16
|
-
|
|
17
14
|
|
|
18
15
|
class SymPyExpressionWriter(myokit.formats.ExpressionWriter):
|
|
19
16
|
"""
|
|
@@ -23,7 +20,7 @@ class SymPyExpressionWriter(myokit.formats.ExpressionWriter):
|
|
|
23
20
|
The returned type is a SymPy object, not a string!
|
|
24
21
|
"""
|
|
25
22
|
def __init__(self):
|
|
26
|
-
super(
|
|
23
|
+
super().__init__()
|
|
27
24
|
|
|
28
25
|
self._flhs = None
|
|
29
26
|
self.set_lhs_function(lambda lhs: str(lhs))
|
myokit/formats/wcp/__init__.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
|
from ._wcp import WcpFile # noqa
|
|
11
8
|
# Importers
|
|
12
9
|
# Exporters
|
myokit/formats/wcp/_wcp.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 os
|
|
11
8
|
import struct
|
|
12
9
|
import numpy as np
|
|
@@ -17,7 +14,7 @@ import myokit
|
|
|
17
14
|
_ENC = 'ascii'
|
|
18
15
|
|
|
19
16
|
|
|
20
|
-
class WcpFile
|
|
17
|
+
class WcpFile:
|
|
21
18
|
"""
|
|
22
19
|
Represents a read-only WinWCP file (``.wcp``), stored at the location
|
|
23
20
|
pointed to by ``filepath``.
|
|
@@ -35,7 +32,6 @@ class WcpFile(object):
|
|
|
35
32
|
"""
|
|
36
33
|
def __init__(self, filepath):
|
|
37
34
|
# The path to the file and its basename
|
|
38
|
-
# Ensure it's a `str` for Python2/3 compatibility
|
|
39
35
|
filepath = str(filepath)
|
|
40
36
|
self._filepath = os.path.abspath(filepath)
|
|
41
37
|
self._filename = os.path.basename(filepath)
|
|
@@ -160,8 +156,6 @@ class WcpFile(object):
|
|
|
160
156
|
rtype = f.read(4)
|
|
161
157
|
|
|
162
158
|
# Group number (float set by the user)
|
|
163
|
-
# Note: First argument to struct.unpack must be a str (so bytes on
|
|
164
|
-
# Python 2).
|
|
165
159
|
group_number = struct.unpack(str('<f'), f.read(4))[0]
|
|
166
160
|
|
|
167
161
|
# Time of recording, as float, not sure how to interpret
|
myokit/formats/xml/__init__.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
|
from ._exporter import XMLExporter
|
|
11
8
|
from ._split import split # noqa
|
|
12
9
|
|
myokit/formats/xml/_exporter.py
CHANGED
myokit/formats/xml/_split.py
CHANGED
myokit/gui/__init__.py
CHANGED
|
@@ -4,303 +4,130 @@
|
|
|
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
|
-
# Library imports
|
|
11
|
-
import logging
|
|
12
7
|
import os
|
|
13
8
|
import platform
|
|
14
9
|
import signal
|
|
15
10
|
import sys
|
|
16
11
|
|
|
17
|
-
# Myokit imports
|
|
18
12
|
import myokit
|
|
19
13
|
|
|
20
14
|
# Detect platform
|
|
21
15
|
platform = platform.system()
|
|
22
16
|
|
|
23
17
|
# Select Qt library to use
|
|
24
|
-
pyqt4 = False
|
|
25
18
|
pyqt5 = False
|
|
26
|
-
|
|
19
|
+
pyqt6 = False
|
|
27
20
|
pyside2 = False
|
|
21
|
+
pyside6 = False
|
|
28
22
|
|
|
29
23
|
# Allow overriding automatic selection
|
|
24
|
+
if myokit.FORCE_PYQT6:
|
|
25
|
+
pyqt6 = True
|
|
30
26
|
if myokit.FORCE_PYQT5:
|
|
31
27
|
pyqt5 = True
|
|
32
|
-
elif myokit.
|
|
33
|
-
|
|
34
|
-
elif myokit.FORCE_PYSIDE:
|
|
35
|
-
pyside = True
|
|
28
|
+
elif myokit.FORCE_PYSIDE6:
|
|
29
|
+
pyside6 = True
|
|
36
30
|
elif myokit.FORCE_PYSIDE2:
|
|
37
31
|
pyside2 = True
|
|
38
32
|
else:
|
|
39
33
|
# Automatic selection
|
|
40
34
|
try:
|
|
41
|
-
import
|
|
42
|
-
|
|
35
|
+
import PyQt6 # noqa
|
|
36
|
+
pyqt6 = True
|
|
43
37
|
except ImportError:
|
|
44
38
|
try:
|
|
45
|
-
import
|
|
46
|
-
|
|
39
|
+
import PySide6 # noqa
|
|
40
|
+
pyside6 = True
|
|
47
41
|
except ImportError:
|
|
48
42
|
try:
|
|
49
|
-
import
|
|
50
|
-
|
|
43
|
+
import PyQt5 # noqa
|
|
44
|
+
pyqt5 = True
|
|
51
45
|
except ImportError:
|
|
52
46
|
try:
|
|
53
|
-
import
|
|
54
|
-
|
|
47
|
+
import PySide2 # noqa
|
|
48
|
+
pyside2 = True
|
|
55
49
|
except ImportError:
|
|
56
50
|
raise ImportError(
|
|
57
|
-
'Unable to find PyQt5,
|
|
51
|
+
'Unable to find PyQt6, PyQt5, PySide6, or PySide2.')
|
|
52
|
+
|
|
58
53
|
|
|
59
54
|
# Import and configure Qt
|
|
60
|
-
if
|
|
55
|
+
if pyqt6:
|
|
56
|
+
from PyQt6 import QtGui, QtWidgets, QtCore
|
|
57
|
+
from PyQt6.QtCore import Qt
|
|
58
|
+
|
|
59
|
+
# Use PySide signal names
|
|
60
|
+
QtCore.Signal = QtCore.pyqtSignal
|
|
61
|
+
QtCore.Slot = QtCore.pyqtSlot
|
|
62
|
+
QtCore.Property = QtCore.pyqtProperty
|
|
63
|
+
|
|
64
|
+
# Set backend variables
|
|
65
|
+
backend = 'PyQt6'
|
|
66
|
+
qtversion = 6
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
elif pyqt5:
|
|
63
69
|
from PyQt5 import QtGui, QtWidgets, QtCore
|
|
64
70
|
from PyQt5.QtCore import Qt
|
|
65
71
|
|
|
66
|
-
#
|
|
72
|
+
# Mimic PyQt6 API changes
|
|
73
|
+
# https://doc.qt.io/qt-6/widgets-changes-qt6.html
|
|
74
|
+
QtGui.QAction = QtWidgets.QAction
|
|
75
|
+
QtWidgets.QApplication.exec = QtWidgets.QApplication.exec_
|
|
76
|
+
|
|
77
|
+
# Use PySide signal names
|
|
67
78
|
QtCore.Signal = QtCore.pyqtSignal
|
|
68
79
|
QtCore.Slot = QtCore.pyqtSlot
|
|
69
80
|
QtCore.Property = QtCore.pyqtProperty
|
|
70
81
|
|
|
71
|
-
# Configure Matplotlib for use with PyQt5
|
|
72
|
-
import matplotlib
|
|
73
|
-
try:
|
|
74
|
-
matplotlib.use('Qt5Agg')
|
|
75
|
-
except ImportError:
|
|
76
|
-
# In matplotlib 3.7.0 this raises ImportErrors if a previous backend
|
|
77
|
-
# was already set.
|
|
78
|
-
pass
|
|
79
|
-
else: # pragma: no cover
|
|
80
|
-
# The method below was deprecated by matplotlib version 2.2, released
|
|
81
|
-
# in 2018. So probably fine to remove this (and similar) after 2023
|
|
82
|
-
v = [int(x) for x in matplotlib.__version__.split('.')]
|
|
83
|
-
if v[0] < 3 and v[1] < 3:
|
|
84
|
-
matplotlib.rcParams['backend.qt5'] = 'PyQt5'
|
|
85
|
-
import matplotlib.backends.backend_qt5agg as matplotlib_backend
|
|
86
|
-
|
|
87
82
|
# Set backend variables
|
|
88
83
|
backend = 'PyQt5'
|
|
89
84
|
qtversion = 5
|
|
90
85
|
|
|
91
|
-
elif
|
|
86
|
+
elif pyside6:
|
|
87
|
+
from PySide6 import QtGui, QtWidgets, QtCore
|
|
88
|
+
from PySide6.QtCore import Qt
|
|
92
89
|
|
|
93
|
-
#
|
|
94
|
-
|
|
90
|
+
# Mimic PyQt6 API changes
|
|
91
|
+
QtWidgets.QApplication.exec = QtWidgets.QApplication.exec_
|
|
92
|
+
|
|
93
|
+
# Set backend variables
|
|
94
|
+
backend = 'PySide6'
|
|
95
|
+
qtversion = 6
|
|
96
|
+
|
|
97
|
+
elif pyside2:
|
|
95
98
|
from PySide2 import QtGui, QtWidgets, QtCore
|
|
96
99
|
from PySide2.QtCore import Qt
|
|
97
100
|
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
matplotlib.use('Qt5Agg')
|
|
102
|
-
except ImportError:
|
|
103
|
-
# In matplotlib 3.3.0 this raises ImportErrors if a previous backend
|
|
104
|
-
# was already set.
|
|
105
|
-
pass
|
|
106
|
-
else: # pragma: no cover
|
|
107
|
-
v = [int(x) for x in matplotlib.__version__.split('.')]
|
|
108
|
-
if v[0] < 3 and v[1] < 3:
|
|
109
|
-
matplotlib.rcParams['backend.qt5'] = 'PySide2'
|
|
110
|
-
import matplotlib.backends.backend_qt5agg as matplotlib_backend # noqa
|
|
101
|
+
# Mimic PyQt6 API changes
|
|
102
|
+
QtGui.QAction = QtWidgets.QAction
|
|
103
|
+
QtWidgets.QApplication.exec = QtWidgets.QApplication.exec_
|
|
111
104
|
|
|
112
105
|
# Set backend variables
|
|
113
106
|
backend = 'PySide2'
|
|
114
107
|
qtversion = 5
|
|
115
108
|
|
|
116
|
-
elif pyqt4:
|
|
117
|
-
|
|
118
|
-
# Load PyQt4
|
|
119
|
-
|
|
120
|
-
# Deprecated since 2019-09-11
|
|
121
|
-
logger = logging.getLogger('myokit')
|
|
122
|
-
logger.warning(
|
|
123
|
-
'PyQt4 support has been deprecated. Please upgrade to PyQt5 or'
|
|
124
|
-
' Pyside2.'
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
# Set PyQt to "API 2"
|
|
128
|
-
import sip
|
|
129
|
-
sip.setapi('QString', 2)
|
|
130
|
-
sip.setapi('QVariant', 2)
|
|
131
|
-
sip.setapi('QDate', 2)
|
|
132
|
-
sip.setapi('QDateTime', 2)
|
|
133
|
-
sip.setapi('QTextStream', 2)
|
|
134
|
-
sip.setapi('QTime', 2)
|
|
135
|
-
sip.setapi('QUrl', 2)
|
|
136
|
-
|
|
137
|
-
# Load main classes
|
|
138
|
-
from PyQt4 import QtGui, QtCore
|
|
139
|
-
from PyQt4.QtCore import Qt
|
|
140
|
-
|
|
141
|
-
# Qt5 compatibility
|
|
142
|
-
QtWidgets = QtGui
|
|
143
|
-
QtCore.QItemSelection = QtGui.QItemSelection
|
|
144
|
-
QtCore.QItemSelectionModel = QtGui.QItemSelectionModel
|
|
145
|
-
QtCore.QItemSelectionRange = QtGui.QItemSelectionRange
|
|
146
|
-
QtCore.QSortFilterProxyModel = QtGui.QSortFilterProxyModel
|
|
147
|
-
QtWidgets.QStyleOptionViewItem = QtWidgets.QStyleOptionViewItemV4
|
|
148
|
-
|
|
149
|
-
# Fix Qt4 location issue
|
|
150
|
-
import PyQt4.Qt
|
|
151
|
-
QtGui.QKeySequence = PyQt4.Qt.QKeySequence
|
|
152
|
-
QtGui.QTextCursor = PyQt4.Qt.QTextCursor
|
|
153
|
-
del PyQt4.Qt
|
|
154
|
-
|
|
155
|
-
# Fix PyQt4 naming issues
|
|
156
|
-
QtCore.Signal = QtCore.pyqtSignal
|
|
157
|
-
QtCore.Slot = QtCore.pyqtSlot
|
|
158
|
-
QtCore.Property = QtCore.pyqtProperty
|
|
159
|
-
|
|
160
|
-
# Fix QFileDialog.getOpenFileName return type issues:
|
|
161
|
-
# Return type in PyQt4 is not a tuple (call ...AndFilter methods instead)
|
|
162
|
-
# Fix getOpenFileName
|
|
163
|
-
def gofn(parent=None, caption='', directory='', filter='',
|
|
164
|
-
initialFilter='', options=0):
|
|
165
|
-
if options == 0:
|
|
166
|
-
options = QtWidgets.QFileDialog.Options()
|
|
167
|
-
return QtWidgets.QFileDialog.getOpenFileNameAndFilter(
|
|
168
|
-
parent, caption, directory, filter, initialFilter, options)
|
|
169
|
-
QtWidgets.QFileDialog.getOpenFileName = staticmethod(gofn)
|
|
170
|
-
del gofn
|
|
171
|
-
|
|
172
|
-
# Fix getOpenFileNames
|
|
173
|
-
def gofns(parent=None, caption='', directory='', filter='',
|
|
174
|
-
initialFilter='', options=0):
|
|
175
|
-
if options == 0:
|
|
176
|
-
options = QtWidgets.QFileDialog.Options()
|
|
177
|
-
return QtWidgets.QFileDialog.getOpenFileNamesAndFilter(
|
|
178
|
-
parent, caption, directory, filter, initialFilter, options)
|
|
179
|
-
QtWidgets.QFileDialog.getOpenFileNames = staticmethod(gofns)
|
|
180
|
-
del gofns
|
|
181
|
-
|
|
182
|
-
# Fix getSaveFileName
|
|
183
|
-
def gsfn(parent=None, caption='', directory='', filter='',
|
|
184
|
-
initialFilter='', options=0):
|
|
185
|
-
if options == 0:
|
|
186
|
-
options = QtWidgets.QFileDialog.Options()
|
|
187
|
-
return QtWidgets.QFileDialog.getSaveFileNameAndFilter(
|
|
188
|
-
parent, caption, directory, filter, initialFilter, options)
|
|
189
|
-
QtWidgets.QFileDialog.getSaveFileName = staticmethod(gsfn)
|
|
190
|
-
del gsfn
|
|
191
|
-
|
|
192
|
-
# Configure Matplotlib for use with PyQt4
|
|
193
|
-
import matplotlib
|
|
194
|
-
try:
|
|
195
|
-
matplotlib.use('Qt4Agg')
|
|
196
|
-
except ImportError:
|
|
197
|
-
# In matplotlib 3.3.0 this raises ImportErrors if a previous backend
|
|
198
|
-
# was already set.
|
|
199
|
-
pass
|
|
200
|
-
else: # pragma: no cover
|
|
201
|
-
v = [int(x) for x in matplotlib.__version__.split('.')]
|
|
202
|
-
if v[0] < 3 and v[1] < 3:
|
|
203
|
-
matplotlib.rcParams['backend.qt4'] = 'PyQt4'
|
|
204
|
-
import matplotlib.backends.backend_qt4agg as matplotlib_backend
|
|
205
|
-
|
|
206
|
-
# Set backend variables
|
|
207
|
-
backend = 'PyQt4'
|
|
208
|
-
qtversion = 4
|
|
209
|
-
|
|
210
|
-
elif pyside:
|
|
211
|
-
|
|
212
|
-
# Load PySide
|
|
213
|
-
|
|
214
|
-
# Deprecated since 2019-09-11
|
|
215
|
-
logger = logging.getLogger('myokit')
|
|
216
|
-
logger.warning(
|
|
217
|
-
'PySide support has been deprecated. Please upgrade to PyQt5 or'
|
|
218
|
-
' Pyside2.'
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
# Load main classes
|
|
222
|
-
from PySide import QtGui, QtCore
|
|
223
|
-
from PySide.QtCore import Qt
|
|
224
|
-
|
|
225
|
-
# Qt5 compatibility
|
|
226
|
-
QtWidgets = QtGui
|
|
227
|
-
QtCore.QItemSelection = QtGui.QItemSelection
|
|
228
|
-
QtCore.QItemSelectionModel = QtGui.QItemSelectionModel
|
|
229
|
-
QtCore.QItemSelectionRange = QtGui.QItemSelectionRange
|
|
230
|
-
QtCore.QSortFilterProxyModel = QtGui.QSortFilterProxyModel
|
|
231
|
-
QtWidgets.QStyleOptionViewItem = QtWidgets.QStyleOptionViewItemV4
|
|
232
|
-
|
|
233
|
-
# Fix QFileDialog.getOpenFileName signature issues (is different in PySide,
|
|
234
|
-
# which causes issues when using keyword arguments. This is fixed simply
|
|
235
|
-
# by simply wrapping the methods.)
|
|
236
|
-
# Signature in PySide
|
|
237
|
-
# parent
|
|
238
|
-
# caption
|
|
239
|
-
# dir --> directory PyQt4/5
|
|
240
|
-
# filter
|
|
241
|
-
# selectedFilter --> initialFilter in PyQt4/5
|
|
242
|
-
# options
|
|
243
|
-
|
|
244
|
-
# Fix getOpenFileName
|
|
245
|
-
gofn_org = QtWidgets.QFileDialog.getOpenFileName
|
|
246
|
-
|
|
247
|
-
def gofn(parent=None, caption='', directory='', filter='',
|
|
248
|
-
initialFilter='', options=0):
|
|
249
|
-
if options == 0:
|
|
250
|
-
options = QtWidgets.QFileDialog.Options()
|
|
251
|
-
return gofn_org(
|
|
252
|
-
parent, caption, directory, filter, initialFilter, options)
|
|
253
|
-
QtWidgets.QFileDialog.getOpenFileName = staticmethod(gofn)
|
|
254
|
-
del gofn
|
|
255
|
-
|
|
256
|
-
# Fix getOpenFileNames
|
|
257
|
-
gofns_org = QtWidgets.QFileDialog.getOpenFileNames
|
|
258
|
-
|
|
259
|
-
def gofns(parent=None, caption='', directory='', filter='',
|
|
260
|
-
initialFilter='', options=0):
|
|
261
|
-
if options == 0:
|
|
262
|
-
options = QtWidgets.QFileDialog.Options()
|
|
263
|
-
return gofns_org(
|
|
264
|
-
parent, caption, directory, filter, initialFilter, options)
|
|
265
|
-
QtWidgets.QFileDialog.getOpenFileNames = staticmethod(gofns)
|
|
266
|
-
del gofns
|
|
267
|
-
|
|
268
|
-
# Fix getSaveFileName
|
|
269
|
-
gsfn_org = QtWidgets.QFileDialog.getSaveFileName
|
|
270
|
-
|
|
271
|
-
def gsfn(parent=None, caption='', directory='', filter='',
|
|
272
|
-
initialFilter='', options=0):
|
|
273
|
-
if options == 0:
|
|
274
|
-
options = QtWidgets.QFileDialog.Options()
|
|
275
|
-
return gsfn_org(
|
|
276
|
-
parent, caption, directory, filter, initialFilter, options)
|
|
277
|
-
QtWidgets.QFileDialog.getSaveFileName = staticmethod(gsfn)
|
|
278
|
-
del gsfn
|
|
279
|
-
|
|
280
|
-
# Configure Matplotlib for use with PySide
|
|
281
|
-
import matplotlib
|
|
282
|
-
try:
|
|
283
|
-
matplotlib.use('Qt4Agg')
|
|
284
|
-
except ImportError:
|
|
285
|
-
# In matplotlib 3.3.0 this raises ImportErrors if a previous backend
|
|
286
|
-
# was already set.
|
|
287
|
-
pass
|
|
288
|
-
else: # pragma: no cover
|
|
289
|
-
v = [int(x) for x in matplotlib.__version__.split('.')]
|
|
290
|
-
if v[0] < 3 and v[1] < 3:
|
|
291
|
-
matplotlib.rcParams['backend.qt4'] = 'PySide'
|
|
292
|
-
import matplotlib.backends.backend_qt4agg as matplotlib_backend # noqa
|
|
293
|
-
|
|
294
|
-
# Set backend variables
|
|
295
|
-
backend = 'PySide'
|
|
296
|
-
qtversion = 4
|
|
297
|
-
|
|
298
109
|
else:
|
|
299
|
-
|
|
300
110
|
raise Exception('Selection of qt version failed.')
|
|
301
111
|
|
|
112
|
+
|
|
113
|
+
# Configure Matplotlib for use with Qt
|
|
114
|
+
import matplotlib # noqa
|
|
115
|
+
try:
|
|
116
|
+
matplotlib.use('QtAgg')
|
|
117
|
+
except ImportError:
|
|
118
|
+
# In matplotlib 3.7.0 this raises ImportErrors if a previous backend
|
|
119
|
+
# was already set.
|
|
120
|
+
pass
|
|
121
|
+
try:
|
|
122
|
+
# New Matplotlib no longer has qt4agg/qt5agg, but now uses qtagg for all
|
|
123
|
+
import matplotlib.backends.back_qtagg as matplotlib_backend # noqa
|
|
124
|
+
except ImportError:
|
|
125
|
+
# https://matplotlib.org/stable/api/backend_qt_api.html
|
|
126
|
+
import matplotlib.backends.backend_qt5agg as matplotlib_backend # noqa
|
|
127
|
+
|
|
302
128
|
# Delete temporary variables
|
|
303
|
-
del
|
|
129
|
+
del pyqt5, pyqt6, pyside2, pyside6
|
|
130
|
+
|
|
304
131
|
|
|
305
132
|
# Load Gnome theme on Wayland (for icons)
|
|
306
133
|
if platform == 'Linux':
|
|
@@ -323,11 +150,11 @@ for k, v in ICONS.items():
|
|
|
323
150
|
ICONS[k] = os.path.join(ICON_PATH, v)
|
|
324
151
|
|
|
325
152
|
# Toolbar style suitable for platform
|
|
326
|
-
TOOL_BUTTON_STYLE = Qt.ToolButtonTextUnderIcon
|
|
153
|
+
TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonTextUnderIcon
|
|
327
154
|
if platform == 'Windows': # pragma: no linux cover
|
|
328
|
-
TOOL_BUTTON_STYLE = Qt.ToolButtonIconOnly
|
|
155
|
+
TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonIconOnly
|
|
329
156
|
elif platform == 'Darwin': # pragma: no linux cover
|
|
330
|
-
TOOL_BUTTON_STYLE = Qt.ToolButtonTextOnly
|
|
157
|
+
TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonTextOnly
|
|
331
158
|
|
|
332
159
|
|
|
333
160
|
# Stand alone applications
|
|
@@ -355,10 +182,11 @@ def qtMonospaceFont():
|
|
|
355
182
|
"""
|
|
356
183
|
font = QtGui.QFont('monospace')
|
|
357
184
|
if platform == 'Windows': # pragma: no linux cover
|
|
358
|
-
font.setStyleHint(QtGui.QFont.TypeWriter)
|
|
185
|
+
font.setStyleHint(QtGui.QFont.StyleHint.TypeWriter)
|
|
359
186
|
else:
|
|
360
|
-
font.setStyleHint(QtGui.QFont.Monospace)
|
|
361
|
-
font.setHintingPreference(
|
|
187
|
+
font.setStyleHint(QtGui.QFont.StyleHint.Monospace)
|
|
188
|
+
font.setHintingPreference(
|
|
189
|
+
QtGui.QFont.HintingPreference.PreferVerticalHinting)
|
|
362
190
|
return font
|
|
363
191
|
|
|
364
192
|
|
|
@@ -408,5 +236,5 @@ def run(app, *args):
|
|
|
408
236
|
timer.timeout.connect(lambda: None)
|
|
409
237
|
|
|
410
238
|
# Wait for app to exit
|
|
411
|
-
sys.exit(a.
|
|
239
|
+
sys.exit(a.exec())
|
|
412
240
|
|