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.
Files changed (87) hide show
  1. plotstyle-1.0.0/CHANGELOG.md +78 -0
  2. plotstyle-1.0.0/PKG-INFO +395 -0
  3. plotstyle-1.0.0/README.md +334 -0
  4. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/pyproject.toml +19 -3
  5. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/__init__.py +11 -12
  6. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/_version.py +2 -2
  7. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/accessibility.py +6 -4
  8. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/grayscale.py +2 -1
  9. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/palettes.py +6 -6
  10. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/export.py +4 -6
  11. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/figure.py +12 -4
  12. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/migrate.py +26 -19
  13. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/style.py +4 -5
  14. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/integrations/seaborn.py +1 -1
  15. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/preview/gallery.py +2 -2
  16. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/__init__.py +1 -1
  17. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/schema.py +10 -7
  18. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/__init__.py +11 -9
  19. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/dimensions.py +1 -1
  20. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/export.py +17 -0
  21. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/report.py +31 -24
  22. plotstyle-1.0.0/tests/test_cli/test_main.py +628 -0
  23. plotstyle-1.0.0/tests/test_color/test_accessibility.py +448 -0
  24. plotstyle-1.0.0/tests/test_color/test_grayscale.py +536 -0
  25. plotstyle-1.0.0/tests/test_color/test_palettes.py +658 -0
  26. plotstyle-1.0.0/tests/test_color/test_rendering.py +215 -0
  27. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_core/test_export.py +419 -39
  28. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_core/test_figure.py +313 -70
  29. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_core/test_migrate.py +328 -24
  30. plotstyle-1.0.0/tests/test_core/test_style.py +764 -0
  31. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_engine/test_fonts.py +7 -1
  32. plotstyle-1.0.0/tests/test_preview/test_gallery.py +897 -0
  33. plotstyle-1.0.0/tests/test_preview/test_print_size.py +764 -0
  34. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_specs/test_registry.py +6 -2
  35. plotstyle-1.0.0/tests/test_utils/test_io.py +333 -0
  36. plotstyle-1.0.0/tests/test_utils/test_warnings.py +235 -0
  37. plotstyle-1.0.0/tests/test_validation/test_checks.py +1348 -0
  38. plotstyle-1.0.0/tests/test_validation/test_report.py +675 -0
  39. plotstyle-0.1.0a1/CHANGELOG.md +0 -42
  40. plotstyle-0.1.0a1/PKG-INFO +0 -271
  41. plotstyle-0.1.0a1/README.md +0 -214
  42. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/.gitignore +0 -0
  43. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/LICENSE +0 -0
  44. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/_utils/__init__.py +0 -0
  45. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/_utils/io.py +0 -0
  46. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/_utils/warnings.py +0 -0
  47. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/cli/__init__.py +0 -0
  48. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/cli/main.py +0 -0
  49. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/__init__.py +0 -0
  50. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/_rendering.py +0 -0
  51. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/okabe_ito.json +0 -0
  52. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/safe_grayscale.json +0 -0
  53. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/tol_bright.json +0 -0
  54. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/tol_muted.json +0 -0
  55. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/color/data/tol_vibrant.json +0 -0
  56. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/core/__init__.py +0 -0
  57. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/engine/__init__.py +0 -0
  58. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/engine/fonts.py +0 -0
  59. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/engine/latex.py +0 -0
  60. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/engine/rcparams.py +0 -0
  61. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/integrations/__init__.py +0 -0
  62. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/preview/__init__.py +0 -0
  63. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/preview/print_size.py +0 -0
  64. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/py.typed +0 -0
  65. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/_templates.toml +0 -0
  66. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/acs.toml +0 -0
  67. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/cell.toml +0 -0
  68. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/elsevier.toml +0 -0
  69. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/ieee.toml +0 -0
  70. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/nature.toml +0 -0
  71. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/plos.toml +0 -0
  72. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/prl.toml +0 -0
  73. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/science.toml +0 -0
  74. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/springer.toml +0 -0
  75. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/units.py +0 -0
  76. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/specs/wiley.toml +0 -0
  77. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/__init__.py +0 -0
  78. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/_base.py +0 -0
  79. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/colors.py +0 -0
  80. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/lines.py +0 -0
  81. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/src/plotstyle/validation/checks/typography.py +0 -0
  82. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/conftest.py +0 -0
  83. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_engine/test_latex.py +0 -0
  84. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_engine/test_rcparams.py +0 -0
  85. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_integrations/test_seaborn.py +0 -0
  86. {plotstyle-0.1.0a1 → plotstyle-1.0.0}/tests/test_specs/test_schema.py +0 -0
  87. {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
@@ -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