maxplotlibx 0.1.6__tar.gz → 0.1.8__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 (46) hide show
  1. maxplotlibx-0.1.8/PKG-INFO +388 -0
  2. maxplotlibx-0.1.8/README.md +351 -0
  3. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/pyproject.toml +2 -2
  4. maxplotlibx-0.1.8/src/maxplotlib/backends/plotext/figure.py +147 -0
  5. maxplotlibx-0.1.8/src/maxplotlib/canvas/canvas.py +2951 -0
  6. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/subfigure/line_plot.py +1895 -29
  7. maxplotlibx-0.1.8/src/maxplotlib/tests/test_canvas.py +1258 -0
  8. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/tests/test_plot.py +4 -4
  9. maxplotlibx-0.1.8/src/maxplotlib/tests/test_plotext.py +289 -0
  10. maxplotlibx-0.1.8/src/maxplotlib/tests/test_plotly_backend.py +338 -0
  11. maxplotlibx-0.1.8/src/maxplotlib/tests/test_styles_and_colors.py +61 -0
  12. maxplotlibx-0.1.8/src/maxplotlibx.egg-info/PKG-INFO +388 -0
  13. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlibx.egg-info/SOURCES.txt +1 -0
  14. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlibx.egg-info/requires.txt +1 -1
  15. maxplotlibx-0.1.6/PKG-INFO +0 -160
  16. maxplotlibx-0.1.6/README.md +0 -123
  17. maxplotlibx-0.1.6/src/maxplotlib/backends/plotext/figure.py +0 -51
  18. maxplotlibx-0.1.6/src/maxplotlib/canvas/canvas.py +0 -1558
  19. maxplotlibx-0.1.6/src/maxplotlib/tests/test_canvas.py +0 -494
  20. maxplotlibx-0.1.6/src/maxplotlib/tests/test_plotext.py +0 -135
  21. maxplotlibx-0.1.6/src/maxplotlib/tests/test_plotly_backend.py +0 -86
  22. maxplotlibx-0.1.6/src/maxplotlibx.egg-info/PKG-INFO +0 -160
  23. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/LICENSE +0 -0
  24. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/setup.cfg +0 -0
  25. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/__init__.py +0 -0
  26. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/backends/matplotlib/utils.py +0 -0
  27. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/backends/plotext/__init__.py +0 -0
  28. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/backends/plotly/__init__.py +0 -0
  29. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/backends/plotly/utils.py +0 -0
  30. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/canvas/__init__.py +0 -0
  31. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/colors/__init__.py +0 -0
  32. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/colors/colors.py +0 -0
  33. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/linestyle/__init__.py +0 -0
  34. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/linestyle/linestyle.py +0 -0
  35. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/objects/__init__.py +0 -0
  36. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/objects/node.py +0 -0
  37. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/objects/path.py +0 -0
  38. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/subfigure/__init__.py +0 -0
  39. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/subfigure/subfigure.py +0 -0
  40. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/tests/test_flame_chart.py +0 -0
  41. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/tests/test_gantt_chart.py +0 -0
  42. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/tests/test_imports.py +0 -0
  43. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/utils/__init__.py +0 -0
  44. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlib/utils/options.py +0 -0
  45. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlibx.egg-info/dependency_links.txt +0 -0
  46. {maxplotlibx-0.1.6 → maxplotlibx-0.1.8}/src/maxplotlibx.egg-info/top_level.txt +0 -0
