babelplot 2025.4__tar.gz → 2025.6__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 (49) hide show
  1. {babelplot-2025.4 → babelplot-2025.6}/PKG-INFO +1 -1
  2. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/__init__.py +3 -1
  3. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/api/backend.py +0 -1
  4. babelplot-2025.6/package/babelplot/api/definition.py +54 -0
  5. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/api/help.py +1 -1
  6. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/backend/catalog/bokeh_.py +84 -94
  7. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/backend/catalog/matplotlib_.py +156 -166
  8. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/backend/catalog/plotly_.py +201 -110
  9. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/backend/catalog/vedo_.py +57 -74
  10. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/backend/helper/creation.py +7 -5
  11. babelplot-2025.4/package/babelplot/constant/backend.py → babelplot-2025.6/package/babelplot/backend/helper/validation.py +38 -40
  12. babelplot-2025.4/package/babelplot/api/definition.py → babelplot-2025.6/package/babelplot/constant/backend.py +13 -3
  13. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/extension/enum_.py +3 -3
  14. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/extension/function.py +0 -51
  15. babelplot-2025.6/package/babelplot/runtime/backends.py +55 -0
  16. babelplot-2025.6/package/babelplot/runtime/figure.py +55 -0
  17. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/task/help.py +12 -10
  18. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/task/instantiation.py +19 -58
  19. babelplot-2025.4/package/babelplot/task/show_pyqt6.py → babelplot-2025.6/package/babelplot/task/showing.py +32 -0
  20. babelplot-2025.6/package/babelplot/type/backend.py +279 -0
  21. {babelplot-2025.4/package/babelplot/definition → babelplot-2025.6/package/babelplot/type}/dimension.py +24 -50
  22. babelplot-2025.4/package/babelplot/type/base.py → babelplot-2025.6/package/babelplot/type/ffp_base.py +30 -35
  23. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/type/figure.py +99 -108
  24. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/type/frame.py +39 -73
  25. babelplot-2025.6/package/babelplot/type/plot.py +61 -0
  26. babelplot-2025.4/package/babelplot/definition/plot.py → babelplot-2025.6/package/babelplot/type/plot_type.py +164 -251
  27. babelplot-2025.6/package/babelplot/type/translator.py +60 -0
  28. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/version.py +1 -1
  29. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot.egg-info/PKG-INFO +1 -1
  30. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot.egg-info/SOURCES.txt +9 -8
  31. babelplot-2025.4/package/babelplot/backend/definition/backend.py +0 -113
  32. babelplot-2025.4/package/babelplot/backend/definition/runtime.py +0 -77
  33. babelplot-2025.4/package/babelplot/backend/helper/validation.py +0 -130
  34. babelplot-2025.4/package/babelplot/extension/ast_.py +0 -155
  35. babelplot-2025.4/package/babelplot/type/plot.py +0 -119
  36. {babelplot-2025.4 → babelplot-2025.6}/MANIFEST.in +0 -0
  37. {babelplot-2025.4 → babelplot-2025.6}/README-COPYRIGHT-utf8.txt +0 -0
  38. {babelplot-2025.4 → babelplot-2025.6}/README-LICENCE-utf8.txt +0 -0
  39. {babelplot-2025.4 → babelplot-2025.6}/README.rst +0 -0
  40. {babelplot-2025.4 → babelplot-2025.6}/documentation/wiki/description.asciidoc +0 -0
  41. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/constant/path.py +0 -0
  42. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot/constant/project.py +0 -0
  43. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot.egg-info/dependency_links.txt +0 -0
  44. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot.egg-info/requires.txt +0 -0
  45. {babelplot-2025.4 → babelplot-2025.6}/package/babelplot.egg-info/top_level.txt +0 -0
  46. {babelplot-2025.4 → babelplot-2025.6}/pyproject.toml +0 -0
  47. {babelplot-2025.4 → babelplot-2025.6}/requirements.txt +0 -0
  48. {babelplot-2025.4 → babelplot-2025.6}/setup.cfg +0 -0
  49. {babelplot-2025.4 → babelplot-2025.6}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: babelplot
