maxplotlibx 0.1.6__tar.gz → 0.1.7__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 (43) hide show
  1. maxplotlibx-0.1.7/PKG-INFO +360 -0
  2. maxplotlibx-0.1.7/README.md +323 -0
  3. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/pyproject.toml +1 -1
  4. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/canvas/canvas.py +828 -20
  5. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/subfigure/line_plot.py +1463 -20
  6. maxplotlibx-0.1.7/src/maxplotlib/tests/test_canvas.py +951 -0
  7. maxplotlibx-0.1.7/src/maxplotlib/tests/test_plotly_backend.py +338 -0
  8. maxplotlibx-0.1.7/src/maxplotlib/tests/test_styles_and_colors.py +61 -0
  9. maxplotlibx-0.1.7/src/maxplotlibx.egg-info/PKG-INFO +360 -0
  10. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlibx.egg-info/SOURCES.txt +1 -0
  11. maxplotlibx-0.1.6/PKG-INFO +0 -160
  12. maxplotlibx-0.1.6/README.md +0 -123
  13. maxplotlibx-0.1.6/src/maxplotlib/tests/test_canvas.py +0 -494
  14. maxplotlibx-0.1.6/src/maxplotlib/tests/test_plotly_backend.py +0 -86
  15. maxplotlibx-0.1.6/src/maxplotlibx.egg-info/PKG-INFO +0 -160
  16. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/LICENSE +0 -0
  17. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/setup.cfg +0 -0
  18. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/__init__.py +0 -0
  19. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/backends/matplotlib/utils.py +0 -0
  20. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/backends/plotext/__init__.py +0 -0
  21. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/backends/plotext/figure.py +0 -0
  22. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/backends/plotly/__init__.py +0 -0
  23. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/backends/plotly/utils.py +0 -0
  24. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/canvas/__init__.py +0 -0
  25. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/colors/__init__.py +0 -0
  26. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/colors/colors.py +0 -0
  27. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/linestyle/__init__.py +0 -0
  28. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/linestyle/linestyle.py +0 -0
  29. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/objects/__init__.py +0 -0
  30. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/objects/node.py +0 -0
  31. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/objects/path.py +0 -0
  32. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/subfigure/__init__.py +0 -0
  33. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/subfigure/subfigure.py +0 -0
  34. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/tests/test_flame_chart.py +0 -0
  35. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/tests/test_gantt_chart.py +0 -0
  36. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/tests/test_imports.py +0 -0
  37. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/tests/test_plot.py +0 -0
  38. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/tests/test_plotext.py +0 -0
  39. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/utils/__init__.py +0 -0
  40. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlib/utils/options.py +0 -0
  41. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlibx.egg-info/dependency_links.txt +0 -0
  42. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlibx.egg-info/requires.txt +0 -0
  43. {maxplotlibx-0.1.6 → maxplotlibx-0.1.7}/src/maxplotlibx.egg-info/top_level.txt +0 -0
