babelplot 2025.8__tar.gz → 2025.10__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.
Files changed (48) hide show
  1. {babelplot-2025.8 → babelplot-2025.10}/PKG-INFO +1 -1
  2. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/__init__.py +1 -1
  3. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/backend/catalog/bokeh_.py +60 -27
  4. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/backend/catalog/matplotlib_.py +47 -47
  5. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/backend/catalog/plotly_.py +35 -35
  6. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/backend/catalog/vedo_.py +18 -14
  7. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/backend/helper/validation.py +53 -1
  8. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/constant/path.py +1 -1
  9. babelplot-2025.10/package/babelplot/task/color.py +112 -0
  10. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/task/help.py +6 -2
  11. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/task/instantiation.py +2 -1
  12. babelplot-2025.10/package/babelplot/task/plotting.py +85 -0
  13. babelplot-2025.10/package/babelplot/task/showing.py +172 -0
  14. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/type/backend.py +23 -40
  15. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/type/ffp_base.py +3 -3
  16. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/type/figure.py +2 -21
  17. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/type/frame.py +2 -1
  18. babelplot-2025.8/package/babelplot/type/translator.py → babelplot-2025.10/package/babelplot/type/plot_function.py +6 -4
  19. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/type/plot_type.py +3 -60
  20. babelplot-2025.10/package/babelplot/type/translator.py +70 -0
  21. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/version.py +1 -1
  22. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot.egg-info/PKG-INFO +1 -1
  23. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot.egg-info/SOURCES.txt +3 -1
  24. babelplot-2025.8/package/babelplot/runtime/figure.py +0 -55
  25. babelplot-2025.8/package/babelplot/task/showing.py +0 -137
  26. {babelplot-2025.8 → babelplot-2025.10}/MANIFEST.in +0 -0
  27. {babelplot-2025.8 → babelplot-2025.10}/README-COPYRIGHT-utf8.txt +0 -0
  28. {babelplot-2025.8 → babelplot-2025.10}/README-LICENCE-utf8.txt +0 -0
  29. {babelplot-2025.8 → babelplot-2025.10}/README.rst +0 -0
  30. {babelplot-2025.8 → babelplot-2025.10}/documentation/wiki/description.asciidoc +0 -0
  31. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/api/backend.py +0 -0
  32. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/api/definition.py +0 -0
  33. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/api/help.py +0 -0
  34. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/backend/helper/creation.py +0 -0
  35. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/constant/backend.py +0 -0
  36. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/constant/project.py +0 -0
  37. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/extension/enum_.py +0 -0
  38. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/extension/function.py +0 -0
  39. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/runtime/backends.py +0 -0
  40. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/type/dimension.py +0 -0
  41. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot/type/plot.py +0 -0
  42. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot.egg-info/dependency_links.txt +0 -0
  43. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot.egg-info/requires.txt +0 -0
  44. {babelplot-2025.8 → babelplot-2025.10}/package/babelplot.egg-info/top_level.txt +0 -0
  45. {babelplot-2025.8 → babelplot-2025.10}/pyproject.toml +0 -0
  46. {babelplot-2025.8 → babelplot-2025.10}/requirements.txt +0 -0
  47. {babelplot-2025.8 → babelplot-2025.10}/setup.cfg +0 -0
  48. {babelplot-2025.8 → babelplot-2025.10}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: babelplot
3
- Version: 2025.8
3
+ Version: 2025.10
4
4
  Summary: A Meta Plotting Library That Speaks Several Backends
5
5
  Home-page: https://src.koda.cnrs.fr/eric.debreuve/babelplot/
6
6
  Author: Eric Debreuve
@@ -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 ShowAllFigures
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__
@@ -9,24 +9,26 @@ import gzip
9
9
  import typing as h
10
10
  from multiprocessing import Process as process_t
11
11
 
12
- from babelplot.task.showing import ShowHTMLWithPyQt
12
+ from babelplot.task.plotting import NewPlotFunctionsTemplate, SetDefaultPlotFunction
13
+ from babelplot.task.showing import ShowHTMLPlotWithPyQt
13
14
  from babelplot.type.dimension import dim_e