3
- Version: 2025.4
3
+ Version: 2025.6
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,9 @@ else:
18
18
  beartype_this_package()
19
19
 
20
20
  from babelplot.task.instantiation import NewFigure, NewPlot
21
- from babelplot.type.figure import ShowAllFigures
21
+ from babelplot.task.showing import ShowAllFigures
22
+ from babelplot.type.dimension import dim_e
23
+ from babelplot.type.plot_type import plot_e
22
24
  from babelplot.version import __version__
23
25
 
24
26
  """
@@ -4,7 +4,6 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2022
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- from babelplot.backend.definition.runtime import AddBackendSpecification # noqa
8
7
  from babelplot.backend.helper.creation import PrintBackendDraft # noqa
9
8
  from babelplot.backend.helper.validation import CheckBackend # noqa
10
9
 
@@ -0,0 +1,54 @@
1
+ """
2
+ Copyright CNRS/Inria/UniCA
3
+ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2022
4
+ SEE COPYRIGHT NOTICE BELOW
5
+ """
6
+
7
+ from babelplot.type.dimension import dim_e # noqa
8
+ from babelplot.type.plot_type import plot_e # noqa
9
+
10
+ """
11
+ COPYRIGHT NOTICE
12
+
13
+ This software is governed by the CeCILL license under French law and
14
+ abiding by the rules of distribution of free software. You can use,
15
+ modify and/ or redistribute the software under the terms of the CeCILL
16
+ license as circulated by CEA, CNRS and INRIA at the following URL
17
+ "http://www.cecill.info".
18
+
19
+ As a counterpart to the access to the source code and rights to copy,
20
+ modify and redistribute granted by the license, users are provided only
21
+ with a limited warranty and the software's author, the holder of the
22
+ economic rights, and the successive licensors have only limited
23
+ liability.
24
+
25
+ In this respect, the user's attention is drawn to the risks associated
26
+ with loading, using, modifying and/or developing or reproducing the
27
+ software by the user in light of its specific status of free software,
28
+ that may mean that it is complicated to manipulate, and that also
29
+ therefore means that it is reserved for developers and experienced
30
+ professionals having in-depth computer knowledge. Users are therefore
31
+ encouraged to load and test the software's suitability as regards their
32
+ requirements in conditions enabling the security of their systems and/or
33
+ data to be ensured and, more generally, to use and operate it in the
34
+ same conditions as regards security.
35
+
36
+ The fact that you are presently reading this means that you have had
37
+ knowledge of the CeCILL license and that you accept its terms.
38
+
39
+ SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
40
+
41
+ This software is being developed by Eric Debreuve, a CNRS employee and
42
+ member of team Morpheme.
43
+ Team Morpheme is a joint team between Inria, CNRS, and UniCA.
44
+ It is hosted by the Centre Inria d'Université Côte d'Azur, Laboratory
45
+ I3S, and Laboratory iBV.
46
+
47
+ CNRS: https://www.cnrs.fr/index.php/en
48
+ Inria: https://www.inria.fr/en/
49
+ UniCA: https://univ-cotedazur.eu/
50
+ Centre Inria d'Université Côte d'Azur: https://www.inria.fr/en/centre/sophia/
51
+ I3S: https://www.i3s.unice.fr/en/
52
+ iBV: http://ibv.unice.fr/
53
+ Team Morpheme: https://team.inria.fr/morpheme/
54
+ """
@@ -4,7 +4,7 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2022
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- from babelplot.task.help import Main as PrintHelp # noqa
7
+ from babelplot.task.help import PrintHelp # noqa
8
8
  from babelplot.task.help import PrintUsage # noqa
9
9
 
10
10
  """
@@ -4,19 +4,16 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2022
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- from __future__ import annotations
8
-
7
+ import dataclasses as d
9
8
  import typing as h
