plotstyle 0.1.0a1__tar.gz → 1.0.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.
- plotstyle-1.0.0/CHANGELOG.md +78 -0
- plotstyle-1.0.0/PKG-INFO +395 -0
- plotstyle-1.0.0/README.md +334 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/pyproject.toml +19 -3
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/__init__.py +11 -12
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/_version.py +2 -2
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/accessibility.py +6 -4
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/grayscale.py +2 -1
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/palettes.py +6 -6
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/export.py +4 -6
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/figure.py +12 -4
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/migrate.py +26 -19
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/style.py +4 -5
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/integrations/seaborn.py +1 -1
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/preview/gallery.py +2 -2
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/__init__.py +1 -1
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/schema.py +10 -7
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/__init__.py +11 -9
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/dimensions.py +1 -1
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/export.py +17 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/report.py +31 -24
- plotstyle-1.0.0/tests/test_cli/test_main.py +628 -0
- plotstyle-1.0.0/tests/test_color/test_accessibility.py +448 -0
- plotstyle-1.0.0/tests/test_color/test_grayscale.py +536 -0
- plotstyle-1.0.0/tests/test_color/test_palettes.py +658 -0
- plotstyle-1.0.0/tests/test_color/test_rendering.py +215 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_core/test_export.py +419 -39
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_core/test_figure.py +313 -70
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_core/test_migrate.py +328 -24
- plotstyle-1.0.0/tests/test_core/test_style.py +764 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_engine/test_fonts.py +7 -1
- plotstyle-1.0.0/tests/test_preview/test_gallery.py +897 -0
- plotstyle-1.0.0/tests/test_preview/test_print_size.py +764 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_specs/test_registry.py +6 -2
- plotstyle-1.0.0/tests/test_utils/test_io.py +333 -0
- plotstyle-1.0.0/tests/test_utils/test_warnings.py +235 -0
- plotstyle-1.0.0/tests/test_validation/test_checks.py +1348 -0
- plotstyle-1.0.0/tests/test_validation/test_report.py +675 -0
- plotstyle-0.1.0a1/CHANGELOG.md +0 -42
- plotstyle-0.1.0a1/PKG-INFO +0 -271
- plotstyle-0.1.0a1/README.md +0 -214
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/.gitignore +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/LICENSE +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/_utils/__init__.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/_utils/io.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/_utils/warnings.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/cli/__init__.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/cli/main.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/__init__.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/_rendering.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/okabe_ito.json +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/safe_grayscale.json +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/tol_bright.json +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/tol_muted.json +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/tol_vibrant.json +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/__init__.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/engine/__init__.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/engine/fonts.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/engine/latex.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/engine/rcparams.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/integrations/__init__.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/preview/__init__.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/preview/print_size.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/py.typed +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/_templates.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/acs.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/cell.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/elsevier.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/ieee.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/nature.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/plos.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/prl.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/science.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/springer.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/units.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/wiley.toml +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/__init__.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/_base.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/colors.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/lines.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/typography.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/conftest.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_engine/test_latex.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_engine/test_rcparams.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_integrations/test_seaborn.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_specs/test_schema.py +0 -0
- {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_specs/test_units.py +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to **plotstyle** will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [PEP 440](https://peps.python.org/pep-0440/) versioning.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
_Nothing yet._
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## [1.0.0] - 2026-04-12
|
|
17
|
+
|
|
18
|
+
First stable release — production-ready for scientific publication workflows.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **Stable release** — promoted from alpha (`0.1.0a2`) to stable (`1.0.0`); all public APIs are now considered stable and subject to semantic versioning guarantees.
|
|
23
|
+
- **PyPI classifiers** updated to `Development Status :: 5 - Production/Stable`.
|
|
24
|
+
- **Enhanced project metadata** — expanded keywords, classifiers, and project URLs in `pyproject.toml` for better PyPI discoverability.
|
|
25
|
+
- **README improvements** — added more badges (downloads, docs status, code style), expanded feature descriptions, and added star-history / citation section.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## [0.1.0a2] - 2026-04-12
|
|
30
|
+
|
|
31
|
+
Second alpha — full documentation suite, comprehensive test coverage, and hardened validation.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **Full documentation suite** — Sphinx/MyST docs covering installation, quickstart, concepts, CLI reference, complete API reference for every public symbol, how-to guides (accessibility, export, migration, multi-panel, palettes, seaborn), FAQ, and a journal comparison index.
|
|
36
|
+
- **ReadTheDocs integration** — `.readthedocs.yaml` added; docs build automatically on every push; Furo theme configured with custom CSS.
|
|
37
|
+
- **Comprehensive test suite** — new test modules added: `test_style`, `test_palettes`, `test_accessibility`, `test_grayscale`, `test_rendering`, `test_gallery`, `test_print_size`, `test_cli`, `test_io`, `test_warnings`, `test_checks`, `test_report`; existing modules `test_figure`, `test_export`, `test_migrate`, `test_fonts`, and `test_registry` substantially expanded.
|
|
38
|
+
- **Export DPI validation** — `validation/checks/export.py` now emits a hard `FAIL` (instead of a `WARN`) when `savefig.dpi` is a numeric value that is provably below the journal's minimum DPI requirement.
|
|
39
|
+
- **Dependabot** — `.github/dependabot.yml` added for automated dependency-update pull requests.
|
|
40
|
+
- **`_format_panel_label()` range guard** — raises `ValueError` for panel indices ≥ 702 (beyond the two-character `"zz"` label); valid range is now explicitly documented as 0–701.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- CI workflow extended: a `docs` build job added to `.github/workflows/ci.yml` — runs `sphinx-build -W -n` on every push and uploads the rendered HTML as an artifact.
|
|
45
|
+
- Module docstring quick-start example in `__init__.py` updated to use the context-manager form (`with plotstyle.use(...) as style:`) and `plotstyle.figure()` instead of `plotstyle.subplots()`.
|
|
46
|
+
- Docstrings across `migrate.py`, `report.py`, `style.py`, `figure.py`, `export.py`, and `accessibility.py` converted to NumPy-style attribute sections for consistent Sphinx rendering.
|
|
47
|
+
- `FORMAT_EXTENSIONS` constant in `export.py` annotated as a module-level Sphinx data comment (`#:`) so it appears correctly in the API docs.
|
|
48
|
+
- `pyproject.toml` documentation extras updated: `furo` pinned to `>=2025.12.19` and `myst-parser` bumped to `>=5.0,<6`.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## [0.1.0a1] - 2026-04-07
|
|
53
|
+
|
|
54
|
+
First public alpha release.
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **Core style engine** — `plotstyle.use()` applies journal presets to Matplotlib's `rcParams`; works as a context manager with automatic restoration on exit.
|
|
59
|
+
- **Figure helpers** — `plotstyle.figure()` and `plotstyle.subplots()` create correctly-sized figures at the exact column width and max height specified by each journal.
|
|
60
|
+
- **Auto panel labels** — multi-panel figures receive **(a)**, **(b)**, **(c)**, … labels placed according to the journal's style rules.
|
|
61
|
+
- **Colorblind-safe palettes** — built-in Okabe–Ito, Tol Bright, Tol Vibrant, Tol Muted, and Safe Grayscale palettes (`plotstyle.palette()`).
|
|
62
|
+
- **Accessibility previews** — `plotstyle.preview_colorblind()` simulates deuteranopia, protanopia, and tritanopia; `plotstyle.preview_grayscale()` previews grayscale rendering.
|
|
63
|
+
- **Pre-submission validation** — `plotstyle.validate()` checks dimensions, typography, line weights, color accessibility, and export settings against a target journal spec.
|
|
64
|
+
- **Submission-ready export** — `plotstyle.savefig()` saves with font embedding and DPI enforcement; `plotstyle.export_submission()` batch-exports to all formats a journal accepts.
|
|
65
|
+
- **Spec diffing & migration** — `plotstyle.diff()` compares two journal specs; `plotstyle.migrate()` re-targets a figure from one journal to another.
|
|
66
|
+
- **Seaborn integration** — `patch_seaborn()` / `plotstyle_theme()` ensure PlotStyle `rcParams` survive `sns.set_theme()` calls.
|
|
67
|
+
- **Gallery & print-size preview** — `plotstyle.gallery()` generates sample figures; `plotstyle.preview_print_size()` opens an interactive scaled preview window.
|
|
68
|
+
- **Journal spec registry** — programmatic access via `plotstyle.registry`; specs are TOML files validated by immutable, typed dataclasses.
|
|
69
|
+
- **CLI** — `plotstyle list`, `plotstyle info`, `plotstyle diff`, `plotstyle fonts`, `plotstyle validate`, and `plotstyle export` sub-commands.
|
|
70
|
+
- **10 journal presets** — ACS, Cell, Elsevier, IEEE, Nature, PLOS, PRL, Science, Springer, Wiley.
|
|
71
|
+
- **10 working examples** — quick start, multi-panel, palettes, accessibility, validation, export, diff/migrate, gallery, registry, context manager patterns.
|
|
72
|
+
- **Dynamic versioning** — version derived from git tags via `hatch-vcs` and `importlib.metadata`.
|
|
73
|
+
- **CI/CD pipeline** — GitHub Actions workflows for lint, type-check, test matrix, and automated PyPI release via OIDC Trusted Publishing.
|
|
74
|
+
|
|
75
|
+
[Unreleased]: https://github.com/rahulkaushal04/plotstyle/compare/v1.0.0...HEAD
|
|
76
|
+
[1.0.0]: https://github.com/rahulkaushal04/plotstyle/compare/v0.1.0a2...v1.0.0
|
|
77
|
+
[0.1.0a2]: https://github.com/rahulkaushal04/plotstyle/compare/v0.1.0a1...v0.1.0a2
|
|
78
|
+
[0.1.0a1]: https://github.com/rahulkaushal04/plotstyle/releases/tag/v0.1.0a1
|
plotstyle-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plotstyle
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Matplotlib/seaborn style presets matching scientific journal requirements, with validation, export safety, and preview capabilities.
|
|
5
|
+
Project-URL: Homepage, https://github.com/rahulkaushal04/plotstyle
|
|
6
|
+
Project-URL: Documentation, https://plotstyle.readthedocs.io
|
|
7
|
+
Project-URL: Repository, https://github.com/rahulkaushal04/plotstyle
|
|
8
|
+
Project-URL: Issues, https://github.com/rahulkaushal04/plotstyle/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/rahulkaushal04/plotstyle/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Download, https://pypi.org/project/plotstyle/
|
|
11
|
+
Author: Rahul Kaushal
|
|
12
|
+
License: MIT
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Keywords: academic,accessibility,colorblind,export,figures,ieee,journal,matplotlib,nature,plotting,publication,rcParams,research,science,scientific,seaborn,style,typesetting,validation,visualization
|
|
15
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
16
|
+
Classifier: Framework :: Matplotlib
|
|
17
|
+
Classifier: Intended Audience :: Education
|
|
18
|
+
Classifier: Intended Audience :: Science/Research
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Natural Language :: English
|
|
21
|
+
Classifier: Operating System :: OS Independent
|
|
22
|
+
Classifier: Programming Language :: Python :: 3
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
27
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
28
|
+
Classifier: Topic :: Scientific/Engineering
|
|
29
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
30
|
+
Classifier: Typing :: Typed
|
|
31
|
+
Requires-Python: >=3.10
|
|
32
|
+
Requires-Dist: matplotlib<4,>=3.9
|
|
33
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
34
|
+
Provides-Extra: all
|
|
35
|
+
Requires-Dist: fonttools<5,>=4.55; extra == 'all'
|
|
36
|
+
Requires-Dist: pandas<3,>=2.2; extra == 'all'
|
|
37
|
+
Requires-Dist: pillow<13,>=11.0; extra == 'all'
|
|
38
|
+
Requires-Dist: seaborn<1,>=0.13.2; extra == 'all'
|
|
39
|
+
Provides-Extra: color
|
|
40
|
+
Requires-Dist: pillow<13,>=11.0; extra == 'color'
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: mypy<2,>=1.15; extra == 'dev'
|
|
43
|
+
Requires-Dist: pillow<13,>=11.0; extra == 'dev'
|
|
44
|
+
Requires-Dist: pre-commit<5,>=4.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest-cov<8,>=6.0; extra == 'dev'
|
|
46
|
+
Requires-Dist: pytest-mpl<1,>=0.18; extra == 'dev'
|
|
47
|
+
Requires-Dist: pytest<10,>=8.3; extra == 'dev'
|
|
48
|
+
Requires-Dist: ruff<1,>=0.15; extra == 'dev'
|
|
49
|
+
Provides-Extra: docs
|
|
50
|
+
Requires-Dist: furo>=2025.12.19; extra == 'docs'
|
|
51
|
+
Requires-Dist: myst-parser<6,>=5.0; extra == 'docs'
|
|
52
|
+
Requires-Dist: sphinx-autodoc-typehints<4,>=3.0; extra == 'docs'
|
|
53
|
+
Requires-Dist: sphinx-copybutton<1,>=0.5; extra == 'docs'
|
|
54
|
+
Requires-Dist: sphinx<10,>=9.0; extra == 'docs'
|
|
55
|
+
Provides-Extra: fonttools
|
|
56
|
+
Requires-Dist: fonttools<5,>=4.55; extra == 'fonttools'
|
|
57
|
+
Provides-Extra: seaborn
|
|
58
|
+
Requires-Dist: pandas<3,>=2.2; extra == 'seaborn'
|
|
59
|
+
Requires-Dist: seaborn<1,>=0.13.2; extra == 'seaborn'
|
|
60
|
+
Description-Content-Type: text/markdown
|
|
61
|
+
|
|
62
|
+
<p align="center">
|
|
63
|
+
<strong>plotstyle</strong>
|
|
64
|
+
</p>
|
|
65
|
+
|
|
66
|
+
<p align="center">
|
|
67
|
+
<em>Publication-ready scientific figures — one line of code.</em>
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
<p align="center">
|
|
71
|
+
<a href="https://pypi.org/project/plotstyle/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/plotstyle?color=blue"></a>
|
|
72
|
+
<a href="https://pypi.org/project/plotstyle/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/plotstyle"></a>
|
|
73
|
+
<a href="https://pypi.org/project/plotstyle/"><img alt="Downloads" src="https://img.shields.io/pypi/dm/plotstyle?color=green"></a>
|
|
74
|
+
<a href="https://github.com/rahulkaushal04/plotstyle/blob/main/LICENSE"><img alt="License: MIT" src="https://img.shields.io/github/license/rahulkaushal04/plotstyle"></a>
|
|
75
|
+
<a href="https://github.com/rahulkaushal04/plotstyle/actions"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/rahulkaushal04/plotstyle/ci.yml?label=CI"></a>
|
|
76
|
+
<a href="https://plotstyle.readthedocs.io"><img alt="Docs" src="https://img.shields.io/readthedocs/plotstyle?label=docs"></a>
|
|
77
|
+
<a href="https://github.com/rahulkaushal04/plotstyle"><img alt="Code style: Ruff" src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json"></a>
|
|
78
|
+
<a href="https://github.com/rahulkaushal04/plotstyle"><img alt="Typed: mypy" src="https://img.shields.io/badge/typed-mypy-blue"></a>
|
|
79
|
+
</p>
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
**PlotStyle** configures [Matplotlib](https://matplotlib.org/) (and optionally [Seaborn](https://seaborn.pydata.org/)) so your figures match the exact typographic, dimensional, and export requirements of major academic journals — out of the box.
|
|
84
|
+
|
|
85
|
+
Getting a figure accepted often means matching a journal's precise column width, font size range, line weight, DPI, and export format. PlotStyle encodes those requirements as TOML specs and applies them automatically, so you spend time on your science rather than your figure settings.
|
|
86
|
+
|
|
87
|
+
> **Current release:** `v1.0.0` (stable)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Table of Contents
|
|
92
|
+
|
|
93
|
+
- [Why PlotStyle?](#why-plotstyle)
|
|
94
|
+
- [Features](#features)
|
|
95
|
+
- [Supported Journals](#supported-journals)
|
|
96
|
+
- [Installation](#installation)
|
|
97
|
+
- [Quick Start](#quick-start)
|
|
98
|
+
- [Usage](#usage)
|
|
99
|
+
- [CLI](#cli)
|
|
100
|
+
- [Examples](#examples)
|
|
101
|
+
- [Documentation](#documentation)
|
|
102
|
+
- [Contributing](#contributing)
|
|
103
|
+
- [Citation](#citation)
|
|
104
|
+
- [License](#license)
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Why PlotStyle?
|
|
109
|
+
|
|
110
|
+
Most journals reject figures that don't meet their formatting requirements — wrong column width, incorrect font sizes, missing font embedding, insufficient DPI, or incompatible file formats. Fixing these manually is tedious and error-prone, especially when targeting multiple journals.
|
|
111
|
+
|
|
112
|
+
PlotStyle solves this by encoding each journal's exact requirements into machine-readable specs and applying them automatically. You focus on your data; PlotStyle handles the formatting.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Features
|
|
117
|
+
|
|
118
|
+
- **One-line journal presets** — `plotstyle.use("nature")` sets fonts, sizes, line widths, and export parameters in Matplotlib's `rcParams`. Wrap it in a `with` block and everything is restored automatically when the block exits.
|
|
119
|
+
- **Correctly-sized figures** — `plotstyle.figure()` and `plotstyle.subplots()` create figures at the exact column width and maximum height specified by each journal.
|
|
120
|
+
- **Auto panel labels** — multi-panel figures get **(a)**, **(b)**, **(c)**, … labels placed and styled according to each journal's conventions.
|
|
121
|
+
- **Colorblind-safe palettes** — built-in Okabe–Ito, Tol Bright/Vibrant/Muted, and grayscale-safe palettes via `plotstyle.palette()`.
|
|
122
|
+
- **Accessibility previews** — simulate deuteranopia, protanopia, and tritanopia; preview grayscale rendering.
|
|
123
|
+
- **Pre-submission validation** — check figure dimensions, font sizes, line weights, color accessibility, and export settings against the target journal's spec before you submit.
|
|
124
|
+
- **Submission-ready export** — `plotstyle.savefig()` enforces TrueType font embedding and minimum DPI; `plotstyle.export_submission()` batch-exports to every format the journal requires.
|
|
125
|
+
- **Spec diffing & migration** — compare two journal specs side-by-side; re-target a figure from one journal to another with `plotstyle.migrate()`.
|
|
126
|
+
- **Seaborn compatibility** — a patch layer ensures PlotStyle's `rcParams` survive `sns.set_theme()` calls.
|
|
127
|
+
- **Typed, schema-validated specs** — journal requirements are stored as TOML files validated by immutable typed dataclasses.
|
|
128
|
+
- **CLI** — `plotstyle list`, `plotstyle info`, `plotstyle validate`, and more — no Python script needed.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Supported Journals
|
|
133
|
+
|
|
134
|
+
| Key | Journal | Publisher |
|
|
135
|
+
|-----|---------|-----------|
|
|
136
|
+
| `acs` | ACS (JACS) | American Chemical Society |
|
|
137
|
+
| `cell` | Cell | Cell Press |
|
|
138
|
+
| `elsevier` | Elsevier | Elsevier |
|
|
139
|
+
| `ieee` | IEEE Transactions | IEEE |
|
|
140
|
+
| `nature` | Nature | Springer Nature |
|
|
141
|
+
| `plos` | PLOS ONE | Public Library of Science |
|
|
142
|
+
| `prl` | Physical Review Letters | American Physical Society |
|
|
143
|
+
| `science` | Science | AAAS |
|
|
144
|
+
| `springer` | Springer | Springer |
|
|
145
|
+
| `wiley` | Wiley | Wiley |
|
|
146
|
+
|
|
147
|
+
> Need another journal? See [CONTRIBUTING.md](CONTRIBUTING.md) for how to add one.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Installation
|
|
152
|
+
|
|
153
|
+
Requires **Python 3.10+** and **Matplotlib ≥ 3.9**.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
pip install plotstyle
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Optional extras
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Colorblind / grayscale preview (needs Pillow)
|
|
163
|
+
pip install "plotstyle[color]"
|
|
164
|
+
|
|
165
|
+
# Font subsetting / inspection
|
|
166
|
+
pip install "plotstyle[fonttools]"
|
|
167
|
+
|
|
168
|
+
# Seaborn integration
|
|
169
|
+
pip install "plotstyle[seaborn]"
|
|
170
|
+
|
|
171
|
+
# Everything
|
|
172
|
+
pip install "plotstyle[all]"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Development install
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
git clone https://github.com/rahulkaushal04/plotstyle.git
|
|
179
|
+
cd plotstyle
|
|
180
|
+
pip install -e ".[dev]"
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Quick Start
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
import numpy as np
|
|
189
|
+
import plotstyle
|
|
190
|
+
|
|
191
|
+
# plotstyle.use() applies the journal's rcParams (fonts, sizes, line widths).
|
|
192
|
+
# The `with` block ensures they are restored automatically when plotting is done.
|
|
193
|
+
with plotstyle.use("nature"):
|
|
194
|
+
# Creates a figure at Nature's exact single-column width (89 mm).
|
|
195
|
+
# Use columns=2 for double-column (full text width).
|
|
196
|
+
fig, ax = plotstyle.figure("nature", columns=1)
|
|
197
|
+
|
|
198
|
+
x = np.linspace(0, 2 * np.pi, 200)
|
|
199
|
+
ax.plot(x, np.sin(x), label="sin(x)")
|
|
200
|
+
ax.plot(x, np.cos(x), label="cos(x)")
|
|
201
|
+
ax.set_xlabel("Phase (rad)")
|
|
202
|
+
ax.set_ylabel("Amplitude (a.u.)")
|
|
203
|
+
ax.legend()
|
|
204
|
+
|
|
205
|
+
# Enforces Nature's minimum DPI (300) and embeds TrueType fonts.
|
|
206
|
+
plotstyle.savefig(fig, "quickstart_nature.pdf", journal="nature")
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
The `with` block is the recommended pattern — `rcParams` are always restored on exit, even if an exception occurs inside the block.
|
|
210
|
+
|
|
211
|
+
If you need to manage the style manually:
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
style = plotstyle.use("ieee")
|
|
215
|
+
try:
|
|
216
|
+
fig, ax = plotstyle.figure("ieee", columns=1)
|
|
217
|
+
ax.plot([1, 2, 3])
|
|
218
|
+
plotstyle.savefig(fig, "fig_ieee.eps", journal="ieee")
|
|
219
|
+
finally:
|
|
220
|
+
style.restore() # always restore, even on error
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Usage
|
|
226
|
+
|
|
227
|
+
### Multi-panel figures
|
|
228
|
+
|
|
229
|
+
`plotstyle.subplots()` works like `plt.subplots()` but sizes the figure to the journal spec and adds panel labels automatically.
|
|
230
|
+
|
|
231
|
+
> **Note:** Unlike `plt.subplots()`, `plotstyle.subplots()` **always** returns a 2-D NumPy array of axes — even for a single panel. Use `axes[0, 0]` to access a single axes, or `axes.flat` to iterate over all panels.
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
import plotstyle
|
|
235
|
+
|
|
236
|
+
with plotstyle.use("science"):
|
|
237
|
+
fig, axes = plotstyle.subplots("science", nrows=2, ncols=2, columns=2)
|
|
238
|
+
# axes has shape (2, 2); each panel is labelled (a), (b), (c), (d)
|
|
239
|
+
for ax in axes.flat:
|
|
240
|
+
ax.plot([1, 2, 3])
|
|
241
|
+
plotstyle.savefig(fig, "multipanel.pdf", journal="science")
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Pass `panels=False` to suppress the automatic labels.
|
|
245
|
+
|
|
246
|
+
### Color palettes
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
# A list of 4 hex color strings from Nature's recommended palette
|
|
250
|
+
colors = plotstyle.palette("nature", n=4)
|
|
251
|
+
|
|
252
|
+
# With linestyles and markers — useful for accessible line plots
|
|
253
|
+
styled = plotstyle.palette("ieee", n=3, with_markers=True)
|
|
254
|
+
# styled is a list of (color, linestyle, marker) tuples
|
|
255
|
+
for color, ls, marker in styled:
|
|
256
|
+
ax.plot(x, y, color=color, linestyle=ls, marker=marker)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Validation
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
report = plotstyle.validate(fig, journal="nature")
|
|
263
|
+
print(report) # formatted table of all checks
|
|
264
|
+
print(report.passed) # True if no checks failed
|
|
265
|
+
|
|
266
|
+
for failure in report.failures:
|
|
267
|
+
print(failure.message) # what failed
|
|
268
|
+
print(failure.fix_suggestion) # how to fix it
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Submission export
|
|
272
|
+
|
|
273
|
+
`export_submission()` writes the figure in every format the journal requires (PDF, TIFF, EPS, etc.) and applies journal-specific naming conventions.
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
paths = plotstyle.export_submission(
|
|
277
|
+
fig,
|
|
278
|
+
"figure1",
|
|
279
|
+
journal="ieee",
|
|
280
|
+
author_surname="Kaushal", # IEEE prepends the first 5 chars of the surname
|
|
281
|
+
output_dir="submission_ieee",
|
|
282
|
+
)
|
|
283
|
+
# Produces: submission_ieee/kaush_figure1.pdf (and any other IEEE-required formats)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Spec diffing and migration
|
|
287
|
+
|
|
288
|
+
```python
|
|
289
|
+
# Compare two journals — useful when retargeting a figure
|
|
290
|
+
result = plotstyle.diff("nature", "science")
|
|
291
|
+
print(result) # aligned two-column table of differences
|
|
292
|
+
|
|
293
|
+
# Re-target a figure to a different journal in place
|
|
294
|
+
plotstyle.migrate(fig, from_journal="nature", to_journal="science")
|
|
295
|
+
plotstyle.savefig(fig, "figure_science.pdf", journal="science")
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Accessibility previews
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
# Simulate how a figure looks under three types of color blindness
|
|
302
|
+
comp = plotstyle.preview_colorblind(fig)
|
|
303
|
+
comp.savefig("colorblind_check.png", dpi=150)
|
|
304
|
+
|
|
305
|
+
# Preview grayscale rendering
|
|
306
|
+
gs = plotstyle.preview_grayscale(fig)
|
|
307
|
+
gs.savefig("grayscale_check.png", dpi=150)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Seaborn integration
|
|
311
|
+
|
|
312
|
+
`sns.set_theme()` normally overwrites the rcParams that PlotStyle set. Pass `seaborn_compatible=True` to prevent that:
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
import seaborn as sns
|
|
316
|
+
import plotstyle
|
|
317
|
+
|
|
318
|
+
with plotstyle.use("nature", seaborn_compatible=True):
|
|
319
|
+
fig, ax = plotstyle.figure("nature", columns=1)
|
|
320
|
+
sns.lineplot(x=[1, 2, 3], y=[4, 5, 6], ax=ax)
|
|
321
|
+
plotstyle.savefig(fig, "seaborn_figure.pdf", journal="nature")
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## CLI
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
plotstyle list # List all journal presets
|
|
330
|
+
plotstyle info <journal> # Show spec details
|
|
331
|
+
plotstyle diff <journal_a> <journal_b> # Compare two journals
|
|
332
|
+
plotstyle fonts --journal <journal> # Check font availability
|
|
333
|
+
plotstyle validate <file> --journal <journal> # Validate a saved figure
|
|
334
|
+
plotstyle export <file> --journal <journal> # Re-export in required formats
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Examples
|
|
340
|
+
|
|
341
|
+
Working examples are in the [`examples/`](examples/) directory:
|
|
342
|
+
|
|
343
|
+
| # | File | Topic |
|
|
344
|
+
|---|------|-------|
|
|
345
|
+
| 01 | [01_quickstart.py](examples/01_quickstart.py) | Basic publication-ready figure |
|
|
346
|
+
| 02 | [02_multi_panel_figure.py](examples/02_multi_panel_figure.py) | 2×2 subplot grid with auto panel labels |
|
|
347
|
+
| 03 | [03_color_palettes.py](examples/03_color_palettes.py) | Journal-specific and universal palettes |
|
|
348
|
+
| 04 | [04_accessibility_checks.py](examples/04_accessibility_checks.py) | Colorblind and grayscale previews |
|
|
349
|
+
| 05 | [05_validation.py](examples/05_validation.py) | Pre-submission validation |
|
|
350
|
+
| 06 | [06_export_submission.py](examples/06_export_submission.py) | Batch submission export |
|
|
351
|
+
| 07 | [07_spec_diff_and_migrate.py](examples/07_spec_diff_and_migrate.py) | Spec comparison and figure migration |
|
|
352
|
+
| 08 | [08_gallery_preview.py](examples/08_gallery_preview.py) | Gallery preview generation |
|
|
353
|
+
| 09 | [09_registry_and_spec.py](examples/09_registry_and_spec.py) | Registry and spec access |
|
|
354
|
+
| 10 | [10_context_manager_patterns.py](examples/10_context_manager_patterns.py) | Context manager usage patterns |
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Documentation
|
|
359
|
+
|
|
360
|
+
Full documentation is available at **[plotstyle.readthedocs.io](https://plotstyle.readthedocs.io)**:
|
|
361
|
+
|
|
362
|
+
- [Installation guide](https://plotstyle.readthedocs.io/en/latest/installation.html)
|
|
363
|
+
- [Quick start tutorial](https://plotstyle.readthedocs.io/en/latest/quickstart.html)
|
|
364
|
+
- [API reference](https://plotstyle.readthedocs.io/en/latest/api/index.html)
|
|
365
|
+
- [How-to guides](https://plotstyle.readthedocs.io/en/latest/guides/index.html)
|
|
366
|
+
- [CLI reference](https://plotstyle.readthedocs.io/en/latest/cli.html)
|
|
367
|
+
- [FAQ](https://plotstyle.readthedocs.io/en/latest/faq.html)
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Contributing
|
|
372
|
+
|
|
373
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, adding journal specs, code style, and pull request guidelines.
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Citation
|
|
378
|
+
|
|
379
|
+
If PlotStyle helps your research, a citation or star is appreciated:
|
|
380
|
+
|
|
381
|
+
```bibtex
|
|
382
|
+
@software{plotstyle,
|
|
383
|
+
author = {Kaushal, Rahul},
|
|
384
|
+
title = {PlotStyle: Publication-ready scientific figure presets for Matplotlib},
|
|
385
|
+
year = {2026},
|
|
386
|
+
url = {https://github.com/rahulkaushal04/plotstyle},
|
|
387
|
+
license = {MIT},
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## License
|
|
394
|
+
|
|
395
|
+
[MIT](LICENSE) © 2026 Rahul Kaushal
|