14
15
  from babelplot.type.figure import figure_t as base_figure_t
15
16
  from babelplot.type.frame import frame_t as base_frame_t
16
17
  from babelplot.type.plot import plot_t as base_plot_t
17
- from babelplot.type.plot_type import plot_e, plot_function_h
18
+ from babelplot.type.plot_function import plot_function_h
19
+ from babelplot.type.plot_type import plot_e
18
20
  from bokeh.embed import file_html as HTMLofBackendContent # noqa
19
21
  from bokeh.layouts import column as NewBackendColLayout # noqa
20
22
  from bokeh.layouts import grid as NewBackendGridLayout # noqa
21
23
  from bokeh.layouts import row as NewBackendRowLayout # noqa
22
24
  from bokeh.models.renderers import GlyphRenderer as backend_plot_t # noqa
23
- from bokeh.plotting import figure as backend_figure_t # noqa
25
+ from bokeh.plotting import figure as backend_frame_t # noqa
24
26
  from bokeh.resources import INLINE # noqa
25
27
 
26
28
  NAME = "bokeh"
27
29
 
28
30
 
29
- backend_frame_t = backend_figure_t
31
+ class backend_figure_t: ...
30
32
 
31
33
 
32
34
  @d.dataclass(slots=True, repr=False, eq=False)
@@ -44,24 +46,22 @@ class frame_t(base_frame_t):
44
46
  **kwargs,
45
47
  ) -> plot_t:
46
48
  """"""