10
9
 
11
- from babelplot.backend.definition.backend import backend_e
12
- from babelplot.definition.dimension import dim_e
13
- from babelplot.definition.plot import PlotsFromTemplate, plot_e, plot_type_h
14
- from babelplot.task.show_pyqt6 import Show
10
+ from babelplot.task.showing import Show
11
+ from babelplot.type.dimension import dim_e
15
12
  from babelplot.type.figure import figure_t as base_figure_t
16
13
  from babelplot.type.frame import frame_t as base_frame_t
17
14
  from babelplot.type.plot import plot_t as base_plot_t
15
+ from babelplot.type.plot_type import plot_e, plot_function_h
18
16
  from bokeh.embed import file_html as HTMLofBackendContent # noqa
19
- from bokeh.layouts import LayoutDOM as backend_content_t # noqa
20
17
  from bokeh.layouts import column as NewBackendColLayout # noqa
21
18
  from bokeh.layouts import grid as NewBackendGridLayout # noqa
22
19
  from bokeh.layouts import row as NewBackendRowLayout # noqa
@@ -24,99 +21,92 @@ from bokeh.models.renderers import GlyphRenderer as backend_plot_t # noqa
24
21
  from bokeh.plotting import figure as backend_figure_t # noqa
25
22
  from bokeh.resources import INLINE # noqa
26
23
 
27
- NAME = backend_e.BOKEH.value
24
+ # from bokeh.layouts import LayoutDOM as backend_content_t # noqa
25
+
26
+ NAME = "bokeh"
28
27
 
29
28
 
30
29
  backend_frame_t = backend_figure_t
31
30
 
32
31
 
33
- def _NewPlot(
34
- frame: backend_frame_t,
35
- type_: plot_type_h | type[backend_plot_t],
36
- plot_function: (
37
- type[backend_plot_t] | h.Callable[..., backend_plot_t | h.Any] | None
38
- ),
39
- *args,
40
- title: str | None = None, # If _, then it is swallowed by kwargs!
41
- **kwargs,
42
- ) -> tuple[
43
- backend_plot_t | h.Any,
44
- type[backend_plot_t] | h.Callable[..., backend_plot_t | h.Any],
45
- ]:
46
- """"""
47
- if plot_function is None:
48
- if hasattr(backend_frame_t, type_):
49
- plot_function = getattr(backend_frame_t, type_)
32
+ @d.dataclass(slots=True, repr=False, eq=False)
33
+ class plot_t(base_plot_t): ...
34
+
35
+
36
+ @d.dataclass(slots=True, repr=False, eq=False)
37
+ class frame_t(base_frame_t):
38
+
39
+ def _NewPlot(
40
+ self,
41
+ plot_function: plot_function_h,
42
+ *args,
43
+ title: str | None = None, # If _, then it is swallowed by kwargs!
44
+ **kwargs,
45
+ ) -> plot_t:
46
+ """"""
47
+ output = plot_t(
48
+ title=title,
49
+ property=kwargs.copy(),
50
+ backend_name=self.backend_name,
51
+ )
52
+
53
+ output.raw = plot_function(self.raw, *args, **kwargs)
54
+
55
+ return output
56
+
57
+
58
+ @d.dataclass(slots=True, repr=False, eq=False)
59
+ class figure_t(base_figure_t):
60
+ layout: h.Any = None
61
+
62
+ _NewBackendFigure = backend_figure_t
63
+ _BackendShow = Show
64
+
65
+ def _NewFrame(
66
+ self,
67
+ row: int,
68
+ col: int,
69
+ *args,
70
+ title: str | None = None,
71
+ dim: dim_e = dim_e.XY,
72
+ **kwargs,
73
+ ) -> frame_t:
74
+ """"""
75
+ output = frame_t(
76
+ title=title,
77
+ dim=dim,
78
+ backend_name=self.backend_name,
79
+ )
80
+
81
+ output.raw = backend_frame_t(*args, title=title, **kwargs)
82
+
83
+ return output
84
+
85
+ def AdjustLayout(self) -> None:
86
+ """"""
87
+ n_rows, n_cols = self.shape
88
+ arranged_frames = [n_cols * [None] for _ in range(n_rows)]
89
+ for frame, (row, col) in zip(self.frames, self.locations):
90
+ arranged_frames[row][col] = frame.raw
91
+ arranged_frames: list[list[backend_frame_t]]
92
+
93
+ if n_rows > 1:
94
+ if n_cols > 1:
95
+ layout = NewBackendGridLayout(arranged_frames)
96
+ else:
97
+ column = [_row[0] for _row in arranged_frames]
98
+ layout = NewBackendColLayout(column)
50
99
  else:
