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/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
|
|
@@ -231,7 +225,7 @@ class WcpFile(object):
|
|
|
231
225
|
Creates and returns a:class:`myokit.DataLog` containing all the
|
|
232
226
|
data from this file.
|
|
233
227
|
|
|
234
|
-
Each channel is stored under its own name, with an
|
|
228
|
+
Each channel is stored under its own name, with an index indicating
|
|
235
229
|
the record it was from. Time is stored under ``time``.
|
|
236
230
|
"""
|
|
237
231
|
log = myokit.DataLog()
|
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,136 @@
|
|
|
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
|
-
|
|
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
|
|
109
|
+
else:
|
|
110
|
+
raise Exception('Selection of qt version failed.')
|
|
205
111
|
|
|
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
112
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
|
297
127
|
|
|
298
|
-
|
|
128
|
+
# Delete temporary variables
|
|
129
|
+
del pyqt5, pyqt6, pyside2, pyside6
|
|
299
130
|
|
|
300
|
-
raise Exception('Selection of qt version failed.')
|
|
301
131
|
|
|
302
|
-
#
|
|
303
|
-
|
|
132
|
+
# Load Gnome theme on Wayland (for icons)
|
|
133
|
+
if platform == 'Linux':
|
|
134
|
+
icon = QtGui.QIcon.fromTheme('document-new')
|
|
135
|
+
if icon.isNull():
|
|
136
|
+
QtGui.QIcon.setThemeName('gnome')
|
|
304
137
|
|
|
305
138
|
# Icons with fallback for apple and windows
|
|
306
139
|
ICON_PATH = os.path.join(myokit.DIR_DATA, 'gui')
|
|
@@ -317,11 +150,11 @@ for k, v in ICONS.items():
|
|
|
317
150
|
ICONS[k] = os.path.join(ICON_PATH, v)
|
|
318
151
|
|
|
319
152
|
# Toolbar style suitable for platform
|
|
320
|
-
TOOL_BUTTON_STYLE = Qt.ToolButtonTextUnderIcon
|
|
153
|
+
TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonTextUnderIcon
|
|
321
154
|
if platform == 'Windows': # pragma: no linux cover
|
|
322
|
-
TOOL_BUTTON_STYLE = Qt.ToolButtonIconOnly
|
|
155
|
+
TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonIconOnly
|
|
323
156
|
elif platform == 'Darwin': # pragma: no linux cover
|
|
324
|
-
TOOL_BUTTON_STYLE = Qt.ToolButtonTextOnly
|
|
157
|
+
TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonTextOnly
|
|
325
158
|
|
|
326
159
|
|
|
327
160
|
# Stand alone applications
|
|
@@ -349,10 +182,11 @@ def qtMonospaceFont():
|
|
|
349
182
|
"""
|
|
350
183
|
font = QtGui.QFont('monospace')
|
|
351
184
|
if platform == 'Windows': # pragma: no linux cover
|
|
352
|
-
font.setStyleHint(QtGui.QFont.TypeWriter)
|
|
185
|
+
font.setStyleHint(QtGui.QFont.StyleHint.TypeWriter)
|
|
353
186
|
else:
|
|
354
|
-
font.setStyleHint(QtGui.QFont.Monospace)
|
|
355
|
-
font.setHintingPreference(
|
|
187
|
+
font.setStyleHint(QtGui.QFont.StyleHint.Monospace)
|
|
188
|
+
font.setHintingPreference(
|
|
189
|
+
QtGui.QFont.HintingPreference.PreferVerticalHinting)
|
|
356
190
|
return font
|
|
357
191
|
|
|
358
192
|
|
|
@@ -402,5 +236,5 @@ def run(app, *args):
|
|
|
402
236
|
timer.timeout.connect(lambda: None)
|
|
403
237
|
|
|
404
238
|
# Wait for app to exit
|
|
405
|
-
sys.exit(a.
|
|
239
|
+
sys.exit(a.exec())
|
|
406
240
|
|