47
- output = plot_t(
49
+ return plot_t(
48
50
  title=title,
49
51
  property=kwargs.copy(),
50
52
  backend_name=self.backend_name,
53
+ raw=plot_function(self.raw, *args, **kwargs),
51
54
  )
52
55
 
53
- output.raw = plot_function(self.raw, *args, **kwargs)
54
-
55
- return output
56
-
57
56
 
58
57
  @d.dataclass(slots=True, repr=False, eq=False)
59
58
  class figure_t(base_figure_t):
60
- layout: h.Any = None
59
+
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(*args, **kwargs)
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
- output = frame_t(
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
- arranged_frames[row][col] = frame.raw
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).
@@ -123,6 +128,7 @@ class figure_t(base_figure_t):
123
128
  """"""
124
129
  try:
125
130
  html = HTMLofBackendContent(self.layout, INLINE)
131
+ html = gzip.compress(html.encode())
126
132
  except ValueError as exception:
127
133
  html = f"""
128
134
  <!DOCTYPE html>
@@ -133,24 +139,51 @@ class figure_t(base_figure_t):
133
139
  </body>
134
140
  </html>
135
141
  """
136
- uid = id(self)
142
+
143
+ process = process_t(target=ShowHTMLPlotWithPyQt, args=(html,))
144
+ process.start()
145
+
137
146
  if modal:
138
- ShowHTMLWithPyQt(html, uid)
139
- self.AcknowledgeClosure()
147
+ process.join()
140
148
  else:
141
- html = gzip.compress(html.encode())
142
- process = process_t(target=lambda: ShowHTMLWithPyQt(html, uid))
143
- process.start()
144
149
  self.showing_process = process
145
150
 
146
151
 
147
- PLOTS = plot_e.NewPlotsTemplate()
148
- PLOTS[plot_e.SCATTER][1] = backend_frame_t.scatter
152
+ def _DefaultFunction(type_: plot_e, frame_dim: int, /) -> plot_function_h:
153
+ """"""
154
+
155
+ def Actual(frame: backend_frame_t, *args, **kwargs) -> backend_plot_t:
156
+ """"""
157
+ args = ", ".join(map(lambda _: type(_).__name__, args))
158
+ kwargs = ", ".join(
159
+ f"{_key}={type(_vle).__name__}" for _key, _vle in kwargs.items()
160
+ )
161
+
162
+ return backend_frame_t.text(
163
+ frame,
164
+ x=(0,),
165
+ y=(0,),
166
+ text=(
167
+ f"Unhandled Plot Request\n{type_.name}.{frame_dim}\nargs: {args}\nkwargs: {kwargs}",
168
+ ),
169
+ text_font_size="30px",
170
+ text_align="center",
171
+ text_color="#FF0000",
172
+ )
173
+
174
+ return Actual
175
+
176
+
177
+ PLOTS = NewPlotFunctionsTemplate()
178
+ PLOTS[plot_e.SCATTER][0] = backend_frame_t.scatter
179
+ SetDefaultPlotFunction(PLOTS, _DefaultFunction)
149
180
 
150
181
 
151
182
  TRANSLATIONS = {
152
183
  "color_face": "fill_color",
153
184
  "opacity": "alpha",
185
+ ("AddFrame", "azimuth"): None,
186
+ ("AddFrame", "elevation"): None,
154
187
  }
155
188
 
156
189
 
@@ -10,12 +10,15 @@ import typing as h
10
10
  import matplotlib.pyplot as pypl # noqa
11
11
  import numpy as nmpy
12
12
  import skimage.measure as msre
13
+ from babelplot.task.color import NewConvertedColor
14
+ from babelplot.task.plotting import NewPlotFunctionsTemplate
13
15
  from babelplot.type.dimension import dim_e
14
16
  from babelplot.type.ffp_base import backend_element_h
15
17
  from babelplot.type.figure import figure_t as base_figure_t
16
18
  from babelplot.type.frame import frame_t as base_frame_t
17
19
  from babelplot.type.plot import plot_t as base_plot_t
18
- from babelplot.type.plot_type import plot_e, plot_function_h, plot_type_h
20
+ from babelplot.type.plot_function import plot_function_h
21
+ from babelplot.type.plot_type import plot_e, plot_type_h
19
22
  from logger_36 import L
20
23
  from matplotlib.artist import Artist as backend_plot_t # noqa
21
24
  from matplotlib.container import Container as backend_plots_t # noqa
@@ -27,7 +30,7 @@ from matplotlib.pyplot import Figure as backend_figure_t # noqa
27
30
  from matplotlib.pyplot import figure as NewBackendFigure # noqa
28
31
  from mpl_toolkits.mplot3d import Axes3D as backend_frame_3d_t # noqa
29
32
 
30
- import matplotlib as mlpl # noqa
33
+ import matplotlib as mtpl # noqa
31
34
 
32
35
  NAME = "matplotlib"
33
36
 
@@ -39,7 +42,7 @@ backend_frame_h = backend_frame_2d_t | backend_frame_3d_t
39
42
  def _DefaultProperties(type_: type[plot_type_h], /) -> dict[str, h.Any]:
40
43
  """"""
41
44
  name = type_.__name__
42
- properties = mlpl.rcParams.find_all(f"^{name}\\.")
45
+ properties = mtpl.rcParams.find_all(f"^{name}\\.")
43
46
 
44
47
  return {_key.replace(f"{name}.", ""): _vle for _key, _vle in properties.items()}
45
48
 
@@ -108,16 +111,13 @@ class frame_t(base_frame_t):
108
111
  **kwargs,
109
112
  ) -> plot_t:
110
113
  """"""