51
- raise ValueError(f"{type_}: Unknown {NAME} graph object.")
52
-
53
- return plot_function(frame, *args, **kwargs), plot_function
54
-
55
-
56
- def _NewFrame(
57
- _: backend_figure_t,
58
- __: int,
59
- ___: int,
60
- *args,
61
- title: str | None = None,
62
- dim: dim_e = dim_e.XY, # If _, then it is swallowed by kwargs!
63
- **kwargs,
64
- ) -> backend_frame_t:
65
- """"""
66
- return backend_frame_t(*args, title=title, **kwargs)
67
-
68
-
69
- def _AdjustLayout(figure: figure_t, /) -> None:
70
- """"""
71
- n_rows, n_cols = figure.shape
72
- arranged_frames = [n_cols * [None] for _ in range(n_rows)]
73
- for frame, (row, col) in zip(figure.frames, figure.locations):
74
- arranged_frames[row][col] = frame.backend
75
- arranged_frames: list[list[backend_frame_t]]
76
-
77
- if n_rows > 1:
78
- if n_cols > 1:
79
- layout = NewBackendGridLayout(arranged_frames)
80
- else:
81
- column = [_row[0] for _row in arranged_frames]
82
- layout = NewBackendColLayout(column)
83
- else:
84
- layout = NewBackendRowLayout(arranged_frames[0])
85
-
86
- figure.layout = layout
87
-
88
-
89
- def _AsHTML(figure: figure_t, /) -> str:
90
- """"""
91
-
92
- return HTMLofBackendContent(figure.layout, INLINE)
93
-
94
-
95
- # noinspection PyTypeChecker
96
- plot_t: type[base_plot_t] = type("plot_t", (base_plot_t,), {})
97
- # noinspection PyTypeChecker
98
- frame_t: type[base_frame_t] = type(
99
- "frame_t",
100
- (base_frame_t,),
101
- {"plot_class": plot_t, "NewBackendPlot": staticmethod(_NewPlot)},
102
- )
103
- # noinspection PyTypeChecker
104
- figure_t: type[base_figure_t] = type(
105
- "figure_t",
106
- (base_figure_t,),
107
- {
108
- "frame_class": frame_t,
109
- "NewBackendFigure": backend_figure_t,
110
- "NewBackendFrame": staticmethod(_NewFrame),
111
- "AdjustLayout": _AdjustLayout,
112
- "BackendShow": Show,
113
- "layout": None,
114
- "AsHTML": _AsHTML,
115
- },
116
- )
117
-
118
-
119
- PLOTS = PlotsFromTemplate()
100
+ layout = NewBackendRowLayout(arranged_frames[0])
101
+
102
+ self.layout = layout
103
+
104
+ def AsHTML(self) -> str:
105
+ """"""
106
+ return HTMLofBackendContent(self.layout, INLINE)
107
+
108
+
109
+ PLOTS = plot_e.NewPlotsTemplate()
120
110
  PLOTS[plot_e.SCATTER][1] = backend_frame_t.scatter
121
111
 
122
112
 
@@ -4,20 +4,18 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2022
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- from __future__ import annotations
8
-
7
+ import dataclasses as d
9
8
  import typing as h