@@ -0,0 +1,388 @@
1
+ Metadata-Version: 2.4
2
+ Name: maxplotlibx
3
+ Version: 0.1.8
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<7,>=6.0
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
+ Use `canvas.plot(x, y)` to add data directly to a canvas. When you want
86
+ to explicitly render an already-built canvas, use `canvas.render(...)`.
87
+ The older `canvas.plot(backend=...)` spelling is still supported for
88
+ compatibility, but emits a `FutureWarning`.
89
+
90
+ Add several lines at once with shared styling:
91
+
92
+ ``` python
93
+ canvas.plot_many(
94
+ [(x, np.sin(x)), (x, np.cos(x))],
95
+ labels=["sin(x)", "cos(x)"],
96
+ linewidth=2,
97
+ )
98
+ ```
99
+
100
+ Common figure and axis settings can be grouped with `configure()`:
101
+
102
+ ``` python
103
+ canvas.configure(
104
+ title="Trigonometry",
105
+ xlabel="Angle",
106
+ ylabel="Value",
107
+ grid=True,
108
+ facecolor="whitesmoke",
109
+ )
110
+ ```
111
+
112
+ For Matplotlib-specific customization, pass method calls declaratively.
113
+ Figure methods run once and axes methods run for every subplot,
114
+ providing access to any Matplotlib API without requiring a maxplotlib
115
+ wrapper:
116
+
117
+ ``` python
118
+ canvas.plot(matplotlib_customizations={
119
+ "figure": {
120
+ "suptitle": "My figure",
121
+ },
122
+ "axes": {
123
+ "tick_params": {
124
+ "axis": "both",
125
+ "which": "major",
126
+ "length": 6,
127
+ },
128
+ },
129
+ })
130
+ ```
131
+
132
+ For dynamic customization, the same option also accepts a function:
133
+
134
+ ``` python
135
+ def customize(fig, axes):
136
+ fig.suptitle("My figure")
137
+ for ax in axes.flat:
138
+ ax.tick_params(axis="both", which="major", length=6)
139
+
140
+ canvas.plot(matplotlib_customizations=customize)
141
+ ```
142
+
143
+ ### Axis Label and Tick Styling
144
+
145
+ Axis labels, titles, and tick appearance accept Matplotlib-style keyword
146
+ arguments:
147
+
148
+ ``` python
149
+ canvas.set_xlabel("Time", fontsize=12, fontweight="bold", labelpad=10)
150
+ canvas.set_ylabel("Duration", color="darkblue")
151
+ canvas.set_title("Runtime", fontsize=14, color="navy")
152
+ canvas.tick_params(
153
+ axis="both",
154
+ which="major",
155
+ labelsize=10,
156
+ colors="darkgreen",
157
+ length=6,
158
+ )
159
+ ```
160
+
161
+ Common axis controls and figure-level layout settings are also
162
+ available:
163
+
164
+ ``` python
165
+ canvas.set_facecolor("whitesmoke")
166
+ canvas.set_axisbelow(True)
167
+ canvas.margins(x=0.05, y=0.1)
168
+ canvas.minorticks_on()
169
+ canvas.invert_yaxis()
170
+ canvas.supxlabel("Shared x label")
171
+ canvas.supylabel("Shared y label")
172
+ canvas.subplots_adjust(left=0.15, bottom=0.15)
173
+ canvas.tight_layout()
174
+ ```
175
+
176
+ ### Secondary Y-Axis
177
+
178
+ Use `Canvas.twinx()` to add a second y-axis that shares the primary
179
+ x-axis:
180
+
181
+ ``` python
182
+ twin_canvas, primary = Canvas.subplots()
183
+ secondary = twin_canvas.twinx()
184
+
185
+ primary.plot(x, np.sin(x), color="tab:blue")
186
+ secondary.plot(x, 100 * np.cos(x), color="tab:red")
187
+ primary.set_ylabel("sin(x)", color="tab:blue")
188
+ secondary.set_ylabel("100 cos(x)", color="tab:red")
189
+
190
+ twin_canvas.show()
191
+ ```
192
+
193
+ Secondary y-axes are currently supported by the Matplotlib and Plotly
194
+ backends.
195
+
196
+ ### Plotly field plots and tables
197
+
198
+ Several Matplotlib field and annotation APIs map directly to interactive
199
+ Plotly traces, including pseudocolor plots, sparsity patterns,
200
+ triangular grids, and tables:
201
+
202
+ ``` python
203
+ plotly_canvas, plotly_ax = Canvas.subplots()
204
+ plotly_ax.pcolor(x, x, np.outer(np.sin(x), np.cos(x)))
205
+ plotly_ax.spy([[1, 0, 1], [0, 1, 0], [1, 0, 1]])
206
+ plotly_ax.table(cellText=[["A", "B"], ["1", "2"]])
207
+ plotly_canvas.show(backend="plotly")
208
+ ```
209
+
210
+ Plotly raises `NotImplementedError` for primitives without a faithful
211
+ equivalent instead of silently dropping them. To render the supported
212
+ parts of a mixed canvas, explicitly opt into skipping unsupported
213
+ primitives:
214
+
215
+ ``` python
216
+ plotly_canvas.render(backend="plotly", allow_unsupported=True)
217
+ ```
218
+
219
+ Render the same line graph directly in the terminal with the `plotext`
220
+ backend:
221
+
222
+ ``` python
223
+ terminal_fig = canvas.render(backend="plotext")
224
+ print(terminal_fig.build(keep_colors=False))
225
+ ```
226
+
227
+ Trigonometry
228
+ Runtime
229
+ ┌┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬┐
230
+ 1.00┼ ▞▞ sin(x) ──▗▄▞▀▀▀▀▀▙▄▖────────────┼─────────────────┼─────────────▄▄▀▀▀┤
231
+ │ ▞▞ cos(x) ▄▀▘ │ ▝▀▄ │ │ ▄▞▀ ││
232
+ ││ ▜▄▘ │ ▀▄ │ │ ▄▛ ││
233
+ 0.67┼┼──────▟▀─▀▄──────┼─────────▀▄──────┼─────────────────┼──────▄▀─────────┼┤
234
+ ││ ▄▛ ▝▚▖ │ ▚▖ │ │ ▗▞▘ ││
235
+ 0.33┼┼──▗▞────────▀▖───┼────────────▝▄───┼─────────────────┼───▗▀────────────┼┤
236
+ ││ ▄▀ ▝▚ │ ▚▖ │ │ ▞▘ ││
237
+ │▗▞▘ ▀▖│ ▀▄│ │▗▀ ││
238
+ 0.00┼▞────────────────▝▙────────────────▝▚▖────────────────▟▘────────────────▄┤
239
+ ││ │▜▖ │▀▄ ▗▛│ ▗▞▘│
240
+ ││ │ ▝▙ │ ▝▚ ▟▘ │ ▄▀ ││
241
+ -0.33┼┼─────────────────┼───▚▖────────────┼───▀▖───────▗▞───┼─────────────▞▘──┼┤
242
+ ││ │ ▝▄▖ │ ▝▚ ▗▄▘ │ ▟▀ ││
243
+ -0.67┼┼─────────────────┼──────▀▖─────────┼──────▀▄─▗▀──────┼─────────▄▛──────┼┤
244
+ ││ │ ▝▜▄ │ ▄▛▘ │ ▗▞▘ ││
245
+ ││ │ ▀▄▖ │ ▗▄▀ ▀▄▖ │ ▗▄▀▘ ││
246
+ -1.00┼┼─────────────────┼────────────▝▀▚▄▄▄▄▄▞▀▘───────▝▀▜▄▄▄▄▄▞▀▘────────────┼┤
247
+ └┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼┘
248
+ 0.0 1.6 3.1 4.7 6.3
249
+ Duration Time
250
+
251
+ Or plot with the TikZ backend:
252
+
253
+ ``` python
254
+ canvas.show(backend="tikzfigure")
255
+ ```
256
+
257
+ ![](README_files/figure-commonmark/cell-14-output-1.png)
258
+
259
+ ### Horizontal Subplots with TikZ Backend
260
+
261
+ The tikzfigure backend supports creating side-by-side subplots (1×n
262
+ layouts):
263
+
264
+ ``` python
265
+ x = np.linspace(0, 2 * np.pi, 200)
266
+ canvas, (ax1, ax2) = Canvas.subplots(ncols=2, width="10cm", ratio=0.3)
267
+
268
+ ax1.plot(x, np.sin(x), color="royalblue")
269
+ ax1.set_title("sin(x)")
270
+
271
+ ax2.plot(x, np.cos(x), color="tomato")
272
+ ax2.set_title("cos(x)")
273
+
274
+ canvas.suptitle("Trigonometric Functions")
275
+ canvas.show(backend="tikzfigure") # Generates LaTeX subfigures
276
+ ```
277
+
278
+ <div id="fig-showcase-subplots">
279
+
280
+ <img
281
+ src="README_files/figure-commonmark/fig-showcase-subplots-output-1.png"
282
+ id="fig-showcase-subplots" />
283
+
284
+ Figure 2
285
+
286
+ </div>
287
+
288
+ **Note:** Only horizontal layouts (1×n) are currently supported with the
289
+ tikzfigure backend. Vertical/grid layouts will raise
290
+ `NotImplementedError`. See the tutorials for more examples.
291
+
292
+ ### Terminal Backend with plotext
293
+
294
+ The `plotext` backend is designed for terminal-first workflows. It
295
+ currently supports line plots, scatter plots, bars, filled regions,
296
+ error bars, reference lines, text/annotations, labels/titles, log axes,
297
+ layers, matrix-style `imshow()` rendering, common patches, and
298
+ multi-subplot canvases.
299
+
300
+ ``` python
301
+ x = np.linspace(1, 10, 40)
302
+
303
+ canvas, ax = Canvas.subplots()
304
+ ax.plot(x, np.sqrt(x), color="cyan", label="sqrt(x)")
305
+ ax.errorbar(x[::8], np.sqrt(x[::8]), yerr=0.15, color="yellow", label="samples")
306
+ ax.set_title("Terminal plot")
307
+ ax.set_xlabel("x")
308
+ ax.set_ylabel("y")
309
+ ax.set_xscale("log")
310
+ ax.set_legend(True)
311
+
312
+ canvas.show(backend="plotext")
313
+ ```
314
+
315
+ Terminal plot
316
+ ┌──────────────────────────────────────────────────────────────────────────┐
317
+ 3.16┤ ▞▞ sqrt(x) ▄▞│
318
+ │ │▗▄▞▀ │
319
+ │ ▄┼▘ │
320
+ 2.79┤ ▄▀▀ │
321
+ │ ┼▀▀ │
322
+ 2.42┤ ▗▞▀▀│ │
323
+ │ ▗▞▀▀▘ │
324
+ │ ▗▄┼▄▀▘ │
325
+ 2.04┤ ▗▄▀▘ │ │
326
+ │ ▗▄▞▀▘ │
327
+ │ │ ▄▄▀▀▘ │
328
+ 1.67┤ ▗▄▄┼▀▀ │
329
+ │ ▗▄▄▞▀▀▘ │
330
+ 1.30┤ ▄▄▄▄▀▀▀▘ │
331
+ │ ▄▄▞▀▀ │
332
+ │┼ ▗▄▄▞▀▀▀▀▀ │
333
+ 0.93┤│▀▀▘ │
334
+ └┬─────────────────┬──────────────────┬─────────────────┬─────────────────┬┘
335
+ 1.0 1.8 3.2 5.6 10.0
336
+ y x
337
+
338
+ <maxplotlib.backends.plotext.figure.PlotextFigure at 0x1102a0690>
339
+
340
+ ### Layers
341
+
342
+ <div id="fig-showcase-2">
343
+
344
+ ``` python
345
+ x = np.linspace(0, 2 * np.pi, 200)
346
+
347
+ canvas, ax = Canvas.subplots(width="10cm", ratio=0.55)
348
+
349
+ ax.plot(x, np.sin(x), color="steelblue", label=r"$\sin(x)$", layer=0)
350
+ ax.plot(x, np.cos(x), color="tomato", label=r"$\cos(x)$", layer=1)
351
+ ax.plot(
352
+ x,
353
+ np.sin(x) * np.cos(x),
354
+ color="seagreen",
355
+ label=r"$\sin(x)\cos(x)$",
356
+ linestyle="dashed",
357
+ layer=2,
358
+ )
359
+
360
+ ax.set_xlabel("x")
361
+ ax.set_legend(True)
362
+ ```
363
+
364
+ Figure 3
365
+
366
+ </div>
367
+
368
+ Show layer 0 only, then layers 0 and 1, then everything:
369
+
370
+ ``` python
371
+ canvas.show(layers=[0])
372
+ ```
373
+
374
+ ![](README_files/figure-commonmark/cell-18-output-1.png)
375
+
376
+ (<Figure size 590.551x324.803 with 1 Axes>,
377
+ array([[<Axes: xlabel='x'>]], dtype=object))
378
+
379
+ Show all layers:
380
+
381
+ ``` python
382
+ canvas.show()
383
+ ```
384
+
385
+ ![](README_files/figure-commonmark/cell-19-output-1.png)
386
+
387
+ (<Figure size 590.551x324.803 with 1 Axes>,
388
+ array([[<Axes: xlabel='x'>]], dtype=object))