plotlet 0.4.0__tar.gz → 0.6.0__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.
- plotlet-0.6.0/PKG-INFO +95 -0
- plotlet-0.6.0/README.md +58 -0
- {plotlet-0.4.0 → plotlet-0.6.0}/pyproject.toml +21 -5
- plotlet-0.6.0/src/plotlet/__init__.py +71 -0
- plotlet-0.6.0/src/plotlet/_coord_registry.py +50 -0
- plotlet-0.6.0/src/plotlet/_datasets/anscombe.csv +45 -0
- plotlet-0.6.0/src/plotlet/_datasets/flights.csv +145 -0
- plotlet-0.6.0/src/plotlet/_datasets/penguins.csv +345 -0
- plotlet-0.6.0/src/plotlet/_datasets/tips.csv +245 -0
- plotlet-0.6.0/src/plotlet/_ir.py +452 -0
- plotlet-0.6.0/src/plotlet/_journal.py +377 -0
- plotlet-0.6.0/src/plotlet/_json_layer.py +144 -0
- plotlet-0.6.0/src/plotlet/_regions.py +143 -0
- plotlet-0.6.0/src/plotlet/_spec.py +147 -0
- plotlet-0.6.0/src/plotlet/_splits.py +105 -0
- plotlet-0.6.0/src/plotlet/_tree.py +113 -0
- plotlet-0.6.0/src/plotlet/artists/__init__.py +53 -0
- plotlet-0.6.0/src/plotlet/artists/_marching.py +140 -0
- plotlet-0.6.0/src/plotlet/artists/_shared.py +204 -0
- plotlet-0.6.0/src/plotlet/artists/bar.py +421 -0
- plotlet-0.6.0/src/plotlet/artists/boxplot.py +264 -0
- plotlet-0.6.0/src/plotlet/artists/contour.py +165 -0
- plotlet-0.6.0/src/plotlet/artists/dendrogram.py +249 -0
- plotlet-0.6.0/src/plotlet/artists/density_1d.py +127 -0
- plotlet-0.6.0/src/plotlet/artists/ecdf.py +111 -0
- plotlet-0.6.0/src/plotlet/artists/errorbar.py +263 -0
- plotlet-0.6.0/src/plotlet/artists/fills.py +218 -0
- plotlet-0.6.0/src/plotlet/artists/freqpoly.py +137 -0
- plotlet-0.6.0/src/plotlet/artists/heatmap.py +704 -0
- plotlet-0.6.0/src/plotlet/artists/hexbin.py +148 -0
- plotlet-0.6.0/src/plotlet/artists/hist.py +367 -0
- plotlet-0.6.0/src/plotlet/artists/hist2d.py +180 -0
- plotlet-0.6.0/src/plotlet/artists/imshow.py +237 -0
- plotlet-0.6.0/src/plotlet/artists/kde_2d.py +230 -0
- plotlet-0.6.0/src/plotlet/artists/line.py +275 -0
- plotlet-0.6.0/src/plotlet/artists/pointplot.py +140 -0
- plotlet-0.6.0/src/plotlet/artists/qq.py +129 -0
- plotlet-0.6.0/src/plotlet/artists/references.py +367 -0
- plotlet-0.6.0/src/plotlet/artists/regression.py +446 -0
- plotlet-0.6.0/src/plotlet/artists/ridge.py +142 -0
- plotlet-0.6.0/src/plotlet/artists/rug.py +102 -0
- plotlet-0.6.0/src/plotlet/artists/scatter.py +434 -0
- plotlet-0.6.0/src/plotlet/artists/shapes.py +185 -0
- plotlet-0.6.0/src/plotlet/artists/strip.py +169 -0
- plotlet-0.6.0/src/plotlet/artists/swarm.py +178 -0
- plotlet-0.6.0/src/plotlet/artists/text.py +297 -0
- plotlet-0.6.0/src/plotlet/artists/violin.py +241 -0
- plotlet-0.6.0/src/plotlet/chart.py +1195 -0
- plotlet-0.6.0/src/plotlet/cluster.py +440 -0
- plotlet-0.6.0/src/plotlet/datasets.py +107 -0
- plotlet-0.6.0/src/plotlet/draw/__init__.py +41 -0
- plotlet-0.6.0/src/plotlet/draw/_css_colors.py +159 -0
- plotlet-0.6.0/src/plotlet/draw/_png.py +78 -0
- plotlet-0.6.0/src/plotlet/draw/colormaps.py +219 -0
- plotlet-0.6.0/src/plotlet/draw/colors.py +172 -0
- plotlet-0.6.0/src/plotlet/draw/font.py +352 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/Arimo-Bold.ttf +0 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/Arimo-BoldItalic.ttf +0 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/Arimo-Italic.ttf +0 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/Arimo-Regular.ttf +0 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/DejaVuSans-Bold.ttf +0 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/DejaVuSans-BoldOblique.ttf +0 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/DejaVuSans-Oblique.ttf +0 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/LICENSE-Arimo.txt +93 -0
- plotlet-0.6.0/src/plotlet/draw/fonts/LICENSE-DejaVuSans.txt +99 -0
- plotlet-0.6.0/src/plotlet/draw/format.py +34 -0
- plotlet-0.6.0/src/plotlet/draw/linestyles.py +27 -0
- plotlet-0.6.0/src/plotlet/draw/primitives.py +687 -0
- plotlet-0.6.0/src/plotlet/extensions/annotation_strip.py +675 -0
- plotlet-0.6.0/src/plotlet/extensions/chord_links.py +209 -0
- plotlet-0.6.0/src/plotlet/extensions/chord_ribbon.py +318 -0
- plotlet-0.6.0/src/plotlet/extensions/curved_tree.py +244 -0
- plotlet-0.6.0/src/plotlet/extensions/numeric_bar.py +109 -0
- plotlet-0.6.0/src/plotlet/facet.py +245 -0
- plotlet-0.6.0/src/plotlet/formatters.py +164 -0
- plotlet-0.6.0/src/plotlet/layout_diagram.py +316 -0
- plotlet-0.6.0/src/plotlet/legend.py +120 -0
- plotlet-0.6.0/src/plotlet/lint.py +130 -0
- plotlet-0.6.0/src/plotlet/registry.py +324 -0
- plotlet-0.6.0/src/plotlet/render/__init__.py +77 -0
- plotlet-0.6.0/src/plotlet/render/_attachments.py +296 -0
- plotlet-0.6.0/src/plotlet/render/_chrome.py +953 -0
- plotlet-0.6.0/src/plotlet/render/_chrome_circular.py +360 -0
- plotlet-0.6.0/src/plotlet/render/_layout_engine.py +1427 -0
- plotlet-0.6.0/src/plotlet/render/_legend.py +645 -0
- plotlet-0.6.0/src/plotlet/render/_nodes.py +521 -0
- plotlet-0.6.0/src/plotlet/render/_validate.py +289 -0
- plotlet-0.6.0/src/plotlet/render/coordinates.py +697 -0
- plotlet-0.6.0/src/plotlet/render/core.py +2100 -0
- plotlet-0.6.0/src/plotlet/render/resolved.py +717 -0
- plotlet-0.6.0/src/plotlet/scales.py +576 -0
- plotlet-0.6.0/src/plotlet/sectors.py +330 -0
- plotlet-0.6.0/src/plotlet/spec.json +135 -0
- plotlet-0.6.0/src/plotlet/themes/dark.json +24 -0
- plotlet-0.6.0/src/plotlet/themes/minimal.json +26 -0
- plotlet-0.6.0/src/plotlet/themes/void.json +15 -0
- plotlet-0.6.0/src/plotlet/themes.py +99 -0
- plotlet-0.6.0/src/plotlet/utils.py +626 -0
- plotlet-0.6.0/src/plotlet.egg-info/PKG-INFO +95 -0
- plotlet-0.6.0/src/plotlet.egg-info/SOURCES.txt +129 -0
- plotlet-0.6.0/src/plotlet.egg-info/requires.txt +14 -0
- plotlet-0.6.0/tests/test_attachments.py +287 -0
- plotlet-0.6.0/tests/test_chart.py +3594 -0
- plotlet-0.6.0/tests/test_circular_coordinate.py +581 -0
- plotlet-0.6.0/tests/test_cluster.py +67 -0
- plotlet-0.6.0/tests/test_colors.py +247 -0
- plotlet-0.6.0/tests/test_datasets.py +53 -0
- plotlet-0.6.0/tests/test_extensions.py +40 -0
- plotlet-0.6.0/tests/test_fonts.py +310 -0
- plotlet-0.6.0/tests/test_formatters.py +64 -0
- plotlet-0.6.0/tests/test_help.py +25 -0
- plotlet-0.6.0/tests/test_import_boundary.py +149 -0
- plotlet-0.6.0/tests/test_io.py +61 -0
- plotlet-0.6.0/tests/test_ir.py +265 -0
- plotlet-0.6.0/tests/test_ir_resolved.py +289 -0
- plotlet-0.6.0/tests/test_ir_validate.py +318 -0
- plotlet-0.6.0/tests/test_journal_roundtrip.py +127 -0
- {plotlet-0.4.0 → plotlet-0.6.0}/tests/test_layout_diagram.py +17 -15
- plotlet-0.6.0/tests/test_legend.py +288 -0
- plotlet-0.6.0/tests/test_lint.py +23 -0
- plotlet-0.6.0/tests/test_record_signatures.py +75 -0
- plotlet-0.6.0/tests/test_sectors.py +393 -0
- plotlet-0.6.0/tests/test_subplots.py +564 -0
- plotlet-0.6.0/tests/test_themes.py +89 -0
- {plotlet-0.4.0 → plotlet-0.6.0}/tests/test_units.py +32 -29
- plotlet-0.4.0/PKG-INFO +0 -176
- plotlet-0.4.0/README.md +0 -146
- plotlet-0.4.0/src/plotlet/__init__.py +0 -33
- plotlet-0.4.0/src/plotlet/_png.py +0 -38
- plotlet-0.4.0/src/plotlet/_spec.py +0 -23
- plotlet-0.4.0/src/plotlet/artists.py +0 -503
- plotlet-0.4.0/src/plotlet/builtin_artists.py +0 -570
- plotlet-0.4.0/src/plotlet/chart.py +0 -718
- plotlet-0.4.0/src/plotlet/colormaps.py +0 -113
- plotlet-0.4.0/src/plotlet/colors.py +0 -20
- plotlet-0.4.0/src/plotlet/core.py +0 -1055
- plotlet-0.4.0/src/plotlet/dendrogram.py +0 -197
- plotlet-0.4.0/src/plotlet/font.py +0 -63
- plotlet-0.4.0/src/plotlet/layout.py +0 -896
- plotlet-0.4.0/src/plotlet/layout_diagram.py +0 -237
- plotlet-0.4.0/src/plotlet/legend.py +0 -367
- plotlet-0.4.0/src/plotlet/registry.py +0 -97
- plotlet-0.4.0/src/plotlet/scales.py +0 -123
- plotlet-0.4.0/src/plotlet/spec.json +0 -100
- plotlet-0.4.0/src/plotlet.egg-info/PKG-INFO +0 -176
- plotlet-0.4.0/src/plotlet.egg-info/SOURCES.txt +0 -32
- plotlet-0.4.0/src/plotlet.egg-info/requires.txt +0 -6
- plotlet-0.4.0/tests/test_chart.py +0 -564
- plotlet-0.4.0/tests/test_legend.py +0 -146
- plotlet-0.4.0/tests/test_subplots.py +0 -385
- {plotlet-0.4.0 → plotlet-0.6.0}/LICENSE +0 -0
- {plotlet-0.4.0 → plotlet-0.6.0}/setup.cfg +0 -0
- {plotlet-0.4.0/src/plotlet → plotlet-0.6.0/src/plotlet/draw}/_cm_data.py +0 -0
- {plotlet-0.4.0/src/plotlet → plotlet-0.6.0/src/plotlet/draw}/fonts/DejaVuSans.ttf +0 -0
- {plotlet-0.4.0 → plotlet-0.6.0}/src/plotlet.egg-info/dependency_links.txt +0 -0
- {plotlet-0.4.0 → plotlet-0.6.0}/src/plotlet.egg-info/top_level.txt +0 -0
plotlet-0.6.0/PKG-INFO
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plotlet
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Python library for reproducible, multi-panel scientific figures, with byte-identical output across machines and an extension API for custom plot types.
|
|
5
|
+
Author: gitbamboo42
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/gitbamboo42/plotlet
|
|
8
|
+
Project-URL: Repository, https://github.com/gitbamboo42/plotlet
|
|
9
|
+
Project-URL: Issues, https://github.com/gitbamboo42/plotlet/issues
|
|
10
|
+
Keywords: plot,svg,scientific,visualization,jupyter,reproducible
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
21
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: fonttools>=4.0
|
|
26
|
+
Requires-Dist: scipy>=1.10
|
|
27
|
+
Requires-Dist: resvg_py>=0.3
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: jupyter; extra == "dev"
|
|
30
|
+
Requires-Dist: nbconvert; extra == "dev"
|
|
31
|
+
Provides-Extra: test
|
|
32
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
33
|
+
Requires-Dist: pandas; extra == "test"
|
|
34
|
+
Provides-Extra: pdf
|
|
35
|
+
Requires-Dist: cairosvg; extra == "pdf"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# plotlet
|
|
39
|
+
|
|
40
|
+
plotlet is a Python library for reproducible, multi-panel scientific figures. Byte-identical output across machines, a standard plotting vocabulary, and a first-class extension story for custom plot types.
|
|
41
|
+
|
|
42
|
+
## Documentation
|
|
43
|
+
|
|
44
|
+
Hands-on tour with executable examples:
|
|
45
|
+
|
|
46
|
+
- [notebooks/00_introduction.ipynb](notebooks/00_introduction.ipynb) — long-form data, aesthetic inheritance, layering, composition (more topic notebooks in [`notebooks/`](notebooks/))
|
|
47
|
+
|
|
48
|
+
Reference docs in [`docs/`](docs/):
|
|
49
|
+
|
|
50
|
+
- [API reference](docs/API.md) — mark methods, frame options, scales, tick overrides
|
|
51
|
+
- [Philosophy](docs/PHILOSOPHY.md) — what's in core, what's not, and why
|
|
52
|
+
- [Subplots](docs/SUBPLOTS.md) — multi-panel composition, shared scales
|
|
53
|
+
- [Coordinates](docs/COORDINATES.md) — Circular, custom non-Cartesian projections
|
|
54
|
+
- [Extending](docs/EXTENDING.md) — write your own plot type
|
|
55
|
+
- [Themes](docs/THEMES.md) — visual presets
|
|
56
|
+
- [AI attributes](docs/AI_ATTRS.md) — `data-plotlet-*` schema for automation
|
|
57
|
+
|
|
58
|
+
Reference plot types beyond the standard vocabulary ship in the separate [`plotlet-extensions`](https://github.com/gitbamboo42/plotlet-extensions) package (single-file artists — sankey, alluvial, raincloud, upset_plot, …; `pip install plotlet-extensions`, then `import plotlet.extensions.<name>`) and in the [`plotlet-cookbook`](https://github.com/gitbamboo42/plotlet-cookbook) repo (multi-file, domain-specific projects). A few extensions the core tests depend on still ship in core under [`src/plotlet/extensions/`](src/plotlet/extensions/).
|
|
59
|
+
|
|
60
|
+
## For AI assistants
|
|
61
|
+
|
|
62
|
+
Compact, vendor-neutral onboarding docs live in [`skills/`](skills/):
|
|
63
|
+
|
|
64
|
+
- [`skills/users.md`](skills/users.md) — for AI tools generating plotlet code on a user's behalf.
|
|
65
|
+
- [`skills/developers.md`](skills/developers.md) — for AI (or human) contributors working on plotlet itself. Symlink as `CLAUDE.md` / `.cursorrules` / `AGENTS.md` as your tool expects.
|
|
66
|
+
|
|
67
|
+
## Dependencies
|
|
68
|
+
|
|
69
|
+
plotlet supports Python 3.10+.
|
|
70
|
+
|
|
71
|
+
Required: `fonttools`, `scipy` (regression, qq, CI error bands, clustering/dendrogram), `resvg_py` (PNG rendering — prebuilt wheels, no system libraries). numpy / pandas / polars inputs work transparently.
|
|
72
|
+
|
|
73
|
+
Optional: `cairosvg` for PDF export (`pip install plotlet[pdf]`).
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install plotlet
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Testing
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install -e ".[test]"
|
|
85
|
+
pytest tests/ # check vs. committed baselines
|
|
86
|
+
pytest tests/ --update # regenerate (review the diff!)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Development
|
|
90
|
+
|
|
91
|
+
Development takes place on GitHub. Please submit bugs to the issue tracker with a reproducible example.
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT
|
plotlet-0.6.0/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# plotlet
|
|
2
|
+
|
|
3
|
+
plotlet is a Python library for reproducible, multi-panel scientific figures. Byte-identical output across machines, a standard plotting vocabulary, and a first-class extension story for custom plot types.
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
Hands-on tour with executable examples:
|
|
8
|
+
|
|
9
|
+
- [notebooks/00_introduction.ipynb](notebooks/00_introduction.ipynb) — long-form data, aesthetic inheritance, layering, composition (more topic notebooks in [`notebooks/`](notebooks/))
|
|
10
|
+
|
|
11
|
+
Reference docs in [`docs/`](docs/):
|
|
12
|
+
|
|
13
|
+
- [API reference](docs/API.md) — mark methods, frame options, scales, tick overrides
|
|
14
|
+
- [Philosophy](docs/PHILOSOPHY.md) — what's in core, what's not, and why
|
|
15
|
+
- [Subplots](docs/SUBPLOTS.md) — multi-panel composition, shared scales
|
|
16
|
+
- [Coordinates](docs/COORDINATES.md) — Circular, custom non-Cartesian projections
|
|
17
|
+
- [Extending](docs/EXTENDING.md) — write your own plot type
|
|
18
|
+
- [Themes](docs/THEMES.md) — visual presets
|
|
19
|
+
- [AI attributes](docs/AI_ATTRS.md) — `data-plotlet-*` schema for automation
|
|
20
|
+
|
|
21
|
+
Reference plot types beyond the standard vocabulary ship in the separate [`plotlet-extensions`](https://github.com/gitbamboo42/plotlet-extensions) package (single-file artists — sankey, alluvial, raincloud, upset_plot, …; `pip install plotlet-extensions`, then `import plotlet.extensions.<name>`) and in the [`plotlet-cookbook`](https://github.com/gitbamboo42/plotlet-cookbook) repo (multi-file, domain-specific projects). A few extensions the core tests depend on still ship in core under [`src/plotlet/extensions/`](src/plotlet/extensions/).
|
|
22
|
+
|
|
23
|
+
## For AI assistants
|
|
24
|
+
|
|
25
|
+
Compact, vendor-neutral onboarding docs live in [`skills/`](skills/):
|
|
26
|
+
|
|
27
|
+
- [`skills/users.md`](skills/users.md) — for AI tools generating plotlet code on a user's behalf.
|
|
28
|
+
- [`skills/developers.md`](skills/developers.md) — for AI (or human) contributors working on plotlet itself. Symlink as `CLAUDE.md` / `.cursorrules` / `AGENTS.md` as your tool expects.
|
|
29
|
+
|
|
30
|
+
## Dependencies
|
|
31
|
+
|
|
32
|
+
plotlet supports Python 3.10+.
|
|
33
|
+
|
|
34
|
+
Required: `fonttools`, `scipy` (regression, qq, CI error bands, clustering/dendrogram), `resvg_py` (PNG rendering — prebuilt wheels, no system libraries). numpy / pandas / polars inputs work transparently.
|
|
35
|
+
|
|
36
|
+
Optional: `cairosvg` for PDF export (`pip install plotlet[pdf]`).
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install plotlet
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Testing
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install -e ".[test]"
|
|
48
|
+
pytest tests/ # check vs. committed baselines
|
|
49
|
+
pytest tests/ --update # regenerate (review the diff!)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Development
|
|
53
|
+
|
|
54
|
+
Development takes place on GitHub. Please submit bugs to the issue tracker with a reproducible example.
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools>=
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "plotlet"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "Python library for
|
|
7
|
+
version = "0.6.0"
|
|
8
|
+
description = "Python library for reproducible, multi-panel scientific figures, with byte-identical output across machines and an extension API for custom plot types."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
license-files = ["LICENSE"]
|
|
@@ -16,7 +16,6 @@ authors = [
|
|
|
16
16
|
keywords = [
|
|
17
17
|
"plot",
|
|
18
18
|
"svg",
|
|
19
|
-
"matplotlib",
|
|
20
19
|
"scientific",
|
|
21
20
|
"visualization",
|
|
22
21
|
"jupyter",
|
|
@@ -31,12 +30,14 @@ classifiers = [
|
|
|
31
30
|
"Programming Language :: Python :: 3.10",
|
|
32
31
|
"Programming Language :: Python :: 3.11",
|
|
33
32
|
"Programming Language :: Python :: 3.12",
|
|
33
|
+
"Programming Language :: Python :: 3.13",
|
|
34
34
|
"Topic :: Scientific/Engineering :: Visualization",
|
|
35
35
|
"Topic :: Multimedia :: Graphics",
|
|
36
36
|
]
|
|
37
37
|
dependencies = [
|
|
38
38
|
"fonttools>=4.0",
|
|
39
39
|
"scipy>=1.10",
|
|
40
|
+
"resvg_py>=0.3",
|
|
40
41
|
]
|
|
41
42
|
|
|
42
43
|
[project.optional-dependencies]
|
|
@@ -44,6 +45,17 @@ dev = [
|
|
|
44
45
|
"jupyter",
|
|
45
46
|
"nbconvert",
|
|
46
47
|
]
|
|
48
|
+
test = [
|
|
49
|
+
"pytest>=7",
|
|
50
|
+
"pandas",
|
|
51
|
+
]
|
|
52
|
+
pdf = [
|
|
53
|
+
"cairosvg",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
testpaths = ["tests"]
|
|
58
|
+
addopts = "-ra"
|
|
47
59
|
|
|
48
60
|
[project.urls]
|
|
49
61
|
Homepage = "https://github.com/gitbamboo42/plotlet"
|
|
@@ -52,6 +64,10 @@ Issues = "https://github.com/gitbamboo42/plotlet/issues"
|
|
|
52
64
|
|
|
53
65
|
[tool.setuptools.packages.find]
|
|
54
66
|
where = ["src"]
|
|
67
|
+
namespaces = true
|
|
55
68
|
|
|
56
69
|
[tool.setuptools.package-data]
|
|
57
|
-
|
|
70
|
+
# draw/fonts/*.txt are the font licenses — DejaVu (Bitstream Vera–derived)
|
|
71
|
+
# and Arimo (SIL OFL 1.1) both require the license text to accompany
|
|
72
|
+
# redistribution, so they must ship in the wheel next to the TTFs.
|
|
73
|
+
plotlet = ["spec.json", "themes/*.json", "draw/fonts/*.ttf", "draw/fonts/*.txt", "_datasets/*.csv"]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""plotlet — pure-Python deferred-rendering SVG plot library.
|
|
2
|
+
|
|
3
|
+
import plotlet as pt
|
|
4
|
+
c = pt.chart(df, title="...", xlabel="x", ylabel="y", legend=True, gridlines=True)
|
|
5
|
+
c.line(x="time", y="value", color="series")
|
|
6
|
+
c # auto-renders in Jupyter
|
|
7
|
+
|
|
8
|
+
Chart methods chain for incremental composition:
|
|
9
|
+
|
|
10
|
+
df = {"x": [1, 2, 3], "y": [1, 4, 9]}
|
|
11
|
+
c = pt.chart()
|
|
12
|
+
c.line(df, x="x", y="y", label="squares")
|
|
13
|
+
c.title("Hello").legend().gridlines(True)
|
|
14
|
+
c
|
|
15
|
+
"""
|
|
16
|
+
from ._spec import SPEC
|
|
17
|
+
from .draw import TAB10, palette, list_palettes
|
|
18
|
+
from .draw import colormap, list_colormaps, register_colormap
|
|
19
|
+
from . import artists # noqa: F401 — registers built-in artists on import
|
|
20
|
+
from .chart import Chart, Layout, chart, grid
|
|
21
|
+
from .legend import legend
|
|
22
|
+
from .registry import ArtistSpec, add_artist, artist_table, declare_coord_support
|
|
23
|
+
from .sectors import Sectors
|
|
24
|
+
from .layout_diagram import layout_diagram
|
|
25
|
+
from .themes import load_theme, list_themes, register_theme
|
|
26
|
+
from .facet import facet, FacetGrid
|
|
27
|
+
from .datasets import load_dataset, list_datasets
|
|
28
|
+
from .cluster import linkage, linkage_split, SplitTree
|
|
29
|
+
from .formatters import (register_formatter, list_formatters,
|
|
30
|
+
superscript, subscript)
|
|
31
|
+
from ._coord_registry import register_coord_codec
|
|
32
|
+
from ._journal import (to_journal, from_journal, to_json, from_json,
|
|
33
|
+
JournalNode, Journal)
|
|
34
|
+
from ._ir import to_ir, from_ir, resolve_ir, FigureIR, IRNode
|
|
35
|
+
from . import draw, utils
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def __getattr__(name):
|
|
39
|
+
# The one render-half class in the top-level namespace stays a lazy
|
|
40
|
+
# import so that `import plotlet` loads only the recording half —
|
|
41
|
+
# the render half loads on first render (or first touch of this
|
|
42
|
+
# name). Enforced by tests/test_import_boundary.py.
|
|
43
|
+
if name == "CircularCoordinate":
|
|
44
|
+
from .render.coordinates import CircularCoordinate
|
|
45
|
+
return CircularCoordinate
|
|
46
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
47
|
+
|
|
48
|
+
__all__ = ["chart", "Chart", "Layout", "SPEC", "TAB10",
|
|
49
|
+
"palette", "list_palettes",
|
|
50
|
+
"colormap", "list_colormaps", "register_colormap",
|
|
51
|
+
"grid", "legend",
|
|
52
|
+
"ArtistSpec", "add_artist", "artist_table", "declare_coord_support",
|
|
53
|
+
"CircularCoordinate", "Sectors",
|
|
54
|
+
"layout_diagram",
|
|
55
|
+
"load_theme", "list_themes", "register_theme",
|
|
56
|
+
"facet", "FacetGrid",
|
|
57
|
+
"load_dataset", "list_datasets",
|
|
58
|
+
"linkage", "linkage_split", "SplitTree",
|
|
59
|
+
"register_formatter", "list_formatters",
|
|
60
|
+
"superscript", "subscript",
|
|
61
|
+
"to_json", "from_json", "register_coord_codec",
|
|
62
|
+
"to_journal", "from_journal", "JournalNode", "Journal",
|
|
63
|
+
"to_ir", "from_ir", "FigureIR", "IRNode", "resolve_ir",
|
|
64
|
+
"draw", "utils"]
|
|
65
|
+
|
|
66
|
+
# Single source of truth: pyproject.toml. importlib.metadata reads it at
|
|
67
|
+
# runtime from the installed package metadata (works for `pip install` and
|
|
68
|
+
# `pip install -e .` alike). Migrating to setuptools_scm later doesn't
|
|
69
|
+
# touch this code — it just changes how pyproject.toml's version is set.
|
|
70
|
+
from importlib.metadata import version as _pkg_version
|
|
71
|
+
__version__ = _pkg_version("plotlet")
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Coord codec registry — a neutral home for the `class_name → class` map
|
|
2
|
+
that both `serialize.py` and `_journal.py` need for round-tripping coord
|
|
3
|
+
objects like `CircularCoordinate`.
|
|
4
|
+
|
|
5
|
+
Lives here rather than in either consumer so that removing one of them
|
|
6
|
+
later (e.g. retiring the JSON tree serializer once the journal covers
|
|
7
|
+
the same ground) doesn't leave the registry orphaned. The public API
|
|
8
|
+
`plotlet.register_coord_codec` re-exports from this module directly.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Populated by `register_coord_codec`; coord classes register themselves
|
|
14
|
+
# at their definition site (or serialize.py registers built-ins on module
|
|
15
|
+
# import, for the ones that ship with plotlet).
|
|
16
|
+
_COORD_REGISTRY: dict[str, type] = {}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def register_coord_codec(cls: type) -> type:
|
|
20
|
+
"""Register `cls` as a serializable coord. The class must define
|
|
21
|
+
`_to_dict(self) -> dict` and `_from_dict(cls, dict) -> cls`. Returns
|
|
22
|
+
`cls` so this can be used as a decorator."""
|
|
23
|
+
if not hasattr(cls, "_to_dict") or not hasattr(cls, "_from_dict"):
|
|
24
|
+
raise TypeError(
|
|
25
|
+
f"register_coord_codec: {cls.__name__} must define "
|
|
26
|
+
f"`_to_dict` and `_from_dict`."
|
|
27
|
+
)
|
|
28
|
+
_COORD_REGISTRY[cls.__name__] = cls
|
|
29
|
+
return cls
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def resolve_coord(name: str) -> type:
|
|
33
|
+
"""Look up a coord class by registered name, importing the built-in
|
|
34
|
+
coord module on first miss — built-ins register at their definition
|
|
35
|
+
site, and nothing else guarantees that module has been imported when
|
|
36
|
+
a `{"$coord": ...}` envelope arrives from JSON in a fresh process."""
|
|
37
|
+
try:
|
|
38
|
+
return _COORD_REGISTRY[name]
|
|
39
|
+
except KeyError:
|
|
40
|
+
pass
|
|
41
|
+
from .render import coordinates # noqa: F401 — registers built-ins
|
|
42
|
+
try:
|
|
43
|
+
return _COORD_REGISTRY[name]
|
|
44
|
+
except KeyError:
|
|
45
|
+
raise KeyError(
|
|
46
|
+
f"unknown coordinate {name!r}. Registered coords: "
|
|
47
|
+
f"{sorted(_COORD_REGISTRY)}. Custom coord classes must be "
|
|
48
|
+
f"imported (and registered via `register_coord_codec`) before "
|
|
49
|
+
f"a figure referencing them is decoded."
|
|
50
|
+
) from None
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
dataset,x,y
|
|
2
|
+
I,10.0,8.04
|
|
3
|
+
I,8.0,6.95
|
|
4
|
+
I,13.0,7.58
|
|
5
|
+
I,9.0,8.81
|
|
6
|
+
I,11.0,8.33
|
|
7
|
+
I,14.0,9.96
|
|
8
|
+
I,6.0,7.24
|
|
9
|
+
I,4.0,4.26
|
|
10
|
+
I,12.0,10.84
|
|
11
|
+
I,7.0,4.82
|
|
12
|
+
I,5.0,5.68
|
|
13
|
+
II,10.0,9.14
|
|
14
|
+
II,8.0,8.14
|
|
15
|
+
II,13.0,8.74
|
|
16
|
+
II,9.0,8.77
|
|
17
|
+
II,11.0,9.26
|
|
18
|
+
II,14.0,8.1
|
|
19
|
+
II,6.0,6.13
|
|
20
|
+
II,4.0,3.1
|
|
21
|
+
II,12.0,9.13
|
|
22
|
+
II,7.0,7.26
|
|
23
|
+
II,5.0,4.74
|
|
24
|
+
III,10.0,7.46
|
|
25
|
+
III,8.0,6.77
|
|
26
|
+
III,13.0,12.74
|
|
27
|
+
III,9.0,7.11
|
|
28
|
+
III,11.0,7.81
|
|
29
|
+
III,14.0,8.84
|
|
30
|
+
III,6.0,6.08
|
|
31
|
+
III,4.0,5.39
|
|
32
|
+
III,12.0,8.15
|
|
33
|
+
III,7.0,6.42
|
|
34
|
+
III,5.0,5.73
|
|
35
|
+
IV,8.0,6.58
|
|
36
|
+
IV,8.0,5.76
|
|
37
|
+
IV,8.0,7.71
|
|
38
|
+
IV,8.0,8.84
|
|
39
|
+
IV,8.0,8.47
|
|
40
|
+
IV,8.0,7.04
|
|
41
|
+
IV,8.0,5.25
|
|
42
|
+
IV,19.0,12.5
|
|
43
|
+
IV,8.0,5.56
|
|
44
|
+
IV,8.0,7.91
|
|
45
|
+
IV,8.0,6.89
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
year,month,passengers
|
|
2
|
+
1949,January,112
|
|
3
|
+
1949,February,118
|
|
4
|
+
1949,March,132
|
|
5
|
+
1949,April,129
|
|
6
|
+
1949,May,121
|
|
7
|
+
1949,June,135
|
|
8
|
+
1949,July,148
|
|
9
|
+
1949,August,148
|
|
10
|
+
1949,September,136
|
|
11
|
+
1949,October,119
|
|
12
|
+
1949,November,104
|
|
13
|
+
1949,December,118
|
|
14
|
+
1950,January,115
|
|
15
|
+
1950,February,126
|
|
16
|
+
1950,March,141
|
|
17
|
+
1950,April,135
|
|
18
|
+
1950,May,125
|
|
19
|
+
1950,June,149
|
|
20
|
+
1950,July,170
|
|
21
|
+
1950,August,170
|
|
22
|
+
1950,September,158
|
|
23
|
+
1950,October,133
|
|
24
|
+
1950,November,114
|
|
25
|
+
1950,December,140
|
|
26
|
+
1951,January,145
|
|
27
|
+
1951,February,150
|
|
28
|
+
1951,March,178
|
|
29
|
+
1951,April,163
|
|
30
|
+
1951,May,172
|
|
31
|
+
1951,June,178
|
|
32
|
+
1951,July,199
|
|
33
|
+
1951,August,199
|
|
34
|
+
1951,September,184
|
|
35
|
+
1951,October,162
|
|
36
|
+
1951,November,146
|
|
37
|
+
1951,December,166
|
|
38
|
+
1952,January,171
|
|
39
|
+
1952,February,180
|
|
40
|
+
1952,March,193
|
|
41
|
+
1952,April,181
|
|
42
|
+
1952,May,183
|
|
43
|
+
1952,June,218
|
|
44
|
+
1952,July,230
|
|
45
|
+
1952,August,242
|
|
46
|
+
1952,September,209
|
|
47
|
+
1952,October,191
|
|
48
|
+
1952,November,172
|
|
49
|
+
1952,December,194
|
|
50
|
+
1953,January,196
|
|
51
|
+
1953,February,196
|
|
52
|
+
1953,March,236
|
|
53
|
+
1953,April,235
|
|
54
|
+
1953,May,229
|
|
55
|
+
1953,June,243
|
|
56
|
+
1953,July,264
|
|
57
|
+
1953,August,272
|
|
58
|
+
1953,September,237
|
|
59
|
+
1953,October,211
|
|
60
|
+
1953,November,180
|
|
61
|
+
1953,December,201
|
|
62
|
+
1954,January,204
|
|
63
|
+
1954,February,188
|
|
64
|
+
1954,March,235
|
|
65
|
+
1954,April,227
|
|
66
|
+
1954,May,234
|
|
67
|
+
1954,June,264
|
|
68
|
+
1954,July,302
|
|
69
|
+
1954,August,293
|
|
70
|
+
1954,September,259
|
|
71
|
+
1954,October,229
|
|
72
|
+
1954,November,203
|
|
73
|
+
1954,December,229
|
|
74
|
+
1955,January,242
|
|
75
|
+
1955,February,233
|
|
76
|
+
1955,March,267
|
|
77
|
+
1955,April,269
|
|
78
|
+
1955,May,270
|
|
79
|
+
1955,June,315
|
|
80
|
+
1955,July,364
|
|
81
|
+
1955,August,347
|
|
82
|
+
1955,September,312
|
|
83
|
+
1955,October,274
|
|
84
|
+
1955,November,237
|
|
85
|
+
1955,December,278
|
|
86
|
+
1956,January,284
|
|
87
|
+
1956,February,277
|
|
88
|
+
1956,March,317
|
|
89
|
+
1956,April,313
|
|
90
|
+
1956,May,318
|
|
91
|
+
1956,June,374
|
|
92
|
+
1956,July,413
|
|
93
|
+
1956,August,405
|
|
94
|
+
1956,September,355
|
|
95
|
+
1956,October,306
|
|
96
|
+
1956,November,271
|
|
97
|
+
1956,December,306
|
|
98
|
+
1957,January,315
|
|
99
|
+
1957,February,301
|
|
100
|
+
1957,March,356
|
|
101
|
+
1957,April,348
|
|
102
|
+
1957,May,355
|
|
103
|
+
1957,June,422
|
|
104
|
+
1957,July,465
|
|
105
|
+
1957,August,467
|
|
106
|
+
1957,September,404
|
|
107
|
+
1957,October,347
|
|
108
|
+
1957,November,305
|
|
109
|
+
1957,December,336
|
|
110
|
+
1958,January,340
|
|
111
|
+
1958,February,318
|
|
112
|
+
1958,March,362
|
|
113
|
+
1958,April,348
|
|
114
|
+
1958,May,363
|
|
115
|
+
1958,June,435
|
|
116
|
+
1958,July,491
|
|
117
|
+
1958,August,505
|
|
118
|
+
1958,September,404
|
|
119
|
+
1958,October,359
|
|
120
|
+
1958,November,310
|
|
121
|
+
1958,December,337
|
|
122
|
+
1959,January,360
|
|
123
|
+
1959,February,342
|
|
124
|
+
1959,March,406
|
|
125
|
+
1959,April,396
|
|
126
|
+
1959,May,420
|
|
127
|
+
1959,June,472
|
|
128
|
+
1959,July,548
|
|
129
|
+
1959,August,559
|
|
130
|
+
1959,September,463
|
|
131
|
+
1959,October,407
|
|
132
|
+
1959,November,362
|
|
133
|
+
1959,December,405
|
|
134
|
+
1960,January,417
|
|
135
|
+
1960,February,391
|
|
136
|
+
1960,March,419
|
|
137
|
+
1960,April,461
|
|
138
|
+
1960,May,472
|
|
139
|
+
1960,June,535
|
|
140
|
+
1960,July,622
|
|
141
|
+
1960,August,606
|
|
142
|
+
1960,September,508
|
|
143
|
+
1960,October,461
|
|
144
|
+
1960,November,390
|
|
145
|
+
1960,December,432
|