babelplot 2025.8__tar.gz → 2025.9__tar.gz
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.
- {babelplot-2025.8 → babelplot-2025.9}/PKG-INFO +1 -1
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/__init__.py +1 -1
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/backend/catalog/bokeh_.py +59 -31
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/backend/catalog/matplotlib_.py +46 -45
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/backend/catalog/plotly_.py +35 -39
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/backend/catalog/vedo_.py +14 -18
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/backend/helper/validation.py +53 -1
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/constant/path.py +1 -1
- babelplot-2025.8/package/babelplot/runtime/figure.py → babelplot-2025.9/package/babelplot/runtime/application.py +7 -2
- babelplot-2025.9/package/babelplot/task/color.py +112 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/task/help.py +6 -2
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/task/instantiation.py +2 -1
- babelplot-2025.9/package/babelplot/task/plotting.py +85 -0
- babelplot-2025.9/package/babelplot/task/showing.py +116 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/type/backend.py +23 -40
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/type/ffp_base.py +3 -3
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/type/figure.py +16 -19
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/type/frame.py +2 -1
- babelplot-2025.8/package/babelplot/type/translator.py → babelplot-2025.9/package/babelplot/type/plot_function.py +6 -4
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/type/plot_type.py +3 -60
- babelplot-2025.9/package/babelplot/type/translator.py +70 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/version.py +1 -1
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot.egg-info/PKG-INFO +1 -1
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot.egg-info/SOURCES.txt +4 -1
- babelplot-2025.8/package/babelplot/task/showing.py +0 -137
- {babelplot-2025.8 → babelplot-2025.9}/MANIFEST.in +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/README-COPYRIGHT-utf8.txt +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/README-LICENCE-utf8.txt +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/README.rst +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/documentation/wiki/description.asciidoc +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/api/backend.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/api/definition.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/api/help.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/backend/helper/creation.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/constant/backend.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/constant/project.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/extension/enum_.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/extension/function.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/runtime/backends.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/type/dimension.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot/type/plot.py +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot.egg-info/dependency_links.txt +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot.egg-info/requires.txt +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/package/babelplot.egg-info/top_level.txt +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/pyproject.toml +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/requirements.txt +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/setup.cfg +0 -0
- {babelplot-2025.8 → babelplot-2025.9}/setup.py +0 -0
|
@@ -18,7 +18,7 @@ else:
|
|
|
18
18
|
beartype_this_package()
|
|
19
19
|
|
|
20
20
|
from babelplot.task.instantiation import NewFigure, NewPlot
|
|
21
|
-
from babelplot.task.showing import
|
|
21
|
+
from babelplot.task.showing import ShowFigures
|
|
22
22
|
from babelplot.type.dimension import dim_e
|
|
23
23
|
from babelplot.type.plot_type import plot_e
|
|
24
24
|
from babelplot.version import __version__
|
|
@@ -5,28 +5,29 @@ SEE COPYRIGHT NOTICE BELOW
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import dataclasses as d
|
|
8
|
-
import gzip
|
|
9
8
|
import typing as h
|
|
10
|
-
from multiprocessing import Process as process_t
|
|
11
9
|
|
|
12
|
-
from babelplot.
|
|
10
|
+
from babelplot.runtime.application import QT_APPLICATION
|
|
11
|
+
from babelplot.task.plotting import NewPlotFunctionsTemplate, SetDefaultPlotFunction
|
|
12
|
+
from babelplot.task.showing import NewPyQtWidgetWithHTML, widget_t
|
|
13
13
|
from babelplot.type.dimension import dim_e
|
|
14
14
|
from babelplot.type.figure import figure_t as base_figure_t
|
|
15
15
|
from babelplot.type.frame import frame_t as base_frame_t
|
|
16
16
|
from babelplot.type.plot import plot_t as base_plot_t
|
|
17
|
-
from babelplot.type.
|
|
17
|
+
from babelplot.type.plot_function import plot_function_h
|
|
18
|
+
from babelplot.type.plot_type import plot_e
|
|
18
19
|
from bokeh.embed import file_html as HTMLofBackendContent # noqa
|
|
19
20
|
from bokeh.layouts import column as NewBackendColLayout # noqa
|
|
20
21
|
from bokeh.layouts import grid as NewBackendGridLayout # noqa
|
|
21
22
|
from bokeh.layouts import row as NewBackendRowLayout # noqa
|
|
22
23
|
from bokeh.models.renderers import GlyphRenderer as backend_plot_t # noqa
|
|
23
|
-
from bokeh.plotting import figure as
|
|
24
|
+
from bokeh.plotting import figure as backend_frame_t # noqa
|
|
24
25
|
from bokeh.resources import INLINE # noqa
|
|
25
26
|
|
|
26
27
|
NAME = "bokeh"
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
class backend_figure_t: ...
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
@d.dataclass(slots=True, repr=False, eq=False)
|
|
@@ -44,24 +45,23 @@ class frame_t(base_frame_t):
|
|
|
44
45
|
**kwargs,
|
|
45
46
|
) -> plot_t:
|
|
46
47
|
""""""
|
|
47
|
-
|
|
48
|
+
return plot_t(
|
|
48
49
|
title=title,
|
|
49
50
|
property=kwargs.copy(),
|
|
50
51
|
backend_name=self.backend_name,
|
|
52
|
+
raw=plot_function(self.raw, *args, **kwargs),
|
|
51
53
|
)
|
|
52
54
|
|
|
53
|
-
output.raw = plot_function(self.raw, *args, **kwargs)
|
|
54
|
-
|
|
55
|
-
return output
|
|
56
|
-
|
|
57
55
|
|
|
58
56
|
@d.dataclass(slots=True, repr=False, eq=False)
|
|
59
57
|
class figure_t(base_figure_t):
|
|
60
|
-
|
|
58
|
+
|
|
59
|
+
widget: widget_t | None = d.field(init=False, default=None)
|
|
60
|
+
layout: h.Any = d.field(init=False, default=None)
|
|
61
61
|
|
|
62
62
|
def _NewBackendFigure(self, *args, **kwargs) -> backend_figure_t:
|
|
63
63
|
""""""
|
|
64
|
-
return backend_figure_t(
|
|
64
|
+
return backend_figure_t() # self.raw is never used.
|
|
65
65
|
|
|
66
66
|
def _NewFrame(
|
|
67
67
|
self,
|
|
@@ -73,26 +73,31 @@ class figure_t(base_figure_t):
|
|
|
73
73
|
**kwargs,
|
|
74
74
|
) -> frame_t:
|
|
75
75
|
""""""
|
|
76
|
-
|
|
76
|
+
return frame_t(
|
|
77
77
|
title=title,
|
|
78
78
|
dim=dim,
|
|
79
79
|
backend_name=self.backend_name,
|
|
80
|
+
raw=backend_frame_t(title=title, **kwargs),
|
|
80
81
|
)
|
|
81
82
|
|
|
82
|
-
output.raw = backend_frame_t(title=title, **kwargs)
|
|
83
|
-
|
|
84
|
-
return output
|
|
85
|
-
|
|
86
83
|
def AdjustLayout(self) -> None:
|
|
87
84
|
""""""
|
|
88
|
-
# from bokeh.layouts import LayoutDOM as backend_content_t # noqa
|
|
89
|
-
|
|
90
85
|
# arranged_frames must be composed of list since Bokeh does not support tuples
|
|
91
86
|
# here!
|
|
92
87
|
n_rows, n_cols = self.shape
|
|
93
88
|
arranged_frames = [n_cols * [None] for _ in range(n_rows)]
|
|
94
89
|
for frame, (row, col) in zip(self.frames, self.locations):
|
|
95
|
-
|
|
90
|
+
raw = frame.raw
|
|
91
|
+
if raw.renderers.__len__() == 0:
|
|
92
|
+
_ = backend_frame_t.text(
|
|
93
|
+
raw,
|
|
94
|
+
x=(0,),
|
|
95
|
+
y=(0,),
|
|
96
|
+
text=("Empty Frame",),
|
|
97
|
+
text_font_size="30px",
|
|
98
|
+
text_color="#FF0000",
|
|
99
|
+
)
|
|
100
|
+
arranged_frames[row][col] = raw
|
|
96
101
|
|
|
97
102
|
# Bokeh does not support inserting None as an indicator of empty space. As a
|
|
98
103
|
# workaround, the frames are currently flattened (and None_s are filtered out).
|
|
@@ -133,24 +138,47 @@ class figure_t(base_figure_t):
|
|
|
133
138
|
</body>
|
|
134
139
|
</html>
|
|
135
140
|
"""
|
|
136
|
-
|
|
141
|
+
self.widget = NewPyQtWidgetWithHTML(html)
|
|
142
|
+
|
|
137
143
|
if modal:
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
QT_APPLICATION.exec()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _DefaultFunction(type_: plot_e, frame_dim: int, /) -> plot_function_h:
|
|
148
|
+
""""""
|
|
149
|
+
|
|
150
|
+
def Actual(frame: backend_frame_t, *args, **kwargs) -> backend_plot_t:
|
|
151
|
+
""""""
|
|
152
|
+
args = ", ".join(map(lambda _: type(_).__name__, args))
|
|
153
|
+
kwargs = ", ".join(
|
|
154
|
+
f"{_key}={type(_vle).__name__}" for _key, _vle in kwargs.items()
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return backend_frame_t.text(
|
|
158
|
+
frame,
|
|
159
|
+
x=(0,),
|
|
160
|
+
y=(0,),
|
|
161
|
+
text=(
|
|
162
|
+
f"Unhandled Plot Request\n{type_.name}.{frame_dim}\nargs: {args}\nkwargs: {kwargs}",
|
|
163
|
+
),
|
|
164
|
+
text_font_size="30px",
|
|
165
|
+
text_align="center",
|
|
166
|
+
text_color="#FF0000",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
return Actual
|
|
145
170
|
|
|
146
171
|
|
|
147
|
-
PLOTS =
|
|
148
|
-
PLOTS[plot_e.SCATTER][
|
|
172
|
+
PLOTS = NewPlotFunctionsTemplate()
|
|
173
|
+
PLOTS[plot_e.SCATTER][0] = backend_frame_t.scatter
|
|
174
|
+
SetDefaultPlotFunction(PLOTS, _DefaultFunction)
|
|
149
175
|
|
|
150
176
|
|
|
151
177
|
TRANSLATIONS = {
|
|
152
178
|
"color_face": "fill_color",
|
|
153
179
|
"opacity": "alpha",
|
|
180
|
+
("AddFrame", "azimuth"): None,
|
|
181
|
+
("AddFrame", "elevation"): None,
|
|
154
182
|
}
|
|
155
183
|
|
|
156
184
|
|
|
@@ -5,17 +5,22 @@ SEE COPYRIGHT NOTICE BELOW
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import dataclasses as d
|
|
8
|
+
import importlib as mprt
|
|
8
9
|
import typing as h
|
|
9
10
|
|
|
10
11
|
import matplotlib.pyplot as pypl # noqa
|
|
11
12
|
import numpy as nmpy
|
|
12
13
|
import skimage.measure as msre
|
|
14
|
+
from babelplot.constant.path import QT_RUNTIME_PY_PATH
|
|
15
|
+
from babelplot.task.color import NewConvertedColor
|
|
16
|
+
from babelplot.task.plotting import NewPlotFunctionsTemplate
|
|
13
17
|
from babelplot.type.dimension import dim_e
|
|
14
18
|
from babelplot.type.ffp_base import backend_element_h
|
|
15
19
|
from babelplot.type.figure import figure_t as base_figure_t
|
|
16
20
|
from babelplot.type.frame import frame_t as base_frame_t
|
|
17
21
|
from babelplot.type.plot import plot_t as base_plot_t
|
|
18
|
-
from babelplot.type.
|
|
22
|
+
from babelplot.type.plot_function import plot_function_h
|
|
23
|
+
from babelplot.type.plot_type import plot_e, plot_type_h
|
|
19
24
|
from logger_36 import L
|
|
20
25
|
from matplotlib.artist import Artist as backend_plot_t # noqa
|
|
21
26
|
from matplotlib.container import Container as backend_plots_t # noqa
|
|
@@ -27,6 +32,7 @@ from matplotlib.pyplot import Figure as backend_figure_t # noqa
|
|
|
27
32
|
from matplotlib.pyplot import figure as NewBackendFigure # noqa
|
|
28
33
|
from mpl_toolkits.mplot3d import Axes3D as backend_frame_3d_t # noqa
|
|
29
34
|
|
|
35
|
+
import matplotlib as mtpl # noqa
|
|
30
36
|
import matplotlib as mlpl # noqa
|
|
31
37
|
|
|
32
38
|
NAME = "matplotlib"
|
|
@@ -108,16 +114,13 @@ class frame_t(base_frame_t):
|
|
|
108
114
|
**kwargs,
|
|
109
115
|
) -> plot_t:
|
|
110
116
|
""""""
|
|
111
|
-
|
|
117
|
+
return plot_t(
|
|
112
118
|
title=title,
|
|
113
119
|
property=kwargs.copy(),
|
|
114
120
|
backend_name=self.backend_name,
|
|
121
|
+
raw=plot_function(self.raw, *args, **kwargs),
|
|
115
122
|
)
|
|
116
123
|
|
|
117
|
-
output.raw = plot_function(self.raw, *args, **kwargs)
|
|
118
|
-
|
|
119
|
-
return output
|
|
120
|
-
|
|
121
124
|
|
|
122
125
|
@d.dataclass(slots=True, repr=False, eq=False)
|
|
123
126
|
class figure_t(base_figure_t):
|
|
@@ -126,11 +129,7 @@ class figure_t(base_figure_t):
|
|
|
126
129
|
|
|
127
130
|
def _NewBackendFigure(self, *args, **kwargs) -> backend_figure_t:
|
|
128
131
|
""""""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
output.canvas.mpl_connect("close_event", lambda *_, **__: _OnCloseEvent(self))
|
|
132
|
-
|
|
133
|
-
return output
|
|
132
|
+
return NewBackendFigure(*args, num=None, **kwargs)
|
|
134
133
|
|
|
135
134
|
def _NewFrame(
|
|
136
135
|
self,
|
|
@@ -204,25 +203,27 @@ class figure_t(base_figure_t):
|
|
|
204
203
|
|
|
205
204
|
def _BackendShow(self, modal: bool, /) -> None:
|
|
206
205
|
""""""
|
|
207
|
-
|
|
208
|
-
raw.show()
|
|
206
|
+
self.raw.show()
|
|
209
207
|
|
|
210
208
|
if modal:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
209
|
+
if "qt" in mtpl.get_backend().lower():
|
|
210
|
+
module = mprt.import_module(QT_RUNTIME_PY_PATH)
|
|
211
|
+
module.QT_APPLICATION.exec()
|
|
214
212
|
else:
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
event_manager = self.raw.canvas
|
|
214
|
+
event_manager.mpl_connect("close_event", _OnCloseEvent)
|
|
215
|
+
event_manager.start_event_loop()
|
|
217
216
|
|
|
218
|
-
raw.canvas.start_event_loop()
|
|
219
217
|
|
|
220
|
-
|
|
221
|
-
def _OnCloseEvent(figure: figure_t, /) -> None:
|
|
218
|
+
def _OnCloseEvent(event: h.Any, /) -> None:
|
|
222
219
|
""""""
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
figure.
|
|
220
|
+
event.canvas.stop_event_loop()
|
|
221
|
+
|
|
222
|
+
figures = tuple(map(pypl.figure, pypl.get_fignums()))
|
|
223
|
+
if figures.__len__() > 0:
|
|
224
|
+
event_manager = figures[0].canvas
|
|
225
|
+
event_manager.mpl_connect("close_event", _OnCloseEvent)
|
|
226
|
+
event_manager.start_event_loop()
|
|
226
227
|
|
|
227
228
|
|
|
228
229
|
def _Arrows2(frame: backend_frame_2d_t, *args, **kwargs) -> backend_plot_t:
|
|
@@ -390,26 +391,26 @@ def _Text3(frame: backend_frame_2d_t, text, x, y, z, *_, **kwargs) -> backend_pl
|
|
|
390
391
|
return frame.text(x, y, z, text, **kwargs)
|
|
391
392
|
|
|
392
393
|
|
|
393
|
-
PLOTS =
|
|
394
|
-
|
|
395
|
-
PLOTS[plot_e.ARROWS][
|
|
396
|
-
PLOTS[plot_e.ARROWS][
|
|
397
|
-
PLOTS[plot_e.BAR3][
|
|
398
|
-
PLOTS[plot_e.BARH][
|
|
399
|
-
PLOTS[plot_e.BARV][
|
|
400
|
-
PLOTS[plot_e.ELEVATION][
|
|
401
|
-
PLOTS[plot_e.IMAGE][
|
|
402
|
-
PLOTS[plot_e.ISOSET][
|
|
403
|
-
PLOTS[plot_e.ISOSET][
|
|
404
|
-
PLOTS[plot_e.MESH][
|
|
405
|
-
PLOTS[plot_e.PIE][
|
|
406
|
-
PLOTS[plot_e.POLYGON][
|
|
407
|
-
PLOTS[plot_e.POLYLINE][
|
|
408
|
-
PLOTS[plot_e.POLYLINE][
|
|
409
|
-
PLOTS[plot_e.SCATTER][
|
|
410
|
-
PLOTS[plot_e.SCATTER][
|
|
411
|
-
PLOTS[plot_e.TEXT][
|
|
412
|
-
PLOTS[plot_e.TEXT][
|
|
394
|
+
PLOTS = NewPlotFunctionsTemplate()
|
|
395
|
+
|
|
396
|
+
PLOTS[plot_e.ARROWS][0] = _Arrows2
|
|
397
|
+
PLOTS[plot_e.ARROWS][1] = _Arrows3
|
|
398
|
+
PLOTS[plot_e.BAR3][1] = _Bar3
|
|
399
|
+
PLOTS[plot_e.BARH][0] = _BarH
|
|
400
|
+
PLOTS[plot_e.BARV][0] = _BarV
|
|
401
|
+
PLOTS[plot_e.ELEVATION][1] = _ElevationSurface
|
|
402
|
+
PLOTS[plot_e.IMAGE][0] = backend_frame_2d_t.matshow
|
|
403
|
+
PLOTS[plot_e.ISOSET][0] = _IsoContour
|
|
404
|
+
PLOTS[plot_e.ISOSET][1] = _IsoSurface
|
|
405
|
+
PLOTS[plot_e.MESH][1] = _Mesh
|
|
406
|
+
PLOTS[plot_e.PIE][0] = backend_frame_2d_t.pie
|
|
407
|
+
PLOTS[plot_e.POLYGON][0] = _Polygon
|
|
408
|
+
PLOTS[plot_e.POLYLINE][0] = backend_frame_2d_t.plot
|
|
409
|
+
PLOTS[plot_e.POLYLINE][1] = backend_frame_3d_t.plot
|
|
410
|
+
PLOTS[plot_e.SCATTER][0] = backend_frame_2d_t.scatter
|
|
411
|
+
PLOTS[plot_e.SCATTER][1] = backend_frame_3d_t.scatter
|
|
412
|
+
PLOTS[plot_e.TEXT][0] = _Text2
|
|
413
|
+
PLOTS[plot_e.TEXT][1] = _Text3
|
|
413
414
|
|
|
414
415
|
|
|
415
416
|
TRANSLATIONS = {
|
|
@@ -437,7 +438,7 @@ TRANSLATIONS = {
|
|
|
437
438
|
(_ElevationSurface, "color_face"): "color",
|
|
438
439
|
(_IsoContour, "color"): "colors",
|
|
439
440
|
(_IsoSurface, "color_face"): "color",
|
|
440
|
-
(_Mesh, "color_face"): "color",
|
|
441
|
+
(_Mesh, "color_face"): ("color", lambda _: NewConvertedColor(_, "hex", 0)),
|
|
441
442
|
(_Polygon, "color_edge"): "edgecolor",
|
|
442
443
|
(_Polygon, "color_face"): "facecolor",
|
|
443
444
|
(backend_frame_2d_t.pie, "color"): "colors",
|
|
@@ -5,20 +5,21 @@ SEE COPYRIGHT NOTICE BELOW
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import dataclasses as d
|
|
8
|
-
import gzip
|
|
9
8
|
import typing as h
|
|
10
|
-
from multiprocessing import Process as process_t
|
|
11
9
|
from pathlib import Path as path_t
|
|
12
10
|
|
|
13
11
|
import numpy as nmpy
|
|
14
12
|
import plotly.figure_factory as fcry # noqa
|
|
15
13
|
import plotly.graph_objects as plly # noqa
|
|
16
|
-
from babelplot.
|
|
14
|
+
from babelplot.runtime.application import QT_APPLICATION
|
|
15
|
+
from babelplot.task.plotting import NewPlotFunctionsTemplate
|
|
16
|
+
from babelplot.task.showing import NewPyQtWidgetWithHTML, widget_t
|
|
17
17
|
from babelplot.type.dimension import dim_e
|
|
18
18
|
from babelplot.type.figure import figure_t as base_figure_t
|
|
19
19
|
from babelplot.type.frame import frame_t as base_frame_t
|
|
20
20
|
from babelplot.type.plot import plot_t as base_plot_t
|
|
21
|
-
from babelplot.type.
|
|
21
|
+
from babelplot.type.plot_function import plot_function_h
|
|
22
|
+
from babelplot.type.plot_type import plot_e
|
|
22
23
|
from plotly.basedatatypes import BasePlotlyType as backend_plot_t # noqa
|
|
23
24
|
from plotly.graph_objects import Figure as backend_figure_t # noqa
|
|
24
25
|
from plotly.subplots import make_subplots as NewMultiAxesFigure # noqa
|
|
@@ -54,20 +55,19 @@ class frame_t(base_frame_t):
|
|
|
54
55
|
**kwargs,
|
|
55
56
|
) -> plot_t:
|
|
56
57
|
""""""
|
|
57
|
-
|
|
58
|
+
return plot_t(
|
|
58
59
|
title=title,
|
|
59
60
|
property=kwargs.copy(),
|
|
60
61
|
backend_name=self.backend_name,
|
|
62
|
+
raw=plot_function(*args, **kwargs),
|
|
61
63
|
)
|
|
62
64
|
|
|
63
|
-
output.raw = plot_function(*args, **kwargs)
|
|
64
|
-
|
|
65
|
-
return output
|
|
66
|
-
|
|
67
65
|
|
|
68
66
|
@d.dataclass(slots=True, repr=False, eq=False)
|
|
69
67
|
class figure_t(base_figure_t):
|
|
70
68
|
|
|
69
|
+
widget: widget_t | None = d.field(init=False, default=None)
|
|
70
|
+
|
|
71
71
|
def _NewBackendFigure(self, *args, **kwargs) -> backend_figure_t:
|
|
72
72
|
""""""
|
|
73
73
|
return backend_figure_t(*args, **kwargs)
|
|
@@ -138,19 +138,15 @@ class figure_t(base_figure_t):
|
|
|
138
138
|
Note on include_plotlyjs:
|
|
139
139
|
- "cdn": works but must be online.
|
|
140
140
|
- True => blank figure if using
|
|
141
|
-
PySide6.QtWebEngineWidgets.QWebEngineView.setHtml because of html size
|
|
142
|
-
|
|
141
|
+
PySide6.QtWebEngineWidgets.QWebEngineView.setHtml because of html size
|
|
142
|
+
limit.
|
|
143
|
+
See note in babelplot.task.html.Show.
|
|
143
144
|
"""
|
|
144
145
|
html = self.raw.to_html(include_plotlyjs=True, config=_FIGURE_CONFIG)
|
|
145
|
-
|
|
146
|
+
self.widget = NewPyQtWidgetWithHTML(html)
|
|
147
|
+
|
|
146
148
|
if modal:
|
|
147
|
-
|
|
148
|
-
self.AcknowledgeClosure()
|
|
149
|
-
else:
|
|
150
|
-
html = gzip.compress(html.encode())
|
|
151
|
-
process = process_t(target=lambda: ShowHTMLWithPyQt(html, uid))
|
|
152
|
-
process.start()
|
|
153
|
-
self.showing_process = process
|
|
149
|
+
QT_APPLICATION.exec()
|
|
154
150
|
|
|
155
151
|
|
|
156
152
|
def _Arrows2(*args, **kwargs) -> backend_plot_t:
|
|
@@ -456,26 +452,26 @@ def _Text3(text: str, x: float, y: float, z: float, *_, **kwargs) -> backend_plo
|
|
|
456
452
|
)
|
|
457
453
|
|
|
458
454
|
|
|
459
|
-
PLOTS =
|
|
460
|
-
|
|
461
|
-
PLOTS[plot_e.ARROWS][
|
|
462
|
-
PLOTS[plot_e.ARROWS][
|
|
463
|
-
PLOTS[plot_e.BAR3][
|
|
464
|
-
PLOTS[plot_e.BARH][
|
|
465
|
-
PLOTS[plot_e.BARV][
|
|
466
|
-
PLOTS[plot_e.ELEVATION][
|
|
467
|
-
PLOTS[plot_e.IMAGE][
|
|
468
|
-
PLOTS[plot_e.ISOSET][
|
|
469
|
-
PLOTS[plot_e.ISOSET][
|
|
470
|
-
PLOTS[plot_e.MESH][
|
|
471
|
-
PLOTS[plot_e.PIE][
|
|
472
|
-
PLOTS[plot_e.POLYGON][
|
|
473
|
-
PLOTS[plot_e.POLYLINE][
|
|
474
|
-
PLOTS[plot_e.POLYLINE][
|
|
475
|
-
PLOTS[plot_e.SCATTER][
|
|
476
|
-
PLOTS[plot_e.SCATTER][
|
|
477
|
-
PLOTS[plot_e.TEXT][
|
|
478
|
-
PLOTS[plot_e.TEXT][
|
|
455
|
+
PLOTS = NewPlotFunctionsTemplate()
|
|
456
|
+
|
|
457
|
+
PLOTS[plot_e.ARROWS][0] = _Arrows2
|
|
458
|
+
PLOTS[plot_e.ARROWS][1] = _Arrows3
|
|
459
|
+
PLOTS[plot_e.BAR3][1] = _Bar3
|
|
460
|
+
PLOTS[plot_e.BARH][0] = _BarH
|
|
461
|
+
PLOTS[plot_e.BARV][0] = _BarV
|
|
462
|
+
PLOTS[plot_e.ELEVATION][1] = _ElevationSurface
|
|
463
|
+
PLOTS[plot_e.IMAGE][0] = _Image
|
|
464
|
+
PLOTS[plot_e.ISOSET][0] = _IsoContour
|
|
465
|
+
PLOTS[plot_e.ISOSET][1] = _IsoSurface
|
|
466
|
+
PLOTS[plot_e.MESH][1] = _Mesh
|
|
467
|
+
PLOTS[plot_e.PIE][0] = _Pie
|
|
468
|
+
PLOTS[plot_e.POLYGON][0] = _Polygon
|
|
469
|
+
PLOTS[plot_e.POLYLINE][0] = _Polyline2
|
|
470
|
+
PLOTS[plot_e.POLYLINE][1] = _Polyline3
|
|
471
|
+
PLOTS[plot_e.SCATTER][0] = _Scatter2
|
|
472
|
+
PLOTS[plot_e.SCATTER][1] = _Scatter3
|
|
473
|
+
PLOTS[plot_e.TEXT][0] = _Text2
|
|
474
|
+
PLOTS[plot_e.TEXT][1] = _Text3
|
|
479
475
|
|
|
480
476
|
|
|
481
477
|
def _ApplyGlobalTranslation(
|
|
@@ -5,14 +5,15 @@ SEE COPYRIGHT NOTICE BELOW
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import dataclasses as d
|
|
8
|
-
from multiprocessing import Process as process_t
|
|
9
8
|
|
|
10
|
-
import
|
|
9
|
+
from babelplot.task.color import NewConvertedColor
|
|
10
|
+
from babelplot.task.plotting import NewPlotFunctionsTemplate
|
|
11
11
|
from babelplot.type.dimension import dim_e
|
|
12
12
|
from babelplot.type.figure import figure_t as base_figure_t
|
|
13
13
|
from babelplot.type.frame import frame_t as base_frame_t
|
|
14
14
|
from babelplot.type.plot import plot_t as base_plot_t
|
|
15
|
-
from babelplot.type.
|
|
15
|
+
from babelplot.type.plot_function import plot_function_h
|
|
16
|
+
from babelplot.type.plot_type import plot_e
|
|
16
17
|
from numpy import ndarray as array_t
|
|
17
18
|
from vedo import Mesh as backend_plot_t # noqa
|
|
18
19
|
from vedo import Plotter as backend_figure_t # noqa
|
|
@@ -40,13 +41,11 @@ class frame_t(base_frame_t):
|
|
|
40
41
|
title=title,
|
|
41
42
|
property=kwargs.copy(),
|
|
42
43
|
backend_name=self.backend_name,
|
|
44
|
+
raw=plot_function(*args, **kwargs),
|
|
43
45
|
)
|
|
44
46
|
|
|
45
|
-
raw
|
|
46
|
-
|
|
47
|
-
self.raw.__iadd__(raw)
|
|
48
|
-
|
|
49
|
-
output.raw = raw
|
|
47
|
+
if output.raw is not None:
|
|
48
|
+
self.raw.__iadd__(output.raw)
|
|
50
49
|
|
|
51
50
|
return output
|
|
52
51
|
|
|
@@ -80,13 +79,9 @@ class figure_t(base_figure_t):
|
|
|
80
79
|
|
|
81
80
|
def _BackendShow(self, modal: bool, /) -> None:
|
|
82
81
|
""""""
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
else:
|
|
87
|
-
process = process_t(target=lambda: self.raw.show().close())
|
|
88
|
-
process.start()
|
|
89
|
-
self.showing_process = process
|
|
82
|
+
# Passing self.raw.show().close shows the figures one by one.
|
|
83
|
+
BackendShow = lambda: self.raw.show().close()
|
|
84
|
+
self._LaunchBackendShow(modal, BackendShow)
|
|
90
85
|
|
|
91
86
|
|
|
92
87
|
def _IsoSurface(volume: array_t, iso_value: float, *_, **kwargs) -> backend_plot_t:
|
|
@@ -108,9 +103,9 @@ def _Mesh(triangles: array_t, vertices: array_t, *_, **kwargs) -> backend_plot_t
|
|
|
108
103
|
return output
|
|
109
104
|
|
|
110
105
|
|
|
111
|
-
PLOTS =
|
|
112
|
-
PLOTS[plot_e.ISOSET][
|
|
113
|
-
PLOTS[plot_e.MESH][
|
|
106
|
+
PLOTS = NewPlotFunctionsTemplate()
|
|
107
|
+
PLOTS[plot_e.ISOSET][1] = _IsoSurface
|
|
108
|
+
PLOTS[plot_e.MESH][1] = _Mesh
|
|
114
109
|
|
|
115
110
|
|
|
116
111
|
TRANSLATIONS = {
|
|
@@ -118,6 +113,7 @@ TRANSLATIONS = {
|
|
|
118
113
|
(_IsoSurface, "color_face"): None,
|
|
119
114
|
(_IsoSurface, "step_size"): None,
|
|
120
115
|
(_IsoSurface, "width_edge"): None,
|
|
116
|
+
(_Mesh, "color_face"): ("color_face", lambda _: NewConvertedColor(_, "hex", 0)),
|
|
121
117
|
}
|
|
122
118
|
|
|
123
119
|
|
|
@@ -7,9 +7,11 @@ SEE COPYRIGHT NOTICE BELOW
|
|
|
7
7
|
import importlib as mprt
|
|
8
8
|
import importlib.util as mput
|
|
9
9
|
import sys as s
|
|
10
|
+
import typing as h
|
|
10
11
|
from pathlib import Path as path_t
|
|
11
12
|
|
|
12
13
|
from babelplot.runtime.backends import BACKENDS
|
|
14
|
+
from babelplot.type.plot_function import plot_functions_h
|
|
13
15
|
from babelplot.type.plot_type import plot_e
|
|
14
16
|
|
|
15
17
|
|
|
@@ -36,7 +38,7 @@ def CheckBackend(backend: str | path_t, /) -> None:
|
|
|
36
38
|
if hasattr(module, "PLOTS"):
|
|
37
39
|
defined = getattr(module, "PLOTS")
|
|
38
40
|
if isinstance(defined, dict):
|
|
39
|
-
issues =
|
|
41
|
+
issues = _PlotFunctionsIssues(defined)
|
|
40
42
|
if issues is not None:
|
|
41
43
|
print(f"--- PLOTS:\n ", "\n ".join(issues), sep="")
|
|
42
44
|
else:
|
|
@@ -49,6 +51,56 @@ def CheckBackend(backend: str | path_t, /) -> None:
|
|
|
49
51
|
# TODO: Check that translations respect the format (to be documented by the way).
|
|
50
52
|
|
|
51
53
|
|
|
54
|
+
def _PlotFunctionsIssues(plots: plot_functions_h, /) -> h.Sequence[str] | None:
|
|
55
|
+
""""""
|
|
56
|
+
issues = []
|
|
57
|
+
|
|
58
|
+
for key, value in plots.items():
|
|
59
|
+
if not isinstance(key, plot_e):
|
|
60
|
+
issues.append(
|
|
61
|
+
f"{key}/{type(key).__name__}: Invalid plot type. "
|
|
62
|
+
f"Expected={plot_e.__name__}."
|
|
63
|
+
)
|
|
64
|
+
continue
|
|
65
|
+
|
|
66
|
+
if not isinstance(value, list | tuple):
|
|
67
|
+
issues.append(
|
|
68
|
+
f"{key}/{type(value).__name__}: Invalid plot record type. "
|
|
69
|
+
f"Expected=list or tuple."
|
|
70
|
+
)
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
value = tuple(filter(lambda _: _ is not None, value))
|
|
74
|
+
|
|
75
|
+
how_defined = key.value
|
|
76
|
+
if (n_dimensions := value.__len__()) != (
|
|
77
|
+
n_required := how_defined[2].__len__()
|
|
78
|
+
):
|
|
79
|
+
issues.append(
|
|
80
|
+
f"{key}: Invalid number of possible dimensions {n_dimensions}. "
|
|
81
|
+
f"Expected={n_required}."
|
|
82
|
+
)
|
|
83
|
+
continue
|
|
84
|
+
|
|
85
|
+
for d_idx, for_dim in enumerate(value):
|
|
86
|
+
if not callable(for_dim):
|
|
87
|
+
issues.append(
|
|
88
|
+
f"{key}/{for_dim}: Invalid plot function "
|
|
89
|
+
f"for dim {how_defined[2][d_idx]}. "
|
|
90
|
+
f"Expected=Callable."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
missing = set(plot_e.__members__.values()).difference(plots.keys())
|
|
94
|
+
if missing.__len__() > 0:
|
|
95
|
+
missing = str(sorted(_elm.name for _elm in missing))[1:-1].replace("'", "")
|
|
96
|
+
issues.append(f"Missing plot type(s): {missing}")
|
|
97
|
+
|
|
98
|
+
if issues.__len__() > 0:
|
|
99
|
+
return issues
|
|
100
|
+
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
|
|
52
104
|
"""
|
|
53
105
|
COPYRIGHT NOTICE
|
|
54
106
|
|
|
@@ -4,9 +4,14 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2022
|
|
|
4
4
|
SEE COPYRIGHT NOTICE BELOW
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
SHOWN_FIGURES = []
|
|
7
|
+
import sys as s
|
|
9
8
|
|
|
9
|
+
from babelplot.constant.project import NAME
|
|
10
|
+
from PyQt6.QtWidgets import QApplication as application_t # noqa
|
|
11
|
+
|
|
12
|
+
if (QT_APPLICATION := application_t.instance()) is None:
|
|
13
|
+
QT_APPLICATION = application_t(s.argv)
|
|
14
|
+
QT_APPLICATION.setApplicationName(NAME) # Useful for window manager.
|
|
10
15
|
|
|
11
16
|
"""
|
|
12
17
|
COPYRIGHT NOTICE
|