10
9
 
11
10
  import matplotlib.pyplot as pypl # noqa
12
11
  import numpy as nmpy
13
12
  import skimage.measure as msre
14
- from babelplot.backend.definition.backend import backend_e
15
- from babelplot.definition.dimension import dim_e
16
- from babelplot.definition.plot import PlotsFromTemplate, plot_e, plot_type_h
17
- from babelplot.type.base import backend_element_h
13
+ from babelplot.type.dimension import dim_e
14
+ from babelplot.type.ffp_base import backend_element_h
18
15
  from babelplot.type.figure import figure_t as base_figure_t
19
16
  from babelplot.type.frame import frame_t as base_frame_t
20
17
  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
21
19
  from logger_36 import L
22
20
  from matplotlib.artist import Artist as backend_plot_t # noqa
23
21
  from matplotlib.container import Container as backend_plots_t # noqa
@@ -31,109 +29,14 @@ from mpl_toolkits.mplot3d import Axes3D as backend_frame_3d_t # noqa
31
29
 
32
30
  import matplotlib as mlpl # noqa
33
31
 
34
- NAME = backend_e.MATPLOTLIB.value
32
+ NAME = "matplotlib"
35
33
 
36
34
 
37
35
  array_t = nmpy.ndarray
38
36
  backend_frame_h = backend_frame_2d_t | backend_frame_3d_t
39
37
 
40
38
 
41
- def _NewPlot(
42
- frame: backend_frame_h,
43
- type_: plot_type_h | type[backend_plot_t],
44
- plot_function: (
45
- type[backend_plot_t] | h.Callable[..., backend_plot_t | h.Any] | None
46
- ),
47
- *args,
48
- title: str | None = None, # /!\ If _, then it is swallowed by kwargs!
49
- **kwargs,
50
- ) -> tuple[
51
- backend_plot_t | h.Any,
52
- type[backend_plot_t] | h.Callable[..., backend_plot_t | h.Any],
53
- ]:
54
- """"""
55
- if plot_function is None:
56
- # Next, priority is given to 2-D plots... which might be a problem if a 2-D and
57
- # 3-D frame have plot types with the same name. For example, scatter in 2-D and
58
- # 3-D.
59
- if hasattr(backend_frame_2d_t, type_):
60
- plot_function = getattr(backend_frame_2d_t, type_)
61
- elif hasattr(backend_frame_3d_t, type_):
62
- plot_function = getattr(backend_frame_3d_t, type_)
63
- else:
64
- raise ValueError(f"{type_}: Unknown {NAME} graph object.")
65
-
66
- return plot_function(frame, *args, **kwargs), plot_function
67
-
68
-
69
- def _NewFrame(
70
- figure: backend_figure_t,
71
- _: int,
72
- __: int,
73
- *args,
74
- title: str | None = None,
75
- dim: dim_e = dim_e.XY,
76
- **kwargs,
77
- ) -> backend_frame_h:
78
- """"""
79
- if dim is dim_e.XY:
80
- output = figure.subplots(*args, **kwargs)
81
- elif dim is dim_e.XYZ:
82
- # See note below
83
- output = backend_frame_3d_t(figure, *args, auto_add_to_figure=False, **kwargs)
84
- figure.add_axes(output)
85
- else:
86
- raise NotImplementedError(f"{dim}: Dimension management not implemented yet")
87
- if title is not None:
88
- output.set_title(title)
89
-
90
- return output
91
-
92
-
93
- def _AdjustLayout(figure: figure_t, /) -> None:
94
- """"""
95
- raw_figure = figure.backend
96
-
97
- if figure.title is not None:
98
- raw_figure.suptitle(figure.title)
99
- for frame in figure.frames:
100
- if frame.title is not None:
101
- frame.backend.set_title(frame.title)
102
- for plot in frame.plots:
103
- if plot.title is not None:
104
- plot.backend.set_label(plot.title)
105
-
106
- if figure.frames.__len__() < 2:
107
- return
108
-
109
- grid_spec = grid_spec_t(*figure.shape, figure=raw_figure)
110
- bottoms, tops, lefts, rights = grid_spec.get_grid_positions(raw_figure)
111
-
112
- for frame, (row, col) in zip(figure.frames, figure.locations):
113
- left, bottom, width, height = (
114
- lefts[col],
115
- bottoms[row],
116
- rights[col] - lefts[col],
117
- tops[row] - bottoms[row],
118
- )
119
- frame.backend.set_position((left, bottom, width, height))
120
-
121
-
122
- def _Show(
123
- figure: figure_t,
124
- /,
125
- ) -> None:
126
- """"""
127
- raw = figure.backend
128
-
129
- raw.show()
130
-
131
- event_manager = raw.canvas
132
- event_manager.mpl_connect("close_event", lambda _: event_manager.stop_event_loop())
133
- event_manager.start_event_loop()
134
-
135
-
136
- def _DefaultProperties(type_: h.Callable, /) -> dict[str, h.Any]:
39
+ def _DefaultProperties(type_: type[plot_type_h], /) -> dict[str, h.Any]:
137
40
  """"""
