plotstyle 1.2.0__tar.gz → 1.2.1__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.2.1/CHANGELOG.md +155 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/PKG-INFO +114 -24
- {plotstyle-1.2.0 → plotstyle-1.2.1}/README.md +113 -23
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/__init__.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/_compat/mpl_style.py +2 -2
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/_version.py +2 -2
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/cli/main.py +3 -3
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/_rendering.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/accessibility.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/core/export.py +12 -7
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/core/figure.py +3 -3
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/core/migrate.py +7 -7
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/core/style.py +14 -14
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/engine/fonts.py +9 -8
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/engine/latex.py +2 -2
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/engine/rcparams.py +5 -5
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/__init__.py +2 -2
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/schema.py +3 -3
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/preview/print_size.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/__init__.py +27 -24
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/_templates.toml +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/schema.py +2 -2
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/units.py +2 -2
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/checks/__init__.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/checks/_base.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/checks/dimensions.py +2 -2
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/checks/typography.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/report.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_cli/test_main.py +3 -3
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_color/test_accessibility.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_color/test_grayscale.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_engine/test_rcparams.py +13 -13
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_integrations/test_seaborn.py +3 -3
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_preview/test_gallery.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_preview/test_print_size.py +1 -1
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_specs/test_registry.py +3 -3
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_specs/test_schema.py +6 -6
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_specs/test_units.py +8 -8
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_utils/test_io.py +5 -5
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_utils/test_warnings.py +1 -1
- plotstyle-1.2.0/CHANGELOG.md +0 -135
- {plotstyle-1.2.0 → plotstyle-1.2.1}/.gitignore +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/LICENSE +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/pyproject.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/_compat/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/_utils/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/_utils/io.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/_utils/warnings.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/cli/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/okabe_ito.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/safe_grayscale.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_bright.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_high_contrast.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_light.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_muted.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_rainbow_10.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_rainbow_12.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_rainbow_4.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_rainbow_6.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_rainbow_8.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/data/tol_vibrant.json +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/grayscale.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/color/palettes.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/core/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/engine/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/integrations/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/integrations/seaborn.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/bar.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/cjk-japanese.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/cjk-korean.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/cjk-simplified.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/cjk-traditional.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/grid.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/high-vis.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/latex-sans.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/minimal.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/no-latex.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/notebook.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/okabe-ito.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/pgf.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/presentation.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/russian.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/safe-grayscale.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/scatter.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-bright.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-high-contrast.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-light.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-muted.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-rainbow-10.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-rainbow-12.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-rainbow-4.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-rainbow-6.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-rainbow-8.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/tol-vibrant.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/overlays/turkish.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/preview/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/preview/gallery.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/py.typed +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/acs.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/cell.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/elsevier.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/ieee.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/nature.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/plos.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/prl.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/science.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/springer.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/specs/wiley.toml +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/__init__.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/checks/colors.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/checks/export.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/src/plotstyle/validation/checks/lines.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/conftest.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_color/test_palettes.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_color/test_rendering.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_core/test_export.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_core/test_figure.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_core/test_migrate.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_core/test_style.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_engine/test_fonts.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_engine/test_latex.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_validation/test_checks.py +0 -0
- {plotstyle-1.2.0 → plotstyle-1.2.1}/tests/test_validation/test_report.py +0 -0
|
@@ -0,0 +1,155 @@
|
|
|
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.2.1] - 2026-04-26
|
|
17
|
+
|
|
18
|
+
Patch release: `simulate_cvd` example, warning quality improvements, and docs/example content fixes.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **`simulate_cvd` example in `04_accessibility_checks.py`**: demonstrates low-level CVD simulation by rendering a figure to an RGB array and applying a single `CVDType` matrix directly via `simulate_cvd()`.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- **`SpecAssumptionWarning` deduplication**: each spec now emits the assumption warning at most once per session. A `_warned_specs` set on `SpecRegistry` tracks which specs have already warned; `reset()` clears it alongside the spec cache.
|
|
27
|
+
- **Clearer `OverlaySizeWarning`**: the message now names the journal, the overlay, the actual width, the limit, and the fix action, replacing the previous vague description.
|
|
28
|
+
- **Improved font-fallback warning**: lists font names in a readable comma-separated form and adds a hint to rebuild the Matplotlib font cache after installing a new font.
|
|
29
|
+
- **FontTools log suppression during PDF export**: `savefig()` temporarily sets the `fontTools` logger to `ERROR` level during `fig.savefig()` to suppress low-level font subsetting noise.
|
|
30
|
+
- **`SpecRegistry.get()` uses `_silent=True` during background style registration**: prevents the assumption warning from firing during the import-time `register_all_styles()` call.
|
|
31
|
+
- **Docs and example content fixes**: factual errors corrected across API reference, guides, CLI docs, and Jupyter notebooks; overlay guide expanded with additional coverage.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## [1.2.0] - 2026-04-23
|
|
36
|
+
|
|
37
|
+
Feature release: **overlays**, **units & conversions**, **Seaborn integration**, improved **font/LaTeX controls**, plus major CLI/docs/example expansion.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **Style overlays** (`plotstyle.overlays`, `plotstyle.list_overlays()`): additive layers that can be composed with a base journal preset.
|
|
42
|
+
- Categories: `color`, `context`, `rendering`, `plot-type`, `script`.
|
|
43
|
+
- Built-in overlays include `minimal`, `notebook`, `presentation`, `high-vis`, `grid`, `bar`, `scatter`, `no-latex`, `pgf`, `latex-sans`, `okabe-ito`, `safe-grayscale`, and `tol-*` palette overlays, plus CJK/Turkish/Russian script overlays.
|
|
44
|
+
- **New CLI commands for overlays**
|
|
45
|
+
- `plotstyle overlays [--category <category>]` to list overlays.
|
|
46
|
+
- `plotstyle overlay-info <overlay>` to inspect overlay metadata and `rcParams`.
|
|
47
|
+
- **Font checks for overlays**: `plotstyle fonts --overlay <overlay>` (in addition to `--journal`).
|
|
48
|
+
- **Seaborn integration**: helpers to keep PlotStyle `rcParams` consistent when using Seaborn themes (`patch_seaborn()`, `plotstyle_theme()`, `unpatch_seaborn()`).
|
|
49
|
+
- **Units & conversions**: new/expanded utilities and docs for consistent size specification across specs and helpers.
|
|
50
|
+
- **Matplotlib-native styles compatibility**: support for registering/using PlotStyle presets as Matplotlib styles where applicable.
|
|
51
|
+
- **New examples & previews**: additional example scripts including overlays, Seaborn integration, units/conversions, print-size preview, Matplotlib native styles, and LaTeX/fonts.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- **CLI UX improvements**
|
|
56
|
+
- `plotstyle fonts` now supports `--journal` *or* `--overlay` (mutually exclusive, required).
|
|
57
|
+
- More robust argument parsing (e.g. ignores empty entries in `--formats`).
|
|
58
|
+
- Friendlier output for empty registries (journals/overlays) and clearer reporting for overlay font availability.
|
|
59
|
+
- **Docs & README expansion**: new/expanded guides and API reference for overlays, units, warnings, Seaborn, preview tooling, and updated patterns/examples.
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- **CLI stability**: avoid noisy/unclear behavior in edge cases (empty registry listings, malformed format lists) and improve error messaging around missing overlay keys.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## [1.1.0] - 2026-04-16
|
|
68
|
+
|
|
69
|
+
Minor feature release : ergonomics improvements, hardened error handling, and spec updates.
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
|
|
73
|
+
- **`quiet` parameter on `JournalStyle.export()`** : suppresses compliance summaries and manifest output for scripting workflows.
|
|
74
|
+
- **Pre-computed Type 3 font checks** : compliance summary now accepts a pre-computed result for Type 3 font detection, improving performance when the check has already been run by the caller.
|
|
75
|
+
- **`JournalSpec` key access** : `JournalSpec` now supports key-style access, and the dimension check message has been updated for clarity.
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
|
|
79
|
+
- **`SpecNotFoundError` base classes** : now inherits from both `ValueError` and `KeyError` so existing `except ValueError` and `except KeyError` handlers catch it correctly; a custom `__str__` produces clearer diagnostic messages.
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
|
|
83
|
+
- **IEEE Transactions spec updated** : column widths, max height, font family, panel-label properties, and preferred output formats revised to match current IEEE author guidelines.
|
|
84
|
+
- **CI documentation build** : Sphinx `docs` job (`sphinx-build -W -n`) added to the CI workflow; rendered HTML is uploaded as an artifact on every push.
|
|
85
|
+
- **Module docstrings** : expanded and standardised across `__init__.py`, `_utils/`, `color/`, `core/`, and `validation/` for consistent Sphinx rendering.
|
|
86
|
+
- **Context-manager examples** : all `plotstyle.use()` call sites in docs and examples updated to the `with plotstyle.use(...) as style:` form to ensure correct `rcParams` restoration.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## [1.0.0] - 2026-04-12
|
|
91
|
+
|
|
92
|
+
First stable release: production-ready for scientific publication workflows.
|
|
93
|
+
|
|
94
|
+
### Changed
|
|
95
|
+
|
|
96
|
+
- **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.
|
|
97
|
+
- **PyPI classifiers** updated to `Development Status :: 5 - Production/Stable`.
|
|
98
|
+
- **Enhanced project metadata**: expanded keywords, classifiers, and project URLs in `pyproject.toml` for better PyPI discoverability.
|
|
99
|
+
- **README improvements**: added more badges (downloads, docs status, code style), expanded feature descriptions, and added star-history / citation section.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## [0.1.0a2] - 2026-04-12
|
|
104
|
+
|
|
105
|
+
Second alpha: full documentation suite, comprehensive test coverage, and hardened validation.
|
|
106
|
+
|
|
107
|
+
### Added
|
|
108
|
+
|
|
109
|
+
- **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.
|
|
110
|
+
- **ReadTheDocs integration**: `.readthedocs.yaml` added; docs build automatically on every push; Furo theme configured with custom CSS.
|
|
111
|
+
- **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.
|
|
112
|
+
- **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.
|
|
113
|
+
- **Dependabot**: `.github/dependabot.yml` added for automated dependency-update pull requests.
|
|
114
|
+
- **`_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.
|
|
115
|
+
|
|
116
|
+
### Changed
|
|
117
|
+
|
|
118
|
+
- 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.
|
|
119
|
+
- 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()`.
|
|
120
|
+
- 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.
|
|
121
|
+
- `FORMAT_EXTENSIONS` constant in `export.py` annotated as a module-level Sphinx data comment (`#:`) so it appears correctly in the API docs.
|
|
122
|
+
- `pyproject.toml` documentation extras updated: `furo` pinned to `>=2025.12.19` and `myst-parser` bumped to `>=5.0,<6`.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## [0.1.0a1] - 2026-04-07
|
|
127
|
+
|
|
128
|
+
First public alpha release.
|
|
129
|
+
|
|
130
|
+
### Added
|
|
131
|
+
|
|
132
|
+
- **Core style engine**: `plotstyle.use()` applies journal presets to Matplotlib's `rcParams`; works as a context manager with automatic restoration on exit.
|
|
133
|
+
- **Figure helpers**: `plotstyle.figure()` and `plotstyle.subplots()` create correctly-sized figures at the exact column width and max height specified by each journal.
|
|
134
|
+
- **Auto panel labels**: multi-panel figures receive **(a)**, **(b)**, **(c)**, … labels placed according to the journal's style rules.
|
|
135
|
+
- **Colorblind-safe palettes**: built-in Okabe–Ito, Tol Bright, Tol Vibrant, Tol Muted, and Safe Grayscale palettes (`plotstyle.palette()`).
|
|
136
|
+
- **Accessibility previews**: `plotstyle.preview_colorblind()` simulates deuteranopia, protanopia, and tritanopia; `plotstyle.preview_grayscale()` previews grayscale rendering.
|
|
137
|
+
- **Pre-submission validation**: `plotstyle.validate()` checks dimensions, typography, line weights, color accessibility, and export settings against a target journal spec.
|
|
138
|
+
- **Submission-ready export**: `plotstyle.savefig()` saves with font embedding and DPI enforcement; `plotstyle.export_submission()` batch-exports to all formats a journal accepts.
|
|
139
|
+
- **Spec diffing & migration**: `plotstyle.diff()` compares two journal specs; `plotstyle.migrate()` re-targets a figure from one journal to another.
|
|
140
|
+
- **Seaborn integration**: `patch_seaborn()` / `plotstyle_theme()` ensure PlotStyle `rcParams` survive `sns.set_theme()` calls.
|
|
141
|
+
- **Gallery & print-size preview**: `plotstyle.gallery()` generates sample figures; `plotstyle.preview_print_size()` opens an interactive scaled preview window.
|
|
142
|
+
- **Journal spec registry**: programmatic access via `plotstyle.registry`; specs are TOML files validated by immutable, typed dataclasses.
|
|
143
|
+
- **CLI**: `plotstyle list`, `plotstyle info`, `plotstyle diff`, `plotstyle fonts`, `plotstyle validate`, and `plotstyle export` sub-commands.
|
|
144
|
+
- **10 journal presets**: ACS, Cell, Elsevier, IEEE, Nature, PLOS, PRL, Science, Springer, Wiley.
|
|
145
|
+
- **10 working examples**: quick start, multi-panel, palettes, accessibility, validation, export, diff/migrate, gallery, registry, context manager patterns.
|
|
146
|
+
- **Dynamic versioning**: version derived from git tags via `hatch-vcs` and `importlib.metadata`.
|
|
147
|
+
- **CI/CD pipeline**: GitHub Actions workflows for lint, type-check, test matrix, and automated PyPI release via OIDC Trusted Publishing.
|
|
148
|
+
|
|
149
|
+
[Unreleased]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.1...HEAD
|
|
150
|
+
[1.2.1]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.0...v1.2.1
|
|
151
|
+
[1.2.0]: https://github.com/rahulkaushal04/plotstyle/compare/v1.1.0...v1.2.0
|
|
152
|
+
[1.1.0]: https://github.com/rahulkaushal04/plotstyle/compare/v1.0.0...v1.1.0
|
|
153
|
+
[1.0.0]: https://github.com/rahulkaushal04/plotstyle/compare/v0.1.0a2...v1.0.0
|
|
154
|
+
[0.1.0a2]: https://github.com/rahulkaushal04/plotstyle/compare/v0.1.0a1...v0.1.0a2
|
|
155
|
+
[0.1.0a1]: https://github.com/rahulkaushal04/plotstyle/releases/tag/v0.1.0a1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plotstyle
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Matplotlib/seaborn style presets matching scientific journal requirements, with validation, export safety, and preview capabilities.
|
|
5
5
|
Project-URL: Homepage, https://github.com/rahulkaushal04/plotstyle
|
|
6
6
|
Project-URL: Documentation, https://plotstyle.readthedocs.io
|
|
@@ -244,45 +244,95 @@ fig.savefig("palette_comparison.png", dpi=150)
|
|
|
244
244
|
Pass `with_markers=True` to get `(color, linestyle, marker)` tuples, useful for journals like IEEE that print in grayscale:
|
|
245
245
|
|
|
246
246
|
```python
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
import numpy as np
|
|
248
|
+
import plotstyle
|
|
249
|
+
|
|
250
|
+
x = np.linspace(0, 2 * np.pi, 100)
|
|
251
|
+
curves = [np.sin(x + i * 0.5) for i in range(4)]
|
|
252
|
+
|
|
253
|
+
with plotstyle.use("ieee") as style:
|
|
254
|
+
fig, ax = style.figure(columns=1)
|
|
255
|
+
styled = plotstyle.palette("ieee", n=4, with_markers=True)
|
|
256
|
+
for i, (color, ls, marker) in enumerate(styled):
|
|
257
|
+
ax.plot(x, curves[i], color=color, linestyle=ls, marker=marker,
|
|
258
|
+
markevery=20, label=f"Series {i + 1}")
|
|
259
|
+
ax.set_xlabel("x")
|
|
260
|
+
ax.set_ylabel("y")
|
|
261
|
+
ax.legend()
|
|
262
|
+
style.savefig(fig, "ieee_markers.pdf")
|
|
250
263
|
```
|
|
251
264
|
|
|
252
265
|
```text
|
|
253
|
-
# styled
|
|
266
|
+
# styled: one (color, linestyle, marker) tuple per series:
|
|
254
267
|
[('#000000', '-', 'o'), ('#333333', '--', 's'), ('#666666', '-.', '^'), ('#999999', ':', 'D')]
|
|
255
268
|
```
|
|
256
269
|
|
|
270
|
+
<p align="center">
|
|
271
|
+
<img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/palette_styled_ieee.png" width="55%" alt="IEEE figure with per-series color, linestyle, and marker combinations">
|
|
272
|
+
</p>
|
|
273
|
+
|
|
257
274
|
---
|
|
258
275
|
|
|
259
276
|
### Overlays
|
|
260
277
|
|
|
261
|
-
Overlays are additive patches that layer on top of a journal preset. They let you adjust one aspect of a figure
|
|
278
|
+
Overlays are additive patches that layer on top of a journal preset. They let you adjust one aspect of a figure (the colour palette, the context, the chart type) without changing the base journal settings.
|
|
262
279
|
|
|
263
280
|
Pass overlay names in the same list as the journal key:
|
|
264
281
|
|
|
265
282
|
```python
|
|
283
|
+
import matplotlib.pyplot as plt
|
|
266
284
|
import plotstyle
|
|
267
285
|
|
|
268
286
|
# Strip top/right spines for a clean editorial look
|
|
269
287
|
with plotstyle.use(["nature", "minimal"]) as style:
|
|
270
288
|
fig, ax = style.figure(columns=1)
|
|
271
|
-
ax.plot([1, 2, 3])
|
|
272
|
-
|
|
289
|
+
ax.plot([1, 2, 3], label="data")
|
|
290
|
+
ax.set_xlabel("x")
|
|
291
|
+
ax.set_ylabel("y")
|
|
292
|
+
ax.legend()
|
|
293
|
+
style.savefig(fig, "minimal_figure.pdf")
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
<p align="center">
|
|
297
|
+
<img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/overlay_minimal.png" width="45%" alt="Nature figure with minimal overlay: no top/right spines">
|
|
298
|
+
</p>
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
import matplotlib.pyplot as plt
|
|
302
|
+
import plotstyle
|
|
273
303
|
|
|
274
304
|
# Larger figure and fonts for Jupyter notebooks
|
|
275
305
|
with plotstyle.use(["nature", "notebook"]) as style:
|
|
276
|
-
import matplotlib.pyplot as plt
|
|
277
306
|
fig, ax = plt.subplots() # plt.subplots() picks up the notebook figsize
|
|
278
|
-
ax.plot([1, 2, 3])
|
|
307
|
+
ax.plot([1, 2, 3], label="data")
|
|
308
|
+
ax.set_xlabel("x")
|
|
309
|
+
ax.set_ylabel("y")
|
|
310
|
+
ax.legend()
|
|
311
|
+
style.savefig(fig, "notebook_figure.pdf")
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
<p align="center">
|
|
315
|
+
<img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/overlay_notebook.png" width="60%" alt="Nature figure with notebook overlay: larger fonts and figure size">
|
|
316
|
+
</p>
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
import matplotlib.pyplot as plt
|
|
320
|
+
import plotstyle
|
|
279
321
|
|
|
280
322
|
# Swap the colour cycle to a specific palette
|
|
281
323
|
with plotstyle.use(["ieee", "okabe-ito"]) as style:
|
|
282
324
|
fig, ax = style.figure(columns=1)
|
|
283
|
-
ax.plot([1, 2, 3])
|
|
325
|
+
ax.plot([1, 2, 3], label="data")
|
|
326
|
+
ax.set_xlabel("x")
|
|
327
|
+
ax.set_ylabel("y")
|
|
328
|
+
ax.legend()
|
|
329
|
+
style.savefig(fig, "okabe_ito_figure.pdf")
|
|
284
330
|
```
|
|
285
331
|
|
|
332
|
+
<p align="center">
|
|
333
|
+
<img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/overlay_okabe_ito.png" width="55%" alt="IEEE figure with okabe-ito colorblind-safe palette">
|
|
334
|
+
</p>
|
|
335
|
+
|
|
286
336
|
| Category | Purpose | Examples |
|
|
287
337
|
|----------|---------|---------|
|
|
288
338
|
| `color` | Swap the colour cycle | `okabe-ito`, `tol-bright`, `safe-grayscale` |
|
|
@@ -353,18 +403,44 @@ with plotstyle.use("nature") as style:
|
|
|
353
403
|
Validate a figure against the journal's requirements, then export in all required formats at once.
|
|
354
404
|
|
|
355
405
|
```python
|
|
406
|
+
import numpy as np
|
|
407
|
+
import matplotlib.pyplot as plt
|
|
408
|
+
import plotstyle
|
|
409
|
+
|
|
410
|
+
x = np.linspace(0, 2 * np.pi, 100)
|
|
411
|
+
|
|
412
|
+
# Outside plotstyle.use() — some checks will fail
|
|
413
|
+
fig, ax = plt.subplots()
|
|
414
|
+
ax.plot(x, np.sin(x), label="sin(x)")
|
|
415
|
+
ax.set_xlabel("Phase (rad)")
|
|
416
|
+
ax.set_ylabel("Amplitude")
|
|
417
|
+
ax.legend()
|
|
418
|
+
|
|
356
419
|
report = plotstyle.validate(fig, journal="nature")
|
|
357
420
|
print(report) # formatted compliance table
|
|
358
|
-
print(report.passed) #
|
|
421
|
+
print(report.passed) # False — rcParams not configured
|
|
359
422
|
|
|
360
423
|
for failure in report.failures:
|
|
361
424
|
print(failure.message) # what failed
|
|
362
425
|
print(failure.fix_suggestion) # how to fix it
|
|
426
|
+
plt.close(fig)
|
|
427
|
+
|
|
428
|
+
# Inside plotstyle.use() — all checks pass
|
|
429
|
+
with plotstyle.use("nature") as style:
|
|
430
|
+
fig, ax = style.figure(columns=1)
|
|
431
|
+
ax.plot(x, np.sin(x), label="sin(x)")
|
|
432
|
+
ax.set_xlabel("Phase (rad)")
|
|
433
|
+
ax.set_ylabel("Amplitude")
|
|
434
|
+
ax.legend()
|
|
435
|
+
|
|
436
|
+
report = plotstyle.validate(fig, journal="nature")
|
|
437
|
+
print(report)
|
|
438
|
+
print(report.passed) # True
|
|
363
439
|
```
|
|
364
440
|
|
|
365
441
|
```text
|
|
366
442
|
┌──────────────────────────────────────────────────────┐
|
|
367
|
-
│ PlotStyle Validation Report
|
|
443
|
+
│ PlotStyle Validation Report: Nature │
|
|
368
444
|
├──────────┬───────────────────────────────────────────┤
|
|
369
445
|
│ ✓ PASS │ Figure width 89.0mm matches single colu...│
|
|
370
446
|
│ ✓ PASS │ Figure height 55.0mm is within the Natu...│
|
|
@@ -387,7 +463,7 @@ When called inside `plotstyle.use()`, all checks pass:
|
|
|
387
463
|
|
|
388
464
|
```text
|
|
389
465
|
┌──────────────────────────────────────────────────────┐
|
|
390
|
-
│ PlotStyle Validation Report
|
|
466
|
+
│ PlotStyle Validation Report: Nature │
|
|
391
467
|
├──────────┬───────────────────────────────────────────┤
|
|
392
468
|
│ ✓ PASS │ Figure width 89.0mm matches single colu...│
|
|
393
469
|
│ ✓ PASS │ Figure height 55.0mm is within the Natu...│
|
|
@@ -403,14 +479,28 @@ passed: True
|
|
|
403
479
|
```
|
|
404
480
|
|
|
405
481
|
```python
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
)
|
|
413
|
-
|
|
482
|
+
import numpy as np
|
|
483
|
+
import os
|
|
484
|
+
import plotstyle
|
|
485
|
+
|
|
486
|
+
os.makedirs("submission", exist_ok=True)
|
|
487
|
+
|
|
488
|
+
with plotstyle.use("ieee") as style:
|
|
489
|
+
fig, ax = style.figure(columns=1)
|
|
490
|
+
x = np.linspace(0, 2 * np.pi, 100)
|
|
491
|
+
ax.plot(x, np.sin(x), label="sin(x)")
|
|
492
|
+
ax.set_xlabel("Phase (rad)")
|
|
493
|
+
ax.set_ylabel("Amplitude")
|
|
494
|
+
ax.legend()
|
|
495
|
+
|
|
496
|
+
paths = plotstyle.export_submission(
|
|
497
|
+
fig,
|
|
498
|
+
"figure1",
|
|
499
|
+
journal="ieee",
|
|
500
|
+
author_surname="Smith", # IEEE prepends the surname prefix to filenames
|
|
501
|
+
output_dir="submission/",
|
|
502
|
+
)
|
|
503
|
+
print(paths)
|
|
414
504
|
```
|
|
415
505
|
|
|
416
506
|
```text
|
|
@@ -498,7 +588,7 @@ Nature → Science
|
|
|
498
588
|
──────────────────────────────────────────────────
|
|
499
589
|
Column Width (single): 89.0mm → 86.4mm
|
|
500
590
|
Column Width (double): 183.0mm → 177.8mm
|
|
501
|
-
Max Height: 247.0mm →
|
|
591
|
+
Max Height: 247.0mm → -
|
|
502
592
|
Font Family: Helvetica, Arial → Minion Pro, Benton Sans Condensed
|
|
503
593
|
Min Font Size: 5.0pt → 7.5pt
|
|
504
594
|
Max Font Size: 7.0pt → 10.0pt
|
|
@@ -583,7 +673,7 @@ If PlotStyle helps your research, a citation or star is appreciated:
|
|
|
583
673
|
title = {PlotStyle: Publication-ready scientific figure presets for Matplotlib},
|
|
584
674
|
year = {2026},
|
|
585
675
|
url = {https://github.com/rahulkaushal04/plotstyle},
|
|
586
|
-
note = {Version 1.2.
|
|
676
|
+
note = {Version 1.2.1},
|
|
587
677
|
}
|
|
588
678
|
```
|
|
589
679
|
|
|
@@ -163,45 +163,95 @@ fig.savefig("palette_comparison.png", dpi=150)
|
|
|
163
163
|
Pass `with_markers=True` to get `(color, linestyle, marker)` tuples, useful for journals like IEEE that print in grayscale:
|
|
164
164
|
|
|
165
165
|
```python
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
import numpy as np
|
|
167
|
+
import plotstyle
|
|
168
|
+
|
|
169
|
+
x = np.linspace(0, 2 * np.pi, 100)
|
|
170
|
+
curves = [np.sin(x + i * 0.5) for i in range(4)]
|
|
171
|
+
|
|
172
|
+
with plotstyle.use("ieee") as style:
|
|
173
|
+
fig, ax = style.figure(columns=1)
|
|
174
|
+
styled = plotstyle.palette("ieee", n=4, with_markers=True)
|
|
175
|
+
for i, (color, ls, marker) in enumerate(styled):
|
|
176
|
+
ax.plot(x, curves[i], color=color, linestyle=ls, marker=marker,
|
|
177
|
+
markevery=20, label=f"Series {i + 1}")
|
|
178
|
+
ax.set_xlabel("x")
|
|
179
|
+
ax.set_ylabel("y")
|
|
180
|
+
ax.legend()
|
|
181
|
+
style.savefig(fig, "ieee_markers.pdf")
|
|
169
182
|
```
|
|
170
183
|
|
|
171
184
|
```text
|
|
172
|
-
# styled
|
|
185
|
+
# styled: one (color, linestyle, marker) tuple per series:
|
|
173
186
|
[('#000000', '-', 'o'), ('#333333', '--', 's'), ('#666666', '-.', '^'), ('#999999', ':', 'D')]
|
|
174
187
|
```
|
|
175
188
|
|
|
189
|
+
<p align="center">
|
|
190
|
+
<img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/palette_styled_ieee.png" width="55%" alt="IEEE figure with per-series color, linestyle, and marker combinations">
|
|
191
|
+
</p>
|
|
192
|
+
|
|
176
193
|
---
|
|
177
194
|
|
|
178
195
|
### Overlays
|
|
179
196
|
|
|
180
|
-
Overlays are additive patches that layer on top of a journal preset. They let you adjust one aspect of a figure
|
|
197
|
+
Overlays are additive patches that layer on top of a journal preset. They let you adjust one aspect of a figure (the colour palette, the context, the chart type) without changing the base journal settings.
|
|
181
198
|
|
|
182
199
|
Pass overlay names in the same list as the journal key:
|
|
183
200
|
|
|
184
201
|
```python
|
|
202
|
+
import matplotlib.pyplot as plt
|
|
185
203
|
import plotstyle
|
|
186
204
|
|
|
187
205
|
# Strip top/right spines for a clean editorial look
|
|
188
206
|
with plotstyle.use(["nature", "minimal"]) as style:
|
|
189
207
|
fig, ax = style.figure(columns=1)
|
|
190
|
-
ax.plot([1, 2, 3])
|
|
191
|
-
|
|
208
|
+
ax.plot([1, 2, 3], label="data")
|
|
209
|
+
ax.set_xlabel("x")
|
|
210
|
+
ax.set_ylabel("y")
|
|
211
|
+
ax.legend()
|
|
212
|
+
style.savefig(fig, "minimal_figure.pdf")
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
<p align="center">
|
|
216
|
+
<img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/overlay_minimal.png" width="45%" alt="Nature figure with minimal overlay: no top/right spines">
|
|
217
|
+
</p>
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
import matplotlib.pyplot as plt
|
|
221
|
+
import plotstyle
|
|
192
222
|
|
|
193
223
|
# Larger figure and fonts for Jupyter notebooks
|
|
194
224
|
with plotstyle.use(["nature", "notebook"]) as style:
|
|
195
|
-
import matplotlib.pyplot as plt
|
|
196
225
|
fig, ax = plt.subplots() # plt.subplots() picks up the notebook figsize
|
|
197
|
-
ax.plot([1, 2, 3])
|
|
226
|
+
ax.plot([1, 2, 3], label="data")
|
|
227
|
+
ax.set_xlabel("x")
|
|
228
|
+
ax.set_ylabel("y")
|
|
229
|
+
ax.legend()
|
|
230
|
+
style.savefig(fig, "notebook_figure.pdf")
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
<p align="center">
|
|
234
|
+
<img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/overlay_notebook.png" width="60%" alt="Nature figure with notebook overlay: larger fonts and figure size">
|
|
235
|
+
</p>
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
import matplotlib.pyplot as plt
|
|
239
|
+
import plotstyle
|
|
198
240
|
|
|
199
241
|
# Swap the colour cycle to a specific palette
|
|
200
242
|
with plotstyle.use(["ieee", "okabe-ito"]) as style:
|
|
201
243
|
fig, ax = style.figure(columns=1)
|
|
202
|
-
ax.plot([1, 2, 3])
|
|
244
|
+
ax.plot([1, 2, 3], label="data")
|
|
245
|
+
ax.set_xlabel("x")
|
|
246
|
+
ax.set_ylabel("y")
|
|
247
|
+
ax.legend()
|
|
248
|
+
style.savefig(fig, "okabe_ito_figure.pdf")
|
|
203
249
|
```
|
|
204
250
|
|
|
251
|
+
<p align="center">
|
|
252
|
+
<img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/overlay_okabe_ito.png" width="55%" alt="IEEE figure with okabe-ito colorblind-safe palette">
|
|
253
|
+
</p>
|
|
254
|
+
|
|
205
255
|
| Category | Purpose | Examples |
|
|
206
256
|
|----------|---------|---------|
|
|
207
257
|
| `color` | Swap the colour cycle | `okabe-ito`, `tol-bright`, `safe-grayscale` |
|
|
@@ -272,18 +322,44 @@ with plotstyle.use("nature") as style:
|
|
|
272
322
|
Validate a figure against the journal's requirements, then export in all required formats at once.
|
|
273
323
|
|
|
274
324
|
```python
|
|
325
|
+
import numpy as np
|
|
326
|
+
import matplotlib.pyplot as plt
|
|
327
|
+
import plotstyle
|
|
328
|
+
|
|
329
|
+
x = np.linspace(0, 2 * np.pi, 100)
|
|
330
|
+
|
|
331
|
+
# Outside plotstyle.use() — some checks will fail
|
|
332
|
+
fig, ax = plt.subplots()
|
|
333
|
+
ax.plot(x, np.sin(x), label="sin(x)")
|
|
334
|
+
ax.set_xlabel("Phase (rad)")
|
|
335
|
+
ax.set_ylabel("Amplitude")
|
|
336
|
+
ax.legend()
|
|
337
|
+
|
|
275
338
|
report = plotstyle.validate(fig, journal="nature")
|
|
276
339
|
print(report) # formatted compliance table
|
|
277
|
-
print(report.passed) #
|
|
340
|
+
print(report.passed) # False — rcParams not configured
|
|
278
341
|
|
|
279
342
|
for failure in report.failures:
|
|
280
343
|
print(failure.message) # what failed
|
|
281
344
|
print(failure.fix_suggestion) # how to fix it
|
|
345
|
+
plt.close(fig)
|
|
346
|
+
|
|
347
|
+
# Inside plotstyle.use() — all checks pass
|
|
348
|
+
with plotstyle.use("nature") as style:
|
|
349
|
+
fig, ax = style.figure(columns=1)
|
|
350
|
+
ax.plot(x, np.sin(x), label="sin(x)")
|
|
351
|
+
ax.set_xlabel("Phase (rad)")
|
|
352
|
+
ax.set_ylabel("Amplitude")
|
|
353
|
+
ax.legend()
|
|
354
|
+
|
|
355
|
+
report = plotstyle.validate(fig, journal="nature")
|
|
356
|
+
print(report)
|
|
357
|
+
print(report.passed) # True
|
|
282
358
|
```
|
|
283
359
|
|
|
284
360
|
```text
|
|
285
361
|
┌──────────────────────────────────────────────────────┐
|
|
286
|
-
│ PlotStyle Validation Report
|
|
362
|
+
│ PlotStyle Validation Report: Nature │
|
|
287
363
|
├──────────┬───────────────────────────────────────────┤
|
|
288
364
|
│ ✓ PASS │ Figure width 89.0mm matches single colu...│
|
|
289
365
|
│ ✓ PASS │ Figure height 55.0mm is within the Natu...│
|
|
@@ -306,7 +382,7 @@ When called inside `plotstyle.use()`, all checks pass:
|
|
|
306
382
|
|
|
307
383
|
```text
|
|
308
384
|
┌──────────────────────────────────────────────────────┐
|
|
309
|
-
│ PlotStyle Validation Report
|
|
385
|
+
│ PlotStyle Validation Report: Nature │
|
|
310
386
|
├──────────┬───────────────────────────────────────────┤
|
|
311
387
|
│ ✓ PASS │ Figure width 89.0mm matches single colu...│
|
|
312
388
|
│ ✓ PASS │ Figure height 55.0mm is within the Natu...│
|
|
@@ -322,14 +398,28 @@ passed: True
|
|
|
322
398
|
```
|
|
323
399
|
|
|
324
400
|
```python
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
)
|
|
332
|
-
|
|
401
|
+
import numpy as np
|
|
402
|
+
import os
|
|
403
|
+
import plotstyle
|
|
404
|
+
|
|
405
|
+
os.makedirs("submission", exist_ok=True)
|
|
406
|
+
|
|
407
|
+
with plotstyle.use("ieee") as style:
|
|
408
|
+
fig, ax = style.figure(columns=1)
|
|
409
|
+
x = np.linspace(0, 2 * np.pi, 100)
|
|
410
|
+
ax.plot(x, np.sin(x), label="sin(x)")
|
|
411
|
+
ax.set_xlabel("Phase (rad)")
|
|
412
|
+
ax.set_ylabel("Amplitude")
|
|
413
|
+
ax.legend()
|
|
414
|
+
|
|
415
|
+
paths = plotstyle.export_submission(
|
|
416
|
+
fig,
|
|
417
|
+
"figure1",
|
|
418
|
+
journal="ieee",
|
|
419
|
+
author_surname="Smith", # IEEE prepends the surname prefix to filenames
|
|
420
|
+
output_dir="submission/",
|
|
421
|
+
)
|
|
422
|
+
print(paths)
|
|
333
423
|
```
|
|
334
424
|
|
|
335
425
|
```text
|
|
@@ -417,7 +507,7 @@ Nature → Science
|
|
|
417
507
|
──────────────────────────────────────────────────
|
|
418
508
|
Column Width (single): 89.0mm → 86.4mm
|
|
419
509
|
Column Width (double): 183.0mm → 177.8mm
|
|
420
|
-
Max Height: 247.0mm →
|
|
510
|
+
Max Height: 247.0mm → -
|
|
421
511
|
Font Family: Helvetica, Arial → Minion Pro, Benton Sans Condensed
|
|
422
512
|
Min Font Size: 5.0pt → 7.5pt
|
|
423
513
|
Max Font Size: 7.0pt → 10.0pt
|
|
@@ -502,7 +592,7 @@ If PlotStyle helps your research, a citation or star is appreciated:
|
|
|
502
592
|
title = {PlotStyle: Publication-ready scientific figure presets for Matplotlib},
|
|
503
593
|
year = {2026},
|
|
504
594
|
url = {https://github.com/rahulkaushal04/plotstyle},
|
|
505
|
-
note = {Version 1.2.
|
|
595
|
+
note = {Version 1.2.1},
|
|
506
596
|
}
|
|
507
597
|
```
|
|
508
598
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""PlotStyle
|
|
1
|
+
"""PlotStyle: scientific journal figure style presets for Matplotlib.
|
|
2
2
|
|
|
3
3
|
Key entry points: ``figure`` / ``subplots`` to create journal-sized figures,
|
|
4
4
|
``use`` to apply a journal's rcParams preset, ``validate`` to check a figure
|
|
@@ -89,7 +89,7 @@ def build_overlay_snapshot(overlay: StyleOverlay) -> dict[str, Any]:
|
|
|
89
89
|
def register_all_styles() -> None:
|
|
90
90
|
"""Inject all plotstyle journal presets and overlays into ``matplotlib.style.core.library``.
|
|
91
91
|
|
|
92
|
-
Called once at ``import plotstyle``. Re-calling is safe
|
|
92
|
+
Called once at ``import plotstyle``. Re-calling is safe; existing keys
|
|
93
93
|
are overwritten with identical values. Wrapped in a broad ``try/except``
|
|
94
94
|
in the caller so a matplotlib internal API change never breaks the import.
|
|
95
95
|
|
|
@@ -115,7 +115,7 @@ def register_all_styles() -> None:
|
|
|
115
115
|
for key in registry.list_available():
|
|
116
116
|
full_key = f"{_PREFIX}{key}"
|
|
117
117
|
with contextlib.suppress(Exception):
|
|
118
|
-
library[full_key] = build_style_snapshot(registry.get(key))
|
|
118
|
+
library[full_key] = build_style_snapshot(registry.get(key, _silent=True))
|
|
119
119
|
registered_journal_keys.add(full_key)
|
|
120
120
|
|
|
121
121
|
for key in overlay_registry.list_available():
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 2,
|
|
21
|
+
__version__ = version = '1.2.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 2, 1)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -185,7 +185,7 @@ def _cmd_validate(file: str, journal: str) -> int:
|
|
|
185
185
|
hits = verify_embedded(path)
|
|
186
186
|
type3_found = any(h.get("type") == "Type3" for h in hits)
|
|
187
187
|
if type3_found:
|
|
188
|
-
print("✗ FAIL Type 3 fonts detected
|
|
188
|
+
print("✗ FAIL Type 3 fonts detected: submission systems may reject this.")
|
|
189
189
|
else:
|
|
190
190
|
print("✓ PASS No Type 3 fonts detected (TrueType embedding OK).")
|
|
191
191
|
else:
|
|
@@ -292,7 +292,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
292
292
|
"""Build and return the top-level argument parser with all sub-commands."""
|
|
293
293
|
parser = argparse.ArgumentParser(
|
|
294
294
|
prog="plotstyle",
|
|
295
|
-
description="PlotStyle
|
|
295
|
+
description="PlotStyle: journal-compliant Matplotlib figure toolkit",
|
|
296
296
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
297
297
|
epilog=(
|
|
298
298
|
"Examples:\n"
|
|
@@ -398,7 +398,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
398
398
|
description=(
|
|
399
399
|
"Prints a ready-to-run Python snippet that calls "
|
|
400
400
|
"plotstyle.export_submission() with the requested settings. "
|
|
401
|
-
"No file is created
|
|
401
|
+
"No file is created; re-export requires the original Matplotlib "
|
|
402
402
|
"Figure object, which cannot be recovered from a saved file."
|
|
403
403
|
),
|
|
404
404
|
)
|