figrecipe 0.5.0__py3-none-any.whl → 0.7.4__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.
Files changed (189) hide show
  1. figrecipe/__init__.py +220 -819
  2. figrecipe/_api/__init__.py +48 -0
  3. figrecipe/_api/_extract.py +108 -0
  4. figrecipe/_api/_notebook.py +61 -0
  5. figrecipe/_api/_panel.py +46 -0
  6. figrecipe/_api/_save.py +191 -0
  7. figrecipe/_api/_seaborn_proxy.py +34 -0
  8. figrecipe/_api/_style_manager.py +153 -0
  9. figrecipe/_api/_subplots.py +333 -0
  10. figrecipe/_api/_validate.py +82 -0
  11. figrecipe/_dev/__init__.py +29 -0
  12. figrecipe/_dev/_plotters.py +76 -0
  13. figrecipe/_dev/_run_demos.py +56 -0
  14. figrecipe/_dev/demo_plotters/__init__.py +64 -0
  15. figrecipe/_dev/demo_plotters/_categories.py +81 -0
  16. figrecipe/_dev/demo_plotters/_figure_creators.py +119 -0
  17. figrecipe/_dev/demo_plotters/_helpers.py +31 -0
  18. figrecipe/_dev/demo_plotters/_registry.py +50 -0
  19. figrecipe/_dev/demo_plotters/bar_categorical/__init__.py +4 -0
  20. figrecipe/_dev/demo_plotters/bar_categorical/plot_bar.py +25 -0
  21. figrecipe/_dev/demo_plotters/bar_categorical/plot_barh.py +25 -0
  22. figrecipe/_dev/demo_plotters/contour_surface/__init__.py +4 -0
  23. figrecipe/_dev/demo_plotters/contour_surface/plot_contour.py +30 -0
  24. figrecipe/_dev/demo_plotters/contour_surface/plot_contourf.py +29 -0
  25. figrecipe/_dev/demo_plotters/contour_surface/plot_tricontour.py +28 -0
  26. figrecipe/_dev/demo_plotters/contour_surface/plot_tricontourf.py +28 -0
  27. figrecipe/_dev/demo_plotters/contour_surface/plot_tripcolor.py +29 -0
  28. figrecipe/_dev/demo_plotters/contour_surface/plot_triplot.py +25 -0
  29. figrecipe/_dev/demo_plotters/distribution/__init__.py +4 -0
  30. figrecipe/_dev/demo_plotters/distribution/plot_boxplot.py +24 -0
  31. figrecipe/_dev/demo_plotters/distribution/plot_ecdf.py +24 -0
  32. figrecipe/_dev/demo_plotters/distribution/plot_hist.py +24 -0
  33. figrecipe/_dev/demo_plotters/distribution/plot_hist2d.py +25 -0
  34. figrecipe/_dev/demo_plotters/distribution/plot_violinplot.py +25 -0
  35. figrecipe/_dev/demo_plotters/image_matrix/__init__.py +4 -0
  36. figrecipe/_dev/demo_plotters/image_matrix/plot_hexbin.py +25 -0
  37. figrecipe/_dev/demo_plotters/image_matrix/plot_imshow.py +23 -0
  38. figrecipe/_dev/demo_plotters/image_matrix/plot_matshow.py +23 -0
  39. figrecipe/_dev/demo_plotters/image_matrix/plot_pcolor.py +29 -0
  40. figrecipe/_dev/demo_plotters/image_matrix/plot_pcolormesh.py +29 -0
  41. figrecipe/_dev/demo_plotters/image_matrix/plot_spy.py +29 -0
  42. figrecipe/_dev/demo_plotters/line_curve/__init__.py +4 -0
  43. figrecipe/_dev/demo_plotters/line_curve/plot_errorbar.py +28 -0
  44. figrecipe/_dev/demo_plotters/line_curve/plot_fill.py +29 -0
  45. figrecipe/_dev/demo_plotters/line_curve/plot_fill_between.py +30 -0
  46. figrecipe/_dev/demo_plotters/line_curve/plot_fill_betweenx.py +28 -0
  47. figrecipe/_dev/demo_plotters/line_curve/plot_plot.py +28 -0
  48. figrecipe/_dev/demo_plotters/line_curve/plot_stackplot.py +29 -0
  49. figrecipe/_dev/demo_plotters/line_curve/plot_stairs.py +27 -0
  50. figrecipe/_dev/demo_plotters/line_curve/plot_step.py +27 -0
  51. figrecipe/_dev/demo_plotters/scatter_points/__init__.py +4 -0
  52. figrecipe/_dev/demo_plotters/scatter_points/plot_scatter.py +24 -0
  53. figrecipe/_dev/demo_plotters/special/__init__.py +4 -0
  54. figrecipe/_dev/demo_plotters/special/plot_eventplot.py +25 -0
  55. figrecipe/_dev/demo_plotters/special/plot_loglog.py +27 -0
  56. figrecipe/_dev/demo_plotters/special/plot_pie.py +27 -0
  57. figrecipe/_dev/demo_plotters/special/plot_semilogx.py +27 -0
  58. figrecipe/_dev/demo_plotters/special/plot_semilogy.py +27 -0
  59. figrecipe/_dev/demo_plotters/special/plot_stem.py +27 -0
  60. figrecipe/_dev/demo_plotters/spectral_signal/__init__.py +4 -0
  61. figrecipe/_dev/demo_plotters/spectral_signal/plot_acorr.py +24 -0
  62. figrecipe/_dev/demo_plotters/spectral_signal/plot_angle_spectrum.py +28 -0
  63. figrecipe/_dev/demo_plotters/spectral_signal/plot_cohere.py +29 -0
  64. figrecipe/_dev/demo_plotters/spectral_signal/plot_csd.py +29 -0
  65. figrecipe/_dev/demo_plotters/spectral_signal/plot_magnitude_spectrum.py +28 -0
  66. figrecipe/_dev/demo_plotters/spectral_signal/plot_phase_spectrum.py +28 -0
  67. figrecipe/_dev/demo_plotters/spectral_signal/plot_psd.py +29 -0
  68. figrecipe/_dev/demo_plotters/spectral_signal/plot_specgram.py +30 -0
  69. figrecipe/_dev/demo_plotters/spectral_signal/plot_xcorr.py +25 -0
  70. figrecipe/_dev/demo_plotters/vector_flow/__init__.py +4 -0
  71. figrecipe/_dev/demo_plotters/vector_flow/plot_barbs.py +30 -0
  72. figrecipe/_dev/demo_plotters/vector_flow/plot_quiver.py +30 -0
  73. figrecipe/_dev/demo_plotters/vector_flow/plot_streamplot.py +30 -0
  74. figrecipe/_editor/__init__.py +278 -0
  75. figrecipe/_editor/_bbox/__init__.py +43 -0
  76. figrecipe/_editor/_bbox/_collections.py +177 -0
  77. figrecipe/_editor/_bbox/_elements.py +159 -0
  78. figrecipe/_editor/_bbox/_extract.py +256 -0
  79. figrecipe/_editor/_bbox/_extract_axes.py +370 -0
  80. figrecipe/_editor/_bbox/_extract_text.py +342 -0
  81. figrecipe/_editor/_bbox/_lines.py +173 -0
  82. figrecipe/_editor/_bbox/_transforms.py +146 -0
  83. figrecipe/_editor/_flask_app.py +258 -0
  84. figrecipe/_editor/_helpers.py +242 -0
  85. figrecipe/_editor/_hitmap/__init__.py +76 -0
  86. figrecipe/_editor/_hitmap/_artists/__init__.py +21 -0
  87. figrecipe/_editor/_hitmap/_artists/_collections.py +345 -0
  88. figrecipe/_editor/_hitmap/_artists/_images.py +68 -0
  89. figrecipe/_editor/_hitmap/_artists/_lines.py +107 -0
  90. figrecipe/_editor/_hitmap/_artists/_patches.py +163 -0
  91. figrecipe/_editor/_hitmap/_artists/_text.py +190 -0
  92. figrecipe/_editor/_hitmap/_colors.py +181 -0
  93. figrecipe/_editor/_hitmap/_detect.py +137 -0
  94. figrecipe/_editor/_hitmap/_restore.py +154 -0
  95. figrecipe/_editor/_hitmap_main.py +182 -0
  96. figrecipe/_editor/_overrides.py +318 -0
  97. figrecipe/_editor/_preferences.py +135 -0
  98. figrecipe/_editor/_render_overrides.py +480 -0
  99. figrecipe/_editor/_renderer.py +199 -0
  100. figrecipe/_editor/_routes_axis.py +453 -0
  101. figrecipe/_editor/_routes_core.py +284 -0
  102. figrecipe/_editor/_routes_element.py +317 -0
  103. figrecipe/_editor/_routes_style.py +223 -0
  104. figrecipe/_editor/_templates/__init__.py +152 -0
  105. figrecipe/_editor/_templates/_html.py +502 -0
  106. figrecipe/_editor/_templates/_scripts/__init__.py +120 -0
  107. figrecipe/_editor/_templates/_scripts/_api.py +228 -0
  108. figrecipe/_editor/_templates/_scripts/_colors.py +485 -0
  109. figrecipe/_editor/_templates/_scripts/_core.py +436 -0
  110. figrecipe/_editor/_templates/_scripts/_debug_snapshot.py +186 -0
  111. figrecipe/_editor/_templates/_scripts/_element_editor.py +310 -0
  112. figrecipe/_editor/_templates/_scripts/_files.py +195 -0
  113. figrecipe/_editor/_templates/_scripts/_hitmap.py +509 -0
  114. figrecipe/_editor/_templates/_scripts/_inspector.py +315 -0
  115. figrecipe/_editor/_templates/_scripts/_labels.py +464 -0
  116. figrecipe/_editor/_templates/_scripts/_legend_drag.py +265 -0
  117. figrecipe/_editor/_templates/_scripts/_modals.py +226 -0
  118. figrecipe/_editor/_templates/_scripts/_overlays.py +292 -0
  119. figrecipe/_editor/_templates/_scripts/_panel_drag.py +334 -0
  120. figrecipe/_editor/_templates/_scripts/_panel_position.py +279 -0
  121. figrecipe/_editor/_templates/_scripts/_selection.py +237 -0
  122. figrecipe/_editor/_templates/_scripts/_tabs.py +89 -0
  123. figrecipe/_editor/_templates/_scripts/_view_mode.py +107 -0
  124. figrecipe/_editor/_templates/_scripts/_zoom.py +179 -0
  125. figrecipe/_editor/_templates/_styles/__init__.py +69 -0
  126. figrecipe/_editor/_templates/_styles/_base.py +64 -0
  127. figrecipe/_editor/_templates/_styles/_buttons.py +206 -0
  128. figrecipe/_editor/_templates/_styles/_color_input.py +123 -0
  129. figrecipe/_editor/_templates/_styles/_controls.py +265 -0
  130. figrecipe/_editor/_templates/_styles/_dynamic_props.py +144 -0
  131. figrecipe/_editor/_templates/_styles/_forms.py +126 -0
  132. figrecipe/_editor/_templates/_styles/_hitmap.py +184 -0
  133. figrecipe/_editor/_templates/_styles/_inspector.py +90 -0
  134. figrecipe/_editor/_templates/_styles/_labels.py +118 -0
  135. figrecipe/_editor/_templates/_styles/_modals.py +98 -0
  136. figrecipe/_editor/_templates/_styles/_overlays.py +130 -0
  137. figrecipe/_editor/_templates/_styles/_preview.py +225 -0
  138. figrecipe/_editor/_templates/_styles/_selection.py +73 -0
  139. figrecipe/_params/_DECORATION_METHODS.py +33 -0
  140. figrecipe/_params/_PLOTTING_METHODS.py +58 -0
  141. figrecipe/_params/__init__.py +9 -0
  142. figrecipe/_recorder.py +92 -110
  143. figrecipe/_recorder_utils.py +124 -0
  144. figrecipe/_reproducer/__init__.py +18 -0
  145. figrecipe/_reproducer/_core.py +498 -0
  146. figrecipe/_reproducer/_custom_plots.py +279 -0
  147. figrecipe/_reproducer/_seaborn.py +100 -0
  148. figrecipe/_reproducer/_violin.py +186 -0
  149. figrecipe/_seaborn.py +14 -9
  150. figrecipe/_serializer.py +2 -2
  151. figrecipe/_signatures/README.md +68 -0
  152. figrecipe/_signatures/__init__.py +12 -2
  153. figrecipe/_signatures/_kwargs.py +273 -0
  154. figrecipe/_signatures/_loader.py +114 -57
  155. figrecipe/_signatures/_parsing.py +147 -0
  156. figrecipe/_utils/__init__.py +6 -4
  157. figrecipe/_utils/_crop.py +10 -4
  158. figrecipe/_utils/_image_diff.py +37 -33
  159. figrecipe/_utils/_numpy_io.py +0 -1
  160. figrecipe/_utils/_units.py +11 -3
  161. figrecipe/_validator.py +12 -3
  162. figrecipe/_wrappers/_axes.py +193 -170
  163. figrecipe/_wrappers/_axes_helpers.py +136 -0
  164. figrecipe/_wrappers/_axes_plots.py +418 -0
  165. figrecipe/_wrappers/_axes_seaborn.py +157 -0
  166. figrecipe/_wrappers/_figure.py +277 -18
  167. figrecipe/_wrappers/_panel_labels.py +127 -0
  168. figrecipe/_wrappers/_plot_helpers.py +143 -0
  169. figrecipe/_wrappers/_violin_helpers.py +180 -0
  170. figrecipe/plt.py +0 -1
  171. figrecipe/pyplot.py +2 -1
  172. figrecipe/styles/__init__.py +12 -11
  173. figrecipe/styles/_dotdict.py +72 -0
  174. figrecipe/styles/_finalize.py +134 -0
  175. figrecipe/styles/_fonts.py +77 -0
  176. figrecipe/styles/_kwargs_converter.py +178 -0
  177. figrecipe/styles/_plot_styles.py +209 -0
  178. figrecipe/styles/_style_applier.py +60 -202
  179. figrecipe/styles/_style_loader.py +73 -121
  180. figrecipe/styles/_themes.py +151 -0
  181. figrecipe/styles/presets/MATPLOTLIB.yaml +95 -0
  182. figrecipe/styles/presets/SCITEX.yaml +181 -0
  183. figrecipe-0.7.4.dist-info/METADATA +429 -0
  184. figrecipe-0.7.4.dist-info/RECORD +188 -0
  185. figrecipe/_reproducer.py +0 -358
  186. figrecipe-0.5.0.dist-info/METADATA +0 -336
  187. figrecipe-0.5.0.dist-info/RECORD +0 -26
  188. {figrecipe-0.5.0.dist-info → figrecipe-0.7.4.dist-info}/WHEEL +0 -0
  189. {figrecipe-0.5.0.dist-info → figrecipe-0.7.4.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Plot categories for organized display."""
4
+
5
+ from typing import Dict, List
6
+
7
+ from ._registry import REGISTRY
8
+
9
+ # Plot categories for organized display
10
+ # Keys match directory names in demo_plotters/
11
+ _CATEGORIES_RAW: Dict[str, List[str]] = {
12
+ "line_curve": [
13
+ "plot",
14
+ "step",
15
+ "fill",
16
+ "fill_between",
17
+ "fill_betweenx",
18
+ "errorbar",
19
+ "stackplot",
20
+ "stairs",
21
+ ],
22
+ "scatter_points": ["scatter"],
23
+ "bar_categorical": ["bar", "barh"],
24
+ "distribution": ["hist", "hist2d", "boxplot", "violinplot", "ecdf"],
25
+ "image_matrix": ["imshow", "matshow", "pcolor", "pcolormesh", "hexbin", "spy"],
26
+ "contour_surface": [
27
+ "contour",
28
+ "contourf",
29
+ "tricontour",
30
+ "tricontourf",
31
+ "tripcolor",
32
+ "triplot",
33
+ ],
34
+ "spectral_signal": [
35
+ "specgram",
36
+ "psd",
37
+ "csd",
38
+ "cohere",
39
+ "angle_spectrum",
40
+ "magnitude_spectrum",
41
+ "phase_spectrum",
42
+ "acorr",
43
+ "xcorr",
44
+ ],
45
+ "vector_flow": ["quiver", "barbs", "streamplot"],
46
+ "special": ["pie", "stem", "eventplot", "loglog", "semilogx", "semilogy"],
47
+ }
48
+
49
+ # Display names for categories (for UI/documentation)
50
+ CATEGORY_DISPLAY_NAMES: Dict[str, str] = {
51
+ "line_curve": "Line & Curve",
52
+ "scatter_points": "Scatter & Points",
53
+ "bar_categorical": "Bar & Categorical",
54
+ "distribution": "Distribution",
55
+ "image_matrix": "2D Image & Matrix",
56
+ "contour_surface": "Contour & Surface",
57
+ "spectral_signal": "Spectral & Signal",
58
+ "vector_flow": "Vector & Flow",
59
+ "special": "Special",
60
+ }
61
+
62
+ # Filter categories to only include available plots
63
+ CATEGORIES: Dict[str, List[str]] = {
64
+ cat: [p for p in plots if p in REGISTRY] for cat, plots in _CATEGORIES_RAW.items()
65
+ }
66
+ CATEGORIES = {cat: plots for cat, plots in CATEGORIES.items() if plots}
67
+
68
+ # Representative plots (one per category)
69
+ REPRESENTATIVES: Dict[str, str] = {
70
+ "line_curve": "plot",
71
+ "scatter_points": "scatter",
72
+ "bar_categorical": "bar",
73
+ "distribution": "hist",
74
+ "image_matrix": "imshow",
75
+ "contour_surface": "contourf",
76
+ "spectral_signal": "specgram",
77
+ "vector_flow": "quiver",
78
+ "special": "pie",
79
+ }
80
+
81
+ # EOF
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Figure creation functions for demo plotters."""
4
+
5
+ import math
6
+ from pathlib import Path
7
+ from typing import Dict, Tuple
8
+
9
+ import numpy as np
10
+
11
+ from ._registry import REGISTRY
12
+
13
+
14
+ def create_all_plots_figure(plt, seed: int = 42) -> Tuple:
15
+ """Create a single figure with all supported plot types.
16
+
17
+ Parameters
18
+ ----------
19
+ plt : module
20
+ figrecipe module (import figrecipe as fr).
21
+ seed : int
22
+ Random seed for reproducibility.
23
+
24
+ Returns
25
+ -------
26
+ tuple
27
+ (fig, axes, results) where results maps name to success/error.
28
+ """
29
+ rng = np.random.default_rng(seed)
30
+
31
+ n_plots = len(REGISTRY)
32
+ ncols = 7
33
+ nrows = math.ceil(n_plots / ncols)
34
+
35
+ fig, axes = plt.subplots(nrows=nrows, ncols=ncols)
36
+ axes_flat = axes.flatten()
37
+
38
+ results = {}
39
+ for i, (name, plotter) in enumerate(REGISTRY.items()):
40
+ ax = axes_flat[i]
41
+ try:
42
+ plotter(plt, rng, ax=ax)
43
+ results[name] = {"success": True, "error": None}
44
+ except Exception as e:
45
+ ax.set_title(f"{name}\n(ERROR)")
46
+ ax.text(
47
+ 0.5,
48
+ 0.5,
49
+ str(e)[:50],
50
+ ha="center",
51
+ va="center",
52
+ transform=ax.transAxes,
53
+ fontsize=6,
54
+ wrap=True,
55
+ )
56
+ results[name] = {"success": False, "error": str(e)}
57
+
58
+ # Hide unused axes
59
+ for i in range(n_plots, len(axes_flat)):
60
+ axes_flat[i].set_visible(False)
61
+
62
+ # Add panel labels
63
+ panel_labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" * 2
64
+ for i, ax in enumerate(axes_flat[:n_plots]):
65
+ if i < len(panel_labels):
66
+ plt.panel_label(ax, panel_labels[i])
67
+
68
+ fig.suptitle(f"All {n_plots} Supported Plot Types")
69
+
70
+ return fig, axes, results
71
+
72
+
73
+ def run_individual_demos(plt, output_dir=None, show=False) -> Dict:
74
+ """Run all demo plotters individually and optionally save outputs.
75
+
76
+ Parameters
77
+ ----------
78
+ plt : module
79
+ figrecipe or matplotlib.pyplot module.
80
+ output_dir : Path, optional
81
+ Directory to save output images.
82
+ show : bool
83
+ Whether to show figures.
84
+
85
+ Returns
86
+ -------
87
+ dict
88
+ Results for each demo: {name: {'success': bool, 'error': str or None}}
89
+ """
90
+ rng = np.random.default_rng(42)
91
+ results = {}
92
+
93
+ if output_dir:
94
+ output_dir = Path(output_dir)
95
+ output_dir.mkdir(parents=True, exist_ok=True)
96
+
97
+ for name, plotter in REGISTRY.items():
98
+ try:
99
+ fig, ax = plotter(plt, rng)
100
+ if output_dir:
101
+ out_path = output_dir / f"plot_{name}.png"
102
+ mpl_fig = fig.fig if hasattr(fig, "fig") else fig
103
+ mpl_fig.savefig(out_path, dpi=100, bbox_inches="tight")
104
+ if show:
105
+ plt.show()
106
+ else:
107
+ mpl_fig = fig.fig if hasattr(fig, "fig") else fig
108
+ plt.close(mpl_fig)
109
+ results[name] = {"success": True, "error": None}
110
+ except Exception as e:
111
+ results[name] = {"success": False, "error": str(e)}
112
+
113
+ return results
114
+
115
+
116
+ # Legacy alias
117
+ run_all_demos = run_individual_demos
118
+
119
+ # EOF
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Helper functions for demo plotters."""
4
+
5
+ from typing import Callable, Dict, List, Optional
6
+
7
+ from ._categories import CATEGORIES, REPRESENTATIVES
8
+ from ._registry import REGISTRY
9
+
10
+
11
+ def list_plots() -> List[str]:
12
+ """List all available plot types."""
13
+ return list(REGISTRY.keys())
14
+
15
+
16
+ def list_plots_by_category() -> Dict[str, List[str]]:
17
+ """List all available plot types organized by category."""
18
+ return CATEGORIES.copy()
19
+
20
+
21
+ def get_representative_plots() -> List[str]:
22
+ """Get one representative plot from each category for demos."""
23
+ return [p for p in REPRESENTATIVES.values() if p in REGISTRY]
24
+
25
+
26
+ def get_plotter(name: str) -> Optional[Callable]:
27
+ """Get plotter function by name."""
28
+ return REGISTRY.get(name)
29
+
30
+
31
+ # EOF
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Registry for demo plotter functions."""
4
+
5
+ import importlib
6
+ from pathlib import Path
7
+ from typing import Callable, Dict
8
+
9
+ # Registry: plot_name -> plotter function
10
+ REGISTRY: Dict[str, Callable] = {}
11
+
12
+ # Get demo directory
13
+ _demo_dir = Path(__file__).parent
14
+
15
+ # Category subdirectories
16
+ _category_dirs = [
17
+ "line_curve",
18
+ "scatter_points",
19
+ "bar_categorical",
20
+ "distribution",
21
+ "image_matrix",
22
+ "contour_surface",
23
+ "spectral_signal",
24
+ "vector_flow",
25
+ "special",
26
+ ]
27
+
28
+ # Collect all plot_*.py files from subdirectories
29
+ _demo_files = []
30
+ for _cat_dir in _category_dirs:
31
+ _cat_path = _demo_dir / _cat_dir
32
+ if _cat_path.is_dir():
33
+ _demo_files.extend(sorted(_cat_path.glob("plot_*.py")))
34
+
35
+ # Import all demo functions into registry
36
+ for _file in _demo_files:
37
+ _module_name = _file.stem # e.g., plot_scatter
38
+ _plot_name = _module_name.replace("plot_", "") # e.g., scatter
39
+ _func_name = _module_name # e.g., plot_scatter
40
+ _cat_dir = _file.parent.name # e.g., scatter_points
41
+ try:
42
+ _module = importlib.import_module(
43
+ f".{_cat_dir}.{_module_name}", package=__name__.rsplit(".", 1)[0]
44
+ )
45
+ if hasattr(_module, _func_name):
46
+ REGISTRY[_plot_name] = getattr(_module, _func_name)
47
+ except ImportError as e:
48
+ print(f"Warning: Could not import {_cat_dir}.{_module_name}: {e}")
49
+
50
+ # EOF
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Demo plotters for bar_categorical category."""
4
+
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """bar: bar chart demo."""
4
+
5
+
6
+ def plot_bar(plt, rng, ax=None):
7
+ """Bar chart demo.
8
+
9
+ Demonstrates: ax.bar()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ categories = ["A", "B", "C", "D", "E"]
17
+ values = rng.integers(1, 10, 5)
18
+ ax.bar(categories, values, id="bar")
19
+ ax.set_xlabel("Category")
20
+ ax.set_ylabel("Value")
21
+ ax.set_title("bar")
22
+ return fig, ax
23
+
24
+
25
+ # EOF
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """barh: horizontal bar chart demo."""
4
+
5
+
6
+ def plot_barh(plt, rng, ax=None):
7
+ """Horizontal bar chart demo.
8
+
9
+ Demonstrates: ax.barh()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ categories = ["A", "B", "C", "D", "E"]
17
+ values = rng.integers(1, 10, 5)
18
+ ax.barh(categories, values, id="barh")
19
+ ax.set_xlabel("Value")
20
+ ax.set_ylabel("Category")
21
+ ax.set_title("barh")
22
+ return fig, ax
23
+
24
+
25
+ # EOF
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Demo plotters for contour_surface category."""
4
+
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """contour: contour plot demo."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def plot_contour(plt, rng, ax=None):
9
+ """Contour plot demo.
10
+
11
+ Demonstrates: ax.contour()
12
+ """
13
+ if ax is None:
14
+ fig, ax = plt.subplots()
15
+ else:
16
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
17
+
18
+ x = np.linspace(-3, 3, 50)
19
+ y = np.linspace(-3, 3, 50)
20
+ X, Y = np.meshgrid(x, y)
21
+ Z = np.exp(-(X**2 + Y**2))
22
+ cs = ax.contour(X, Y, Z, id="contour")
23
+ ax.clabel(cs)
24
+ ax.set_xlabel("X")
25
+ ax.set_ylabel("Y")
26
+ ax.set_title("contour")
27
+ return fig, ax
28
+
29
+
30
+ # EOF
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """contourf: filled contour plot demo."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def plot_contourf(plt, rng, ax=None):
9
+ """Filled contour plot demo.
10
+
11
+ Demonstrates: ax.contourf()
12
+ """
13
+ if ax is None:
14
+ fig, ax = plt.subplots()
15
+ else:
16
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
17
+
18
+ x = np.linspace(-3, 3, 50)
19
+ y = np.linspace(-3, 3, 50)
20
+ X, Y = np.meshgrid(x, y)
21
+ Z = np.exp(-(X**2 + Y**2))
22
+ ax.contourf(X, Y, Z, id="contourf")
23
+ ax.set_xlabel("X")
24
+ ax.set_ylabel("Y")
25
+ ax.set_title("contourf")
26
+ return fig, ax
27
+
28
+
29
+ # EOF
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tricontour: triangular contour demo."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def plot_tricontour(plt, rng, ax=None):
9
+ """Triangular contour demo.
10
+
11
+ Demonstrates: ax.tricontour()
12
+ """
13
+ if ax is None:
14
+ fig, ax = plt.subplots()
15
+ else:
16
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
17
+
18
+ x = rng.uniform(0, 1, 50)
19
+ y = rng.uniform(0, 1, 50)
20
+ z = np.sin(x * 2 * np.pi) * np.cos(y * 2 * np.pi)
21
+ ax.tricontour(x, y, z, id="tricontour")
22
+ ax.set_xlabel("X")
23
+ ax.set_ylabel("Y")
24
+ ax.set_title("tricontour")
25
+ return fig, ax
26
+
27
+
28
+ # EOF
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tricontourf: filled triangular contour demo."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def plot_tricontourf(plt, rng, ax=None):
9
+ """Filled triangular contour demo.
10
+
11
+ Demonstrates: ax.tricontourf()
12
+ """
13
+ if ax is None:
14
+ fig, ax = plt.subplots()
15
+ else:
16
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
17
+
18
+ x = rng.uniform(0, 1, 50)
19
+ y = rng.uniform(0, 1, 50)
20
+ z = np.sin(x * 2 * np.pi) * np.cos(y * 2 * np.pi)
21
+ ax.tricontourf(x, y, z, id="tricontourf")
22
+ ax.set_xlabel("X")
23
+ ax.set_ylabel("Y")
24
+ ax.set_title("tricontourf")
25
+ return fig, ax
26
+
27
+
28
+ # EOF
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tripcolor: unstructured triangular grid demo."""
4
+
5
+ import numpy as np
6
+
7
+
8
+ def plot_tripcolor(plt, rng, ax=None):
9
+ """Unstructured triangular grid demo.
10
+
11
+ Demonstrates: ax.tripcolor()
12
+ """
13
+ if ax is None:
14
+ fig, ax = plt.subplots()
15
+ else:
16
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
17
+
18
+ # Create random triangulation
19
+ x = rng.uniform(0, 1, 30)
20
+ y = rng.uniform(0, 1, 30)
21
+ z = np.sin(x * 2 * np.pi) * np.cos(y * 2 * np.pi)
22
+ ax.tripcolor(x, y, z, id="tripcolor")
23
+ ax.set_xlabel("X")
24
+ ax.set_ylabel("Y")
25
+ ax.set_title("tripcolor")
26
+ return fig, ax
27
+
28
+
29
+ # EOF
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """triplot: triangular mesh plot demo."""
4
+
5
+
6
+ def plot_triplot(plt, rng, ax=None):
7
+ """Triangular mesh plot demo.
8
+
9
+ Demonstrates: ax.triplot()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ x = rng.uniform(0, 1, 20)
17
+ y = rng.uniform(0, 1, 20)
18
+ ax.triplot(x, y, id="triplot")
19
+ ax.set_xlabel("X")
20
+ ax.set_ylabel("Y")
21
+ ax.set_title("triplot")
22
+ return fig, ax
23
+
24
+
25
+ # EOF
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Demo plotters for distribution category."""
4
+
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """boxplot: box plot demo."""
4
+
5
+
6
+ def plot_boxplot(plt, rng, ax=None):
7
+ """Box plot demo.
8
+
9
+ Demonstrates: ax.boxplot()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ data = [rng.normal(i, 1, 100) for i in range(4)]
17
+ ax.boxplot(data, tick_labels=["A", "B", "C", "D"], id="boxplot")
18
+ ax.set_xlabel("Group")
19
+ ax.set_ylabel("Value")
20
+ ax.set_title("boxplot")
21
+ return fig, ax
22
+
23
+
24
+ # EOF
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """ecdf: empirical CDF demo."""
4
+
5
+
6
+ def plot_ecdf(plt, rng, ax=None):
7
+ """Empirical CDF demo.
8
+
9
+ Demonstrates: ax.ecdf()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ data = rng.normal(0, 1, 100)
17
+ ax.ecdf(data, id="ecdf")
18
+ ax.set_xlabel("Value")
19
+ ax.set_ylabel("Cumulative Probability")
20
+ ax.set_title("ecdf")
21
+ return fig, ax
22
+
23
+
24
+ # EOF
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """hist: histogram demo."""
4
+
5
+
6
+ def plot_hist(plt, rng, ax=None):
7
+ """Histogram demo.
8
+
9
+ Demonstrates: ax.hist()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ data = rng.normal(0, 1, 500)
17
+ ax.hist(data, bins=30, id="hist")
18
+ ax.set_xlabel("Value")
19
+ ax.set_ylabel("Frequency")
20
+ ax.set_title("hist")
21
+ return fig, ax
22
+
23
+
24
+ # EOF
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """hist2d: 2D histogram demo."""
4
+
5
+
6
+ def plot_hist2d(plt, rng, ax=None):
7
+ """2D histogram demo.
8
+
9
+ Demonstrates: ax.hist2d()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ x = rng.normal(0, 1, 1000)
17
+ y = rng.normal(0, 1, 1000)
18
+ ax.hist2d(x, y, id="hist2d")
19
+ ax.set_xlabel("X")
20
+ ax.set_ylabel("Y")
21
+ ax.set_title("hist2d")
22
+ return fig, ax
23
+
24
+
25
+ # EOF
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """violinplot: violin plot demo."""
4
+
5
+
6
+ def plot_violinplot(plt, rng, ax=None):
7
+ """Violin plot demo.
8
+
9
+ Demonstrates: ax.violinplot()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ data = [rng.normal(i, 1, 100) for i in range(4)]
17
+ # Modern style: show box inside (default from SCITEX style)
18
+ ax.violinplot(data, id="violinplot")
19
+ ax.set_xlabel("Group")
20
+ ax.set_ylabel("Value")
21
+ ax.set_title("violinplot")
22
+ return fig, ax
23
+
24
+
25
+ # EOF
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Demo plotters for image_matrix category."""
4
+
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """hexbin: hexagonal binning demo."""
4
+
5
+
6
+ def plot_hexbin(plt, rng, ax=None):
7
+ """Hexagonal binning demo.
8
+
9
+ Demonstrates: ax.hexbin()
10
+ """
11
+ if ax is None:
12
+ fig, ax = plt.subplots()
13
+ else:
14
+ fig = ax.get_figure() if hasattr(ax, "get_figure") else ax.fig
15
+
16
+ x = rng.normal(0, 1, 1000)
17
+ y = rng.normal(0, 1, 1000)
18
+ ax.hexbin(x, y, id="hexbin")
19
+ ax.set_xlabel("X")
20
+ ax.set_ylabel("Y")
21
+ ax.set_title("hexbin")
22
+ return fig, ax
23
+
24
+
25
+ # EOF