@@ -0,0 +1,360 @@
1
+ Metadata-Version: 2.4
2
+ Name: maxplotlibx
3
+ Version: 0.1.7
4
+ Summary: A reproducible plotting module with various backends and export options.
5
+ Author: Max
6
+ Project-URL: Source, https://github.com/max-models/maxplotlib
7
+ Keywords: matplotlib
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: matplotlib
13
+ Requires-Dist: pint
14
+ Requires-Dist: plotly
15
+ Requires-Dist: plotext
16
+ Requires-Dist: tikzfigure[vis]>=0.3.0
17
+ Provides-Extra: test
18
+ Requires-Dist: pytest; extra == "test"
19
+ Requires-Dist: coverage; extra == "test"
20
+ Provides-Extra: docs
21
+ Requires-Dist: myst-parser; extra == "docs"
22
+ Requires-Dist: sphinx; extra == "docs"
23
+ Requires-Dist: sphinx-rtd-theme; extra == "docs"
24
+ Requires-Dist: nbsphinx; extra == "docs"
25
+ Requires-Dist: ipykernel; extra == "docs"
26
+ Requires-Dist: nbconvert; extra == "docs"
27
+ Provides-Extra: dev
28
+ Requires-Dist: maxplotlibx[docs,test]; extra == "dev"
29
+ Requires-Dist: ruff; extra == "dev"
30
+ Requires-Dist: black[jupyter]; extra == "dev"
31
+ Requires-Dist: isort; extra == "dev"
32
+ Requires-Dist: jupyterlab; extra == "dev"
33
+ Requires-Dist: nbstripout; extra == "dev"
34
+ Requires-Dist: pre-commit; extra == "dev"
35
+ Requires-Dist: pyproject-fmt; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # Maxlotlib
39
+
40
+
41
+ # Maxplotlib
42
+
43
+ A clean, expressive wrapper around **Matplotlib**, **Plotly**,
44
+ **plotext**, and **tikzfigure** for producing publication-quality
45
+ figures with minimal boilerplate. Swap backends without rewriting your
46
+ data — render the same canvas as a crisp PNG, an interactive Plotly
47
+ chart, a terminal-native plotext figure, or camera-ready **TikZ** code
48
+ for LaTeX.
49
+
50
+ ## Install
51
+
52
+ ``` bash
53
+ pip install maxplotlibx
54
+ ```
55
+
56
+ ## Showcase
57
+
58
+ ### Quickstart
59
+
60
+ <div id="fig-showcase-1">
61
+
62
+ ``` python
63
+ import numpy as np
64
+ from maxplotlib import Canvas
65
+
66
+ x = np.linspace(0, 2 * np.pi, 200)
67
+ y = np.sin(x)
68
+
69
+ canvas, ax = Canvas.subplots()
70
+ ax.plot(x, y)
71
+ ```
72
+
73
+ Figure 1
74
+
75
+ </div>
76
+
77
+ Plot the figure with the default (matplotlib) backend:
78
+
79
+ ``` python
80
+ canvas.show()
81
+ ```
82
+
83
+ ![](README_files/figure-commonmark/cell-3-output-1.png)
84
+
85
+ For Matplotlib-specific customization, pass method calls declaratively.
86
+ Figure methods run once and axes methods run for every subplot,
87
+ providing access to any Matplotlib API without requiring a maxplotlib
88
+ wrapper:
89
+
90
+ ``` python
91
+ canvas.plot(matplotlib_customizations={
92
+ "figure": {
93
+ "suptitle": "My figure",
94
+ },
95
+ "axes": {
96
+ "tick_params": {
97
+ "axis": "both",
98
+ "which": "major",
99
+ "length": 6,
100
+ },
101
+ },
102
+ })
103
+ ```
104
+
105
+ For dynamic customization, the same option also accepts a function:
106
+
107
+ ``` python
108
+ def customize(fig, axes):
109
+ fig.suptitle("My figure")
110
+ for ax in axes.flat:
111
+ ax.tick_params(axis="both", which="major", length=6)
112
+
113
+ canvas.plot(matplotlib_customizations=customize)
114
+ ```
115
+
116
+ ### Axis Label and Tick Styling
117
+
118
+ Axis labels, titles, and tick appearance accept Matplotlib-style keyword
119
+ arguments:
120
+
121
+ ``` python
122
+ canvas.set_xlabel("Time", fontsize=12, fontweight="bold", labelpad=10)
123
+ canvas.set_ylabel("Duration", color="darkblue")
124
+ canvas.set_title("Runtime", fontsize=14, color="navy")
125
+ canvas.tick_params(
126
+ axis="both",
127
+ which="major",
128
+ labelsize=10,
129
+ colors="darkgreen",
130
+ length=6,
131
+ )
132
+ ```
133
+
134
+ Common axis controls and figure-level layout settings are also
135
+ available:
136
+
137
+ ``` python
138
+ canvas.set_facecolor("whitesmoke")
139
+ canvas.set_axisbelow(True)
140
+ canvas.margins(x=0.05, y=0.1)
141
+ canvas.minorticks_on()
142
+ canvas.invert_yaxis()
143
+ canvas.supxlabel("Shared x label")
144
+ canvas.supylabel("Shared y label")
145
+ canvas.subplots_adjust(left=0.15, bottom=0.15)
146
+ canvas.tight_layout()
147
+ ```
148
+
149
+ ### Secondary Y-Axis
150
+
151
+ Use `Canvas.twinx()` to add a second y-axis that shares the primary
152
+ x-axis:
153
+
154
+ ``` python
155
+ twin_canvas, primary = Canvas.subplots()
156
+ secondary = twin_canvas.twinx()
157
+
158
+ primary.plot(x, np.sin(x), color="tab:blue")
159
+ secondary.plot(x, 100 * np.cos(x), color="tab:red")
160
+ primary.set_ylabel("sin(x)", color="tab:blue")
161
+ secondary.set_ylabel("100 cos(x)", color="tab:red")
162
+
163
+ twin_canvas.show()
164
+ ```
165
+
166
+ Secondary y-axes are currently supported by the Matplotlib and Plotly
167
+ backends.
168
+
169
+ ### Plotly field plots and tables
170
+
171
+ Several Matplotlib field and annotation APIs map directly to interactive
172
+ Plotly traces, including pseudocolor plots, sparsity patterns,
173
+ triangular grids, and tables:
174
+
175
+ ``` python
176
+ plotly_canvas, plotly_ax = Canvas.subplots()
177
+ plotly_ax.pcolor(x, x, np.outer(np.sin(x), np.cos(x)))
178
+ plotly_ax.spy([[1, 0, 1], [0, 1, 0], [1, 0, 1]])
179
+ plotly_ax.table(cellText=[["A", "B"], ["1", "2"]])
180
+ plotly_canvas.show(backend="plotly")
181
+ ```
182
+
183
+ Plotly raises `NotImplementedError` for primitives without a faithful
184
+ equivalent instead of silently dropping them. To render the supported
185
+ parts of a mixed canvas, explicitly opt into skipping unsupported
186
+ primitives:
187
+
188
+ ``` python
189
+ plotly_canvas.plot(backend="plotly", allow_unsupported=True)
190
+ ```
191
+
192
+ Render the same line graph directly in the terminal with the `plotext`
193
+ backend:
194
+
195
+ ``` python
196
+ terminal_fig = canvas.plot(backend="plotext")
197
+ print(terminal_fig.build(keep_colors=False))
198
+ ```
199
+
200
+ Runtime
201
+ ┌─────────────────────────────────────────────────────────────────────────┐
202
+ 1.00┤ ▗▄▞▀▀▀▀▀▙▄▖ │
203
+ │ ▗▄▀▘ ▝▀▄ │
204
+ │ ▗▞▘ ▀▄ │
205
+ 0.67┤ ▟▀ ▀▄ │
206
+ │ ▄▛ ▚▖ │
207
+ 0.33┤ ▗▞ ▝▄ │
208
+ │ ▄▀ ▚▖ │
209
+ │▗▞▘ ▀▄ │
210
+ 0.00┤▀ ▝▚▖ ▞│
211
+ │ ▀▄ ▗▞▘│
212
+ │ ▝▚ ▄▀ │
213
+ -0.33┤ ▀▖ ▞▘ │
214
+ │ ▝▚ ▟▀ │
215
+ -0.67┤ ▀▄ ▄▛ │
216
+ │ ▀▄ ▗▞▘ │
217
+ │ ▀▄▖ ▗▄▀▘ │
218
+ -1.00┤ ▝▀▜▄▄▄▄▄▞▀▘ │
219
+ └┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬┘
220
+ 0.0 1.6 3.1 4.7 6.3
221
+ Duration Time
222
+
223
+ Or plot with the TikZ backend:
224
+
225
+ ``` python
226
+ canvas.show(backend="tikzfigure")
227
+ ```
228
+
229
+ ![](README_files/figure-commonmark/cell-12-output-1.png)
230
+
231
+ ### Horizontal Subplots with TikZ Backend
232
+
233
+ The tikzfigure backend supports creating side-by-side subplots (1×n
234
+ layouts):
235
+
236
+ ``` python
237
+ x = np.linspace(0, 2 * np.pi, 200)
238
+ canvas, (ax1, ax2) = Canvas.subplots(ncols=2, width="10cm", ratio=0.3)
239
+
240
+ ax1.plot(x, np.sin(x), color="royalblue")
241
+ ax1.set_title("sin(x)")
242
+
243
+ ax2.plot(x, np.cos(x), color="tomato")
244
+ ax2.set_title("cos(x)")
245
+
246
+ canvas.suptitle("Trigonometric Functions")
247
+ canvas.show(backend="tikzfigure") # Generates LaTeX subfigures
248
+ ```
249
+
250
+ <div id="fig-showcase-subplots">
251
+
252
+ <img
253
+ src="README_files/figure-commonmark/fig-showcase-subplots-output-1.png"
254
+ id="fig-showcase-subplots" />
255
+
256
+ Figure 2
257
+
258
+ </div>
259
+
260
+ **Note:** Only horizontal layouts (1×n) are currently supported with the
261
+ tikzfigure backend. Vertical/grid layouts will raise
262
+ `NotImplementedError`. See the tutorials for more examples.
263
+
264
+ ### Terminal Backend with plotext
265
+
266
+ The `plotext` backend is designed for terminal-first workflows. It
267
+ currently supports line plots, scatter plots, bars, filled regions,
268
+ error bars, reference lines, text/annotations, labels/titles, log axes,
269
+ layers, matrix-style `imshow()` rendering, common patches, and
270
+ multi-subplot canvases.
271
+
272
+ ``` python
273
+ x = np.linspace(1, 10, 40)
274
+
275
+ canvas, ax = Canvas.subplots()
276
+ ax.plot(x, np.sqrt(x), color="cyan", label="sqrt(x)")
277
+ ax.errorbar(x[::8], np.sqrt(x[::8]), yerr=0.15, color="yellow", label="samples")
278
+ ax.set_title("Terminal plot")
279
+ ax.set_xlabel("x")
280
+ ax.set_ylabel("y")
281
+ ax.set_xscale("log")
282
+ ax.set_legend(True)
283
+
284
+ canvas.show(backend="plotext")
285
+ ```
286
+
287
+ Terminal plot
288
+ ┌──────────────────────────────────────────────────────────────────────────┐
289
+ 3.16┤ ▞▞ sqrt(x) ▄▞│
290
+ │ │▗▄▞▀ │
291
+ │ ▄┼▘ │
292
+ 2.79┤ ▄▀▀ │
293
+ │ ┼▀▀ │
294
+ 2.42┤ ▗▞▀▀│ │
295
+ │ ▗▞▀▀▘ │
296
+ │ ▗▄┼▄▀▘ │
297
+ 2.04┤ ▗▄▀▘ │ │
298
+ │ ▗▄▞▀▘ │
299
+ │ │ ▄▄▀▀▘ │
300
+ 1.67┤ ▗▄▄┼▀▀ │
301
+ │ ▗▄▄▞▀▀▘ │
302
+ 1.30┤ ▄▄▄▄▀▀▀▘ │
303
+ │ ▄▄▞▀▀ │
304
+ │┼ ▗▄▄▞▀▀▀▀▀ │
305
+ 0.93┤│▀▀▘ │
306
+ └┬─────────────────┬──────────────────┬─────────────────┬─────────────────┬┘
307
+ 1.0 1.8 3.2 5.6 10.0
308
+ y x
309
+
310
+ <maxplotlib.backends.plotext.figure.PlotextFigure at 0x110a30550>
311
+
312
+ ### Layers
313
+
314
+ <div id="fig-showcase-2">
315
+
316
+ ``` python
317
+ x = np.linspace(0, 2 * np.pi, 200)
318
+
319
+ canvas, ax = Canvas.subplots(width="10cm", ratio=0.55)
320
+
321
+ ax.plot(x, np.sin(x), color="steelblue", label=r"$\sin(x)$", layer=0)
322
+ ax.plot(x, np.cos(x), color="tomato", label=r"$\cos(x)$", layer=1)
323
+ ax.plot(
324
+ x,
325
+ np.sin(x) * np.cos(x),
326
+ color="seagreen",
327
+ label=r"$\sin(x)\cos(x)$",
328
+ linestyle="dashed",
329
+ layer=2,
330
+ )
331
+
332
+ ax.set_xlabel("x")
333
+ ax.set_legend(True)
334
+ ```
335
+
336
+ Figure 3
337
+
338
+ </div>
339
+
340
+ Show layer 0 only, then layers 0 and 1, then everything:
341
+
342
+ ``` python
343
+ canvas.show(layers=[0])
344
+ ```
345
+
346
+ ![](README_files/figure-commonmark/cell-16-output-1.png)
347
+
348
+ (<Figure size 590.551x324.803 with 1 Axes>,
349
+ array([[<Axes: xlabel='x'>]], dtype=object))
350
+
351
+ Show all layers:
352
+
353
+ ``` python
354
+ canvas.show()
355
+ ```
356
+
357
+ ![](README_files/figure-commonmark/cell-17-output-1.png)
358
+
359
+ (<Figure size 590.551x324.803 with 1 Axes>,
360
+ array([[<Axes: xlabel='x'>]], dtype=object))
@@ -0,0 +1,323 @@
1
+ # Maxlotlib
2
+
3
+
4
+ # Maxplotlib
5
+
6
+ A clean, expressive wrapper around **Matplotlib**, **Plotly**,
7
+ **plotext**, and **tikzfigure** for producing publication-quality
8
+ figures with minimal boilerplate. Swap backends without rewriting your
9
+ data — render the same canvas as a crisp PNG, an interactive Plotly
10
+ chart, a terminal-native plotext figure, or camera-ready **TikZ** code
11
+ for LaTeX.
12
+
13
+ ## Install
14
+
15
+ ``` bash
16
+ pip install maxplotlibx
17
+ ```
18
+
19
+ ## Showcase
20
+
21
+ ### Quickstart
22
+
23
+ <div id="fig-showcase-1">
24
+
25
+ ``` python
26
+ import numpy as np
27
+ from maxplotlib import Canvas
28
+
29
+ x = np.linspace(0, 2 * np.pi, 200)
30
+ y = np.sin(x)
31
+
32
+ canvas, ax = Canvas.subplots()
33
+ ax.plot(x, y)
34
+ ```
35
+
36
+ Figure 1
37
+
38
+ </div>
39
+
40
+ Plot the figure with the default (matplotlib) backend:
41
+
42
+ ``` python
43
+ canvas.show()
44
+ ```
45
+
46
+ ![](README_files/figure-commonmark/cell-3-output-1.png)
47
+
48
+ For Matplotlib-specific customization, pass method calls declaratively.
49
+ Figure methods run once and axes methods run for every subplot,
50
+ providing access to any Matplotlib API without requiring a maxplotlib
51
+ wrapper:
52
+
53
+ ``` python
54
+ canvas.plot(matplotlib_customizations={
55
+ "figure": {
56
+ "suptitle": "My figure",
57
+ },
58
+ "axes": {
59
+ "tick_params": {
60
+ "axis": "both",
61
+ "which": "major",
62
+ "length": 6,
63
+ },
64
+ },
65
+ })
66
+ ```
67
+
68
+ For dynamic customization, the same option also accepts a function:
69
+
70
+ ``` python
71
+ def customize(fig, axes):
72
+ fig.suptitle("My figure")
73
+ for ax in axes.flat:
74
+ ax.tick_params(axis="both", which="major", length=6)
75
+
76
+ canvas.plot(matplotlib_customizations=customize)
77
+ ```
78
+
79
+ ### Axis Label and Tick Styling
80
+
81
+ Axis labels, titles, and tick appearance accept Matplotlib-style keyword
82
+ arguments:
83
+
84
+ ``` python
85
+ canvas.set_xlabel("Time", fontsize=12, fontweight="bold", labelpad=10)
86
+ canvas.set_ylabel("Duration", color="darkblue")
87
+ canvas.set_title("Runtime", fontsize=14, color="navy")
88
+ canvas.tick_params(
89
+ axis="both",
90
+ which="major",
91
+ labelsize=10,
92
+ colors="darkgreen",
93
+ length=6,
94
+ )
95
+ ```
96
+
97
+ Common axis controls and figure-level layout settings are also
98
+ available:
99
+
100
+ ``` python
101
+ canvas.set_facecolor("whitesmoke")
102
+ canvas.set_axisbelow(True)
103
+ canvas.margins(x=0.05, y=0.1)
104
+ canvas.minorticks_on()
105
+ canvas.invert_yaxis()
106
+ canvas.supxlabel("Shared x label")
107
+ canvas.supylabel("Shared y label")
108
+ canvas.subplots_adjust(left=0.15, bottom=0.15)
109
+ canvas.tight_layout()
110
+ ```
111
+
112
+ ### Secondary Y-Axis
113
+
114
+ Use `Canvas.twinx()` to add a second y-axis that shares the primary
115
+ x-axis:
116
+
117
+ ``` python
118
+ twin_canvas, primary = Canvas.subplots()
119
+ secondary = twin_canvas.twinx()
120
+
121
+ primary.plot(x, np.sin(x), color="tab:blue")
122
+ secondary.plot(x, 100 * np.cos(x), color="tab:red")
123
+ primary.set_ylabel("sin(x)", color="tab:blue")
124
+ secondary.set_ylabel("100 cos(x)", color="tab:red")
125
+
126
+ twin_canvas.show()
127
+ ```
128
+
129
+ Secondary y-axes are currently supported by the Matplotlib and Plotly
130
+ backends.
131
+
132
+ ### Plotly field plots and tables
133
+
134
+ Several Matplotlib field and annotation APIs map directly to interactive
135
+ Plotly traces, including pseudocolor plots, sparsity patterns,
136
+ triangular grids, and tables:
137
+
138
+ ``` python
139
+ plotly_canvas, plotly_ax = Canvas.subplots()
140
+ plotly_ax.pcolor(x, x, np.outer(np.sin(x), np.cos(x)))
141
+ plotly_ax.spy([[1, 0, 1], [0, 1, 0], [1, 0, 1]])
142
+ plotly_ax.table(cellText=[["A", "B"], ["1", "2"]])
143
+ plotly_canvas.show(backend="plotly")
144
+ ```
145
+
146
+ Plotly raises `NotImplementedError` for primitives without a faithful
147
+ equivalent instead of silently dropping them. To render the supported
148
+ parts of a mixed canvas, explicitly opt into skipping unsupported
149
+ primitives:
150
+
151
+ ``` python
152
+ plotly_canvas.plot(backend="plotly", allow_unsupported=True)
153
+ ```
154
+
155
+ Render the same line graph directly in the terminal with the `plotext`
156
+ backend:
157
+
158
+ ``` python
159
+ terminal_fig = canvas.plot(backend="plotext")
160
+ print(terminal_fig.build(keep_colors=False))
161
+ ```
162
+
163
+ Runtime
164
+ ┌─────────────────────────────────────────────────────────────────────────┐
165
+ 1.00┤ ▗▄▞▀▀▀▀▀▙▄▖ │
166
+ │ ▗▄▀▘ ▝▀▄ │
167
+ │ ▗▞▘ ▀▄ │
168
+ 0.67┤ ▟▀ ▀▄ │
169
+ │ ▄▛ ▚▖ │
170
+ 0.33┤ ▗▞ ▝▄ │
171
+ │ ▄▀ ▚▖ │
172
+ │▗▞▘ ▀▄ │
173
+ 0.00┤▀ ▝▚▖ ▞│
174
+ │ ▀▄ ▗▞▘│
175
+ │ ▝▚ ▄▀ │
176
+ -0.33┤ ▀▖ ▞▘ │
177
+ │ ▝▚ ▟▀ │
178
+ -0.67┤ ▀▄ ▄▛ │
179
+ │ ▀▄ ▗▞▘ │
180
+ │ ▀▄▖ ▗▄▀▘ │
181
+ -1.00┤ ▝▀▜▄▄▄▄▄▞▀▘ │
182
+ └┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬┘
183
+ 0.0 1.6 3.1 4.7 6.3
184
+ Duration Time
185
+
186
+ Or plot with the TikZ backend:
187
+
188
+ ``` python
189
+ canvas.show(backend="tikzfigure")
190
+ ```
191
+
192
+ ![](README_files/figure-commonmark/cell-12-output-1.png)
193
+
194
+ ### Horizontal Subplots with TikZ Backend
195
+
196
+ The tikzfigure backend supports creating side-by-side subplots (1×n
197
+ layouts):
198
+
199
+ ``` python
200
+ x = np.linspace(0, 2 * np.pi, 200)
201
+ canvas, (ax1, ax2) = Canvas.subplots(ncols=2, width="10cm", ratio=0.3)
202
+
203
+ ax1.plot(x, np.sin(x), color="royalblue")
204
+ ax1.set_title("sin(x)")
205
+
206
+ ax2.plot(x, np.cos(x), color="tomato")
207
+ ax2.set_title("cos(x)")
208
+
209
+ canvas.suptitle("Trigonometric Functions")
210
+ canvas.show(backend="tikzfigure") # Generates LaTeX subfigures
211
+ ```
212
+
213
+ <div id="fig-showcase-subplots">
214
+
215
+ <img
216
+ src="README_files/figure-commonmark/fig-showcase-subplots-output-1.png"
217
+ id="fig-showcase-subplots" />
218
+
219
+ Figure 2
220
+
221
+ </div>
222
+
223
+ **Note:** Only horizontal layouts (1×n) are currently supported with the
224
+ tikzfigure backend. Vertical/grid layouts will raise
225
+ `NotImplementedError`. See the tutorials for more examples.
226
+
227
+ ### Terminal Backend with plotext
228
+
229
+ The `plotext` backend is designed for terminal-first workflows. It
230
+ currently supports line plots, scatter plots, bars, filled regions,
231
+ error bars, reference lines, text/annotations, labels/titles, log axes,
232
+ layers, matrix-style `imshow()` rendering, common patches, and
233
+ multi-subplot canvases.
234
+
235
+ ``` python
236
+ x = np.linspace(1, 10, 40)
237
+
238
+ canvas, ax = Canvas.subplots()
239
+ ax.plot(x, np.sqrt(x), color="cyan", label="sqrt(x)")
240
+ ax.errorbar(x[::8], np.sqrt(x[::8]), yerr=0.15, color="yellow", label="samples")
241
+ ax.set_title("Terminal plot")
242
+ ax.set_xlabel("x")
243
+ ax.set_ylabel("y")
244
+ ax.set_xscale("log")
245
+ ax.set_legend(True)
246
+
247
+ canvas.show(backend="plotext")
248
+ ```
249
+
250
+ Terminal plot
251
+ ┌──────────────────────────────────────────────────────────────────────────┐
252
+ 3.16┤ ▞▞ sqrt(x) ▄▞│
253
+ │ │▗▄▞▀ │
254
+ │ ▄┼▘ │
255
+ 2.79┤ ▄▀▀ │
256
+ │ ┼▀▀ │
257
+ 2.42┤ ▗▞▀▀│ │
258
+ │ ▗▞▀▀▘ │
259
+ │ ▗▄┼▄▀▘ │
260
+ 2.04┤ ▗▄▀▘ │ │
261
+ │ ▗▄▞▀▘ │
262
+ │ │ ▄▄▀▀▘ │
263
+ 1.67┤ ▗▄▄┼▀▀ │
264
+ │ ▗▄▄▞▀▀▘ │
265
+ 1.30┤ ▄▄▄▄▀▀▀▘ │
266
+ │ ▄▄▞▀▀ │
267
+ │┼ ▗▄▄▞▀▀▀▀▀ │
268
+ 0.93┤│▀▀▘ │
269
+ └┬─────────────────┬──────────────────┬─────────────────┬─────────────────┬┘
270
+ 1.0 1.8 3.2 5.6 10.0
271
+ y x
272
+
273
+ <maxplotlib.backends.plotext.figure.PlotextFigure at 0x110a30550>
274
+
275
+ ### Layers
276
+
277
+ <div id="fig-showcase-2">
278
+
279
+ ``` python
280
+ x = np.linspace(0, 2 * np.pi, 200)
281
+
282
+ canvas, ax = Canvas.subplots(width="10cm", ratio=0.55)
283
+
284
+ ax.plot(x, np.sin(x), color="steelblue", label=r"$\sin(x)$", layer=0)
285
+ ax.plot(x, np.cos(x), color="tomato", label=r"$\cos(x)$", layer=1)
286
+ ax.plot(
287
+ x,
288
+ np.sin(x) * np.cos(x),
289
+ color="seagreen",
290
+ label=r"$\sin(x)\cos(x)$",
291
+ linestyle="dashed",
292
+ layer=2,
293
+ )
294
+
295
+ ax.set_xlabel("x")
296
+ ax.set_legend(True)
297
+ ```
298
+
299
+ Figure 3
300
+
301
+ </div>
302
+
303
+ Show layer 0 only, then layers 0 and 1, then everything:
304
+
305
+ ``` python
306
+ canvas.show(layers=[0])
307
+ ```
308
+
309
+ ![](README_files/figure-commonmark/cell-16-output-1.png)
310
+
311
+ (<Figure size 590.551x324.803 with 1 Axes>,
312
+ array([[<Axes: xlabel='x'>]], dtype=object))
313
+
314
+ Show all layers:
315
+
316
+ ``` python
317
+ canvas.show()
318
+ ```
319
+
320
+ ![](README_files/figure-commonmark/cell-17-output-1.png)
321
+
322
+ (<Figure size 590.551x324.803 with 1 Axes>,
323
+ array([[<Axes: xlabel='x'>]], dtype=object))
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maxplotlibx"
7
- version = "0.1.6"
7
+ version = "0.1.7"
8
8
  description = "A reproducible plotting module with various backends and export options."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"