111
- output = plot_t(
114
+ return plot_t(
112
115
  title=title,
113
116
  property=kwargs.copy(),
114
117
  backend_name=self.backend_name,
118
+ raw=plot_function(self.raw, *args, **kwargs),
115
119
  )
116
120
 
117
- output.raw = plot_function(self.raw, *args, **kwargs)
118
-
119
- return output
120
-
121
121
 
122
122
  @d.dataclass(slots=True, repr=False, eq=False)
123
123
  class figure_t(base_figure_t):
@@ -126,11 +126,7 @@ class figure_t(base_figure_t):
126
126
 
127
127
  def _NewBackendFigure(self, *args, **kwargs) -> backend_figure_t:
128
128
  """"""
129
- output = NewBackendFigure(*args, num=None, **kwargs)
130
-
131
- output.canvas.mpl_connect("close_event", lambda *_, **__: _OnCloseEvent(self))
132
-
133
- return output
129
+ return NewBackendFigure(*args, num=None, **kwargs)
134
130
 
135
131
  def _NewFrame(
136
132
  self,
@@ -204,25 +200,29 @@ class figure_t(base_figure_t):
204
200
 
205
201
  def _BackendShow(self, modal: bool, /) -> None:
206
202
  """"""
207
- raw = self.raw
208
- raw.show()
203
+ self.raw.show()
209
204
 
210
205
  if modal:
211
- title = raw.get_suptitle()
212
- if title.__len__() > 0:
213
- title = f"{title} [MASTER FIGURE]"
214
- else:
215
- title = "MASTER FIGURE"
216
- raw.suptitle(title)
206
+ if "qt" in mtpl.get_backend().lower():
207
+ from matplotlib.backends.qt_compat import QtWidgets # noqa
217
208
 
218
- raw.canvas.start_event_loop()
209
+ application = QtWidgets.QApplication.instance()
210
+ application.exec()
211
+ else:
212
+ event_manager = self.raw.canvas
213
+ event_manager.mpl_connect("close_event", _OnCloseEvent)
214
+ event_manager.start_event_loop()
219
215
 
220
216
 
221
- def _OnCloseEvent(figure: figure_t, /) -> None:
217
+ def _OnCloseEvent(event: h.Any, /) -> None:
222
218
  """"""
223
- # Hopefully, the event loop does not mind being stopped several times.
224
- figure.raw.canvas.stop_event_loop()
225
- figure.AcknowledgeClosure()
219
+ event.canvas.stop_event_loop()
220
+
221
+ figures = tuple(map(pypl.figure, pypl.get_fignums()))
222
+ if figures.__len__() > 0:
223
+ event_manager = figures[0].canvas
224
+ event_manager.mpl_connect("close_event", _OnCloseEvent)
225
+ event_manager.start_event_loop()
226
226
 
227
227
 
228
228
  def _Arrows2(frame: backend_frame_2d_t, *args, **kwargs) -> backend_plot_t:
@@ -390,26 +390,26 @@ def _Text3(frame: backend_frame_2d_t, text, x, y, z, *_, **kwargs) -> backend_pl
390
390
  return frame.text(x, y, z, text, **kwargs)
391
391
 
392
392
 
393
- PLOTS = plot_e.NewPlotsTemplate()
394
-
395
- PLOTS[plot_e.ARROWS][1] = _Arrows2
396
- PLOTS[plot_e.ARROWS][2] = _Arrows3
397
- PLOTS[plot_e.BAR3][2] = _Bar3
398
- PLOTS[plot_e.BARH][1] = _BarH
399
- PLOTS[plot_e.BARV][1] = _BarV
400
- PLOTS[plot_e.ELEVATION][2] = _ElevationSurface
401
- PLOTS[plot_e.IMAGE][1] = backend_frame_2d_t.matshow
402
- PLOTS[plot_e.ISOSET][1] = _IsoContour
403
- PLOTS[plot_e.ISOSET][2] = _IsoSurface
404
- PLOTS[plot_e.MESH][2] = _Mesh
405
- PLOTS[plot_e.PIE][1] = backend_frame_2d_t.pie
406
- PLOTS[plot_e.POLYGON][1] = _Polygon
407
- PLOTS[plot_e.POLYLINE][1] = backend_frame_2d_t.plot
408
- PLOTS[plot_e.POLYLINE][2] = backend_frame_3d_t.plot
409
- PLOTS[plot_e.SCATTER][1] = backend_frame_2d_t.scatter
410
- PLOTS[plot_e.SCATTER][2] = backend_frame_3d_t.scatter
411
- PLOTS[plot_e.TEXT][1] = _Text2
412
- PLOTS[plot_e.TEXT][2] = _Text3
393
+ PLOTS = NewPlotFunctionsTemplate()
394
+
395
+ PLOTS[plot_e.ARROWS][0] = _Arrows2
396
+ PLOTS[plot_e.ARROWS][1] = _Arrows3
397
+ PLOTS[plot_e.BAR3][1] = _Bar3
398
+ PLOTS[plot_e.BARH][0] = _BarH
399
+ PLOTS[plot_e.BARV][0] = _BarV
400
+ PLOTS[plot_e.ELEVATION][1] = _ElevationSurface
401
+ PLOTS[plot_e.IMAGE][0] = backend_frame_2d_t.matshow
402
+ PLOTS[plot_e.ISOSET][0] = _IsoContour
403
+ PLOTS[plot_e.ISOSET][1] = _IsoSurface
404
+ PLOTS[plot_e.MESH][1] = _Mesh
405
+ PLOTS[plot_e.PIE][0] = backend_frame_2d_t.pie
406
+ PLOTS[plot_e.POLYGON][0] = _Polygon
407
+ PLOTS[plot_e.POLYLINE][0] = backend_frame_2d_t.plot
408
+ PLOTS[plot_e.POLYLINE][1] = backend_frame_3d_t.plot
409
+ PLOTS[plot_e.SCATTER][0] = backend_frame_2d_t.scatter
410
+ PLOTS[plot_e.SCATTER][1] = backend_frame_3d_t.scatter
411
+ PLOTS[plot_e.TEXT][0] = _Text2
412
+ PLOTS[plot_e.TEXT][1] = _Text3
413
413
 
414
414
 
415
415
  TRANSLATIONS = {
@@ -437,7 +437,7 @@ TRANSLATIONS = {
437
437
  (_ElevationSurface, "color_face"): "color",
438
438
  (_IsoContour, "color"): "colors",
439
439
  (_IsoSurface, "color_face"): "color",
440
- (_Mesh, "color_face"): "color",
440
+ (_Mesh, "color_face"): ("color", lambda _: NewConvertedColor(_, "hex", 0)),
441
441
  (_Polygon, "color_edge"): "edgecolor",
442
442
  (_Polygon, "color_face"): "facecolor",
443
443
  (backend_frame_2d_t.pie, "color"): "colors",
@@ -13,12 +13,14 @@ from pathlib import Path as path_t
13
13
  import numpy as nmpy
14
14
  import plotly.figure_factory as fcry # noqa
15
15
  import plotly.graph_objects as plly # noqa
16
- from babelplot.task.showing import ShowHTMLWithPyQt
16
+ from babelplot.task.plotting import NewPlotFunctionsTemplate
17
+ from babelplot.task.showing import ShowHTMLPlotWithPyQt
17
18
  from babelplot.type.dimension import dim_e
18
19
  from babelplot.type.figure import figure_t as base_figure_t
19
20
  from babelplot.type.frame import frame_t as base_frame_t
20
21
  from babelplot.type.plot import plot_t as base_plot_t
21
- from babelplot.type.plot_type import plot_e, plot_function_h
22
+ from babelplot.type.plot_function import plot_function_h
23
+ from babelplot.type.plot_type import plot_e
22
24
  from plotly.basedatatypes import BasePlotlyType as backend_plot_t # noqa
23
25
  from plotly.graph_objects import Figure as backend_figure_t # noqa
24
26
  from plotly.subplots import make_subplots as NewMultiAxesFigure # noqa
@@ -54,16 +56,13 @@ class frame_t(base_frame_t):
54
56
  **kwargs,
55
57
  ) -> plot_t:
56
58
  """"""
57
- output = plot_t(
59
+ return plot_t(
58
60
  title=title,
59
61
  property=kwargs.copy(),
60
62
  backend_name=self.backend_name,
63
+ raw=plot_function(*args, **kwargs),
61
64
  )
62
65
 
63
- output.raw = plot_function(*args, **kwargs)
64
-
65
- return output
66
-
67
66
 
68
67
  @d.dataclass(slots=True, repr=False, eq=False)
69
68
  class figure_t(base_figure_t):
@@ -138,18 +137,19 @@ class figure_t(base_figure_t):
138
137
  Note on include_plotlyjs:
139
138
  - "cdn": works but must be online.
140
139
  - True => blank figure if using
141
- PySide6.QtWebEngineWidgets.QWebEngineView.setHtml because of html size limit.
142
- See note in babelplot.task.html.Show.
140
+ PySide6.QtWebEngineWidgets.QWebEngineView.setHtml because of html size
141
+ limit.
142
+ See note in babelplot.task.html.Show.
143
143
  """
144
144
  html = self.raw.to_html(include_plotlyjs=True, config=_FIGURE_CONFIG)
145
- uid = id(self)
145
+ html = gzip.compress(html.encode())
146
+
147
+ process = process_t(target=ShowHTMLPlotWithPyQt, args=(html,))
148
+ process.start()
149
+
146
150
  if modal:
147
- ShowHTMLWithPyQt(html, uid)
148
- self.AcknowledgeClosure()
151
+ process.join()
149
152
  else:
150
- html = gzip.compress(html.encode())
151
- process = process_t(target=lambda: ShowHTMLWithPyQt(html, uid))
152
- process.start()
153
153
  self.showing_process = process
154
154
 
155
155
 
@@ -456,26 +456,26 @@ def _Text3(text: str, x: float, y: float, z: float, *_, **kwargs) -> backend_plo
456
456
  )
457
457
 
458
458
 
459
- PLOTS = plot_e.NewPlotsTemplate()
460
-
461
- PLOTS[plot_e.ARROWS][1] = _Arrows2
462
- PLOTS[plot_e.ARROWS][2] = _Arrows3
463
- PLOTS[plot_e.BAR3][2] = _Bar3
464
- PLOTS[plot_e.BARH][1] = _BarH
465
- PLOTS[plot_e.BARV][1] = _BarV
466
- PLOTS[plot_e.ELEVATION][2] = _ElevationSurface
467
- PLOTS[plot_e.IMAGE][1] = _Image
468
- PLOTS[plot_e.ISOSET][1] = _IsoContour
469
- PLOTS[plot_e.ISOSET][2] = _IsoSurface
470
- PLOTS[plot_e.MESH][2] = _Mesh
471
- PLOTS[plot_e.PIE][1] = _Pie
472
- PLOTS[plot_e.POLYGON][1] = _Polygon
473
- PLOTS[plot_e.POLYLINE][1] = _Polyline2
474
- PLOTS[plot_e.POLYLINE][2] = _Polyline3
475
- PLOTS[plot_e.SCATTER][1] = _Scatter2
476
- PLOTS[plot_e.SCATTER][2] = _Scatter3
477
- PLOTS[plot_e.TEXT][1] = _Text2
478
- PLOTS[plot_e.TEXT][2] = _Text3
459
+ PLOTS = NewPlotFunctionsTemplate()
460
+
461
+ PLOTS[plot_e.ARROWS][0] = _Arrows2
462
+ PLOTS[plot_e.ARROWS][1] = _Arrows3
463
+ PLOTS[plot_e.BAR3][1] = _Bar3
464
+ PLOTS[plot_e.BARH][0] = _BarH
465
+ PLOTS[plot_e.BARV][0] = _BarV
466
+ PLOTS[plot_e.ELEVATION][1] = _ElevationSurface
467
+ PLOTS[plot_e.IMAGE][0] = _Image
468
+ PLOTS[plot_e.ISOSET][0] = _IsoContour
469
+ PLOTS[plot_e.ISOSET][1] = _IsoSurface
470
+ PLOTS[plot_e.MESH][1] = _Mesh
471
+ PLOTS[plot_e.PIE][0] = _Pie
472
+ PLOTS[plot_e.POLYGON][0] = _Polygon
473
+ PLOTS[plot_e.POLYLINE][0] = _Polyline2
474
+ PLOTS[plot_e.POLYLINE][1] = _Polyline3
475
+ PLOTS[plot_e.SCATTER][0] = _Scatter2
476
+ PLOTS[plot_e.SCATTER][1] = _Scatter3
477
+ PLOTS[plot_e.TEXT][0] = _Text2
478
+ PLOTS[plot_e.TEXT][1] = _Text3
479
479
 
480
480
 
481
481
  def _ApplyGlobalTranslation(
@@ -7,12 +7,14 @@ SEE COPYRIGHT NOTICE BELOW
7
7
  import dataclasses as d
8
8
  from multiprocessing import Process as process_t
9
9
 
10
- import vedo # noqa
10
+ from babelplot.task.color import NewConvertedColor
11
+ from babelplot.task.plotting import NewPlotFunctionsTemplate
11
12
  from babelplot.type.dimension import dim_e
12
13
  from babelplot.type.figure import figure_t as base_figure_t
13
14
  from babelplot.type.frame import frame_t as base_frame_t
14
15
  from babelplot.type.plot import plot_t as base_plot_t
15
- from babelplot.type.plot_type import plot_e, plot_function_h
16
+ from babelplot.type.plot_function import plot_function_h
17
+ from babelplot.type.plot_type import plot_e
16
18
  from numpy import ndarray as array_t
17
19
  from vedo import Mesh as backend_plot_t # noqa
18
20
  from vedo import Plotter as backend_figure_t # noqa
@@ -40,13 +42,11 @@ class frame_t(base_frame_t):
40
42
  title=title,
41
43
  property=kwargs.copy(),
42
44
  backend_name=self.backend_name,
45
+ raw=plot_function(*args, **kwargs),
43
46
  )
44
47
 
45
- raw = plot_function(*args, **kwargs)
46
- if raw is not None:
47
- self.raw.__iadd__(raw)
48
-
49
- output.raw = raw
48
+ if output.raw is not None:
49
+ self.raw.__iadd__(output.raw)
50
50
 
51
51
  return output
52
52
 
@@ -80,12 +80,15 @@ class figure_t(base_figure_t):
80
80
 
81
81
  def _BackendShow(self, modal: bool, /) -> None:
82
82
  """"""
83
+ # Passing self.raw.show().close shows the figures one by one.
84
+ BackendShow = lambda: self.raw.show().close()
85
+
86
+ process = process_t(target=BackendShow)
87
+ process.start()
88
+
83
89
  if modal:
84
- self.raw.show().close()
85
- self.AcknowledgeClosure()
90
+ process.join()
86
91
  else:
87
- process = process_t(target=lambda: self.raw.show().close())
88
- process.start()
89
92
  self.showing_process = process
90
93
 
91
94
 
@@ -108,9 +111,9 @@ def _Mesh(triangles: array_t, vertices: array_t, *_, **kwargs) -> backend_plot_t
108
111
  return output
109
112
 
110
113
 
111
- PLOTS = plot_e.NewPlotsTemplate()
112
- PLOTS[plot_e.ISOSET][2] = _IsoSurface
113
- PLOTS[plot_e.MESH][2] = _Mesh
114
+ PLOTS = NewPlotFunctionsTemplate()
115
+ PLOTS[plot_e.ISOSET][1] = _IsoSurface
116
+ PLOTS[plot_e.MESH][1] = _Mesh
114
117
 
115
118
 
116
119
  TRANSLATIONS = {
@@ -118,6 +121,7 @@ TRANSLATIONS = {
118
121
  (_IsoSurface, "color_face"): None,
119
122
  (_IsoSurface, "step_size"): None,
120
123
  (_IsoSurface, "width_edge"): None,
124
+ (_Mesh, "color_face"): ("color_face", lambda _: NewConvertedColor(_, "hex", 0)),
121
125
  }
122
126
 
123
127
 
@@ -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 = plot_e.PlotsIssues(defined)
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
 
@@ -5,7 +5,7 @@ SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
7
  BACKEND_CATALOG_PY_PATH = "babelplot.backend.catalog"
8
-
8
+ QT_RUNTIME_PY_PATH = "babelplot.runtime.application"
9
9
 
10
10
  """
11
11
  COPYRIGHT NOTICE