138
41
  name = type_.__name__
139
42
  properties = mlpl.rcParams.find_all(f"^{name}\\.")
@@ -151,16 +54,16 @@ def _SetProperty(
151
54
  if isinstance(element, h.Sequence):
152
55
  elements = element
153
56
  for element in elements:
154
- _SetProperty(element, name, value)
57
+ _SetProperty(element.raw, name, value)
155
58
  return
156
59
 
157
60
  if name == "marker":
158
61
  new_marker = marker_style_t(value)
159
- element.set_paths((new_marker.get_path(),))
62
+ element.raw.set_paths((new_marker.get_path(),))
160
63
  else:
161
64
  property_ = {name: value}
162
65
  try:
163
- pypl.setp(element, **property_)
66
+ pypl.setp(element.raw, **property_)
164
67
  except AttributeError:
165
68
  L.error(
166
69
  f'Property "{name}": Invalid property for element of type "{type(element).__name__}"'
@@ -172,10 +75,10 @@ def _Property(
172
75
  ) -> h.Any:
173
76
  """"""
174
77
  if isinstance(element, h.Sequence):
175
- return _Property(element[0], name)
78
+ return _Property(element[0].raw, name)
176
79
 
177
80
  try:
178
- output = pypl.getp(element, property=name)
81
+ output = pypl.getp(element.raw, property=name)
179
82
  except AttributeError:
180
83
  output = None
181
84
  L.error(
@@ -185,41 +88,128 @@ def _Property(
185
88
  return output
186
89
 
187
90
 
188
- # noinspection PyTypeChecker
189
- plot_t: type[base_plot_t] = type(
190
- "plot_t",
191
- (base_plot_t,),
192
- {
193
- "BackendDefaultProperties": staticmethod(_DefaultProperties),
194
- "BackendSetProperty": staticmethod(_SetProperty),
195
- "BackendProperty": staticmethod(_Property),
196
- },
197
- )
198
- # noinspection PyTypeChecker
199
- frame_t: type[base_frame_t] = type(
200
- "frame_t",
201
- (base_frame_t,),
202
- {
203
- "plot_class": plot_t,
204
- "NewBackendPlot": staticmethod(_NewPlot),
205
- "BackendSetProperty": staticmethod(_SetProperty),
206
- "BackendProperty": staticmethod(_Property),
207
- },
208
- )
209
- # noinspection PyTypeChecker
210
- figure_t: type[base_figure_t] = type(
211
- "figure_t",
212
- (base_figure_t,),
213
- {
214
- "frame_class": frame_t,
215
- "NewBackendFigure": staticmethod(NewBackendFigure),
216
- "NewBackendFrame": staticmethod(_NewFrame),
217
- "AdjustLayout": _AdjustLayout,
218
- "BackendShow": _Show,
219
- "BackendSetProperty": staticmethod(_SetProperty),
220
- "BackendProperty": staticmethod(_Property),
221
- },
222
- )
91
+ @d.dataclass(slots=True, repr=False, eq=False)
92
+ class plot_t(base_plot_t):
93
+ _BackendDefaultProperties: h.ClassVar[h.Callable] = _DefaultProperties
94
+ _BackendSetProperty: h.ClassVar[h.Callable] = _SetProperty
95
+ _BackendProperty: h.ClassVar[h.Callable] = _Property
96
+
97
+
98
+ @d.dataclass(slots=True, repr=False, eq=False)
99
+ class frame_t(base_frame_t):
100
+ _BackendSetProperty: h.ClassVar[h.Callable] = _SetProperty
101
+ _BackendProperty: h.ClassVar[h.Callable] = _Property
102
+
103
+ def _NewPlot(
104
+ self,
105
+ plot_function: plot_function_h,
106
+ *args,
107
+ title: str | None = None, # /!\ If _, then it is swallowed by kwargs!
108
+ **kwargs,
109
+ ) -> plot_t:
110
+ """"""
111
+ output = plot_t(
112
+ title=title,
113
+ property=kwargs.copy(),
114
+ backend_name=self.backend_name,
115
+ )
116
+
117
+ output.raw = plot_function(self.raw, *args, **kwargs)
118
+
119
+ return output
120
+
121
+
122
+ @d.dataclass(slots=True, repr=False, eq=False)
123
+ class figure_t(base_figure_t):
124
+ _BackendSetProperty: h.ClassVar[h.Callable] = _SetProperty
125
+ _BackendProperty: h.ClassVar[h.Callable] = _Property
126
+
127
+ @staticmethod
128
+ def _NewBackendFigure(*args, **kwargs) -> backend_figure_t:
129
+ """"""
130
+ return NewBackendFigure(*args, num=None, **kwargs)
131
+
132
+ def _NewFrame(
133
+ self,
134
+ title: str | None,
135
+ dim: dim_e,
136
+ row: int,
137
+ col: int,
138
+ *args,
139
+ **kwargs,
140
+ ) -> frame_t:
141
+ """"""
142
+ output = frame_t(
143
+ title=title,
144
+ dim=dim,
145
+ backend_name=self.backend_name,
146
+ )
147
+
148
+ if dim is dim_e.XY:
149
+ raw = self.raw.subplots(*args, **kwargs)
150
+ elif dim is dim_e.XYZ:
151
+ # See note below
152
+ raw = backend_frame_3d_t(
153
+ self.raw, *args, auto_add_to_figure=False, **kwargs
154
+ )
155
+ self.raw.add_axes(raw)
156
+ else:
157
+ raise NotImplementedError(f"Frame dimension {dim} not implemented.")
158
+ if title is not None:
159
+ raw.set_title(title)
160
+
161
+ output.raw = raw
162
+
163
+ return output
164
+
165
+ def AdjustLayout(self) -> None:
166
+ """"""
167
+ figure_raw = self.raw
168
+
169
+ if self.title is not None:
170
+ figure_raw.suptitle(self.title)
171
+ for frame in self.frames:
172
+ if frame.title is not None:
173
+ frame.raw.set_title(frame.title)
174
+ for plot in frame.plots:
175
+ if plot.title is not None:
176
+ plot_raw = plot.raw
177
+ if isinstance(plot_raw, h.Sequence):
178
+ plot_raw_s = plot_raw
179
+ else:
180
+ plot_raw_s = (plot_raw,)
181
+ for plot_raw in plot_raw_s:
182
+ if (
183
+ SetLabel := getattr(plot_raw, "set_label", None)
184
+ ) is not None:
185
+ SetLabel(plot.title)
186
+
187
+ if self.frames.__len__() < 2:
188
+ return
189
+
190
+ grid_spec = grid_spec_t(*self.shape, figure=figure_raw)
191
+ bottoms, tops, lefts, rights = grid_spec.get_grid_positions(figure_raw)
192
+
193
+ for frame, (row, col) in zip(self.frames, self.locations):
194
+ left, bottom, width, height = (
195
+ lefts[col],
196
+ bottoms[row],
197
+ rights[col] - lefts[col],
198
+ tops[row] - bottoms[row],
199
+ )
200
+ frame.raw.set_position((left, bottom, width, height))
201
+
202
+ def _BackendShow(self) -> None:
203
+ """"""
204
+ raw = self.raw
205
+
206
+ raw.show()
207
+
208
+ event_manager = raw.canvas
209
+ event_manager.mpl_connect(
210
+ "close_event", lambda _: event_manager.stop_event_loop()
211
+ )
212
+ event_manager.start_event_loop()
223
213
 
224
214
 
225
215
  def _Polygon(
@@ -387,7 +377,7 @@ def _Text3(frame: backend_frame_2d_t, text, x, y, z, *_, **kwargs) -> backend_pl
387
377
  return frame.text(x, y, z, text, **kwargs)
388
378
 
389
379
 
390
- PLOTS = PlotsFromTemplate()
380
+ PLOTS = plot_e.NewPlotsTemplate()
391
381
 
392
382
  PLOTS[plot_e.SCATTER][1] = backend_frame_2d_t.scatter
393
383
  PLOTS[plot_e.POLYLINE][1] = backend_frame_2d_t.plot
@@ -442,30 +432,30 @@ TRANSLATIONS = {
442
432
  (backend_frame_3d_t.scatter, 2): "zs",
443
433
  }
444
434
 
435
+ """
436
+ From: https://matplotlib.org/stable/api/prev_api_changes/api_changes_3.4.0.html
437
+ *Axes3D automatically adding itself to Figure is deprecated*
438
+
439
+ New Axes3D objects previously added themselves to figures when they were created,
440
+ unlike all other Axes classes, which lead to them being added twice if
441
+ fig.add_subplot(111, projection='3d') was called.
442
+
443
+ This behavior is now deprecated and will warn. The new keyword argument
444
+ auto_add_to_figure controls the behavior and can be used to suppress the warning. The
445
+ default value will change to False in Matplotlib 3.5, and any non-False value will be
446
+ an error in Matplotlib 3.6.
447
+
448
+ In the future, Axes3D will need to be explicitly added to the figure
445
449
 
446
- # From: https://matplotlib.org/stable/api/prev_api_changes/api_changes_3.4.0.html
447
- # *Axes3D automatically adding itself to Figure is deprecated*
448
- #
449
- # New Axes3D objects previously added themselves to figures when they were created,
450
- # unlike all other Axes classes, which lead to them being added twice if
451
- # fig.add_subplot(111, projection='3d') was called.
452
- #
453
- # This behavior is now deprecated and will warn. The new keyword argument
454
- # auto_add_to_figure controls the behavior and can be used to suppress the warning. The
455
- # default value will change to False in Matplotlib 3.5, and any non-False value will be
456
- # an error in Matplotlib 3.6.
457
- #
458
- # In the future, Axes3D will need to be explicitly added to the figure
459
- #
460
- # fig = Figure()
461
- # ax = Axes3d(fig)
462
- # fig.add_axes(ax)
463
- #
464
- # as needs to be done for other axes.Axes subclasses. Or, a 3D projection can be made
465
- # via:
466
- #
467
- # fig.add_subplot(projection='3d')
450
+ fig = Figure()
451
+ ax = Axes3d(fig)
452
+ fig.add_axes(ax)
468
453
 
454
+ as needs to be done for other axes.Axes subclasses. Or, a 3D projection can be made
455
+ via:
456
+
457
+ fig.add_subplot(projection='3d')
458
+ """
469
459
 
470
460
  """
471
461
  COPYRIGHT NOTICE