plotstyle 1.2.1__tar.gz → 1.2.3__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 (123) hide show
  1. {plotstyle-1.2.1 → plotstyle-1.2.3}/.gitignore +2 -0
  2. {plotstyle-1.2.1 → plotstyle-1.2.3}/CHANGELOG.md +53 -1
  3. {plotstyle-1.2.1 → plotstyle-1.2.3}/PKG-INFO +75 -25
  4. {plotstyle-1.2.1 → plotstyle-1.2.3}/README.md +74 -24
  5. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/_version.py +2 -2
  6. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/cli/main.py +2 -0
  7. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/_rendering.py +2 -3
  8. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/core/style.py +8 -0
  9. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/engine/rcparams.py +22 -3
  10. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/preview/gallery.py +2 -2
  11. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/nature.toml +1 -0
  12. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/schema.py +26 -0
  13. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_core/test_style.py +107 -0
  14. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_engine/test_rcparams.py +177 -3
  15. {plotstyle-1.2.1 → plotstyle-1.2.3}/LICENSE +0 -0
  16. {plotstyle-1.2.1 → plotstyle-1.2.3}/pyproject.toml +0 -0
  17. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/__init__.py +0 -0
  18. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/_compat/__init__.py +0 -0
  19. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/_compat/mpl_style.py +0 -0
  20. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/_utils/__init__.py +0 -0
  21. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/_utils/io.py +0 -0
  22. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/_utils/warnings.py +0 -0
  23. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/cli/__init__.py +0 -0
  24. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/__init__.py +0 -0
  25. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/accessibility.py +0 -0
  26. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/okabe_ito.json +0 -0
  27. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/safe_grayscale.json +0 -0
  28. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_bright.json +0 -0
  29. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_high_contrast.json +0 -0
  30. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_light.json +0 -0
  31. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_muted.json +0 -0
  32. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_10.json +0 -0
  33. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_12.json +0 -0
  34. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_4.json +0 -0
  35. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_6.json +0 -0
  36. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_8.json +0 -0
  37. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_vibrant.json +0 -0
  38. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/grayscale.py +0 -0
  39. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/color/palettes.py +0 -0
  40. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/core/__init__.py +0 -0
  41. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/core/export.py +0 -0
  42. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/core/figure.py +0 -0
  43. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/core/migrate.py +0 -0
  44. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/engine/__init__.py +0 -0
  45. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/engine/fonts.py +0 -0
  46. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/engine/latex.py +0 -0
  47. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/integrations/__init__.py +0 -0
  48. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/integrations/seaborn.py +0 -0
  49. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/__init__.py +0 -0
  50. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/bar.toml +0 -0
  51. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/cjk-japanese.toml +0 -0
  52. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/cjk-korean.toml +0 -0
  53. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/cjk-simplified.toml +0 -0
  54. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/cjk-traditional.toml +0 -0
  55. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/grid.toml +0 -0
  56. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/high-vis.toml +0 -0
  57. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/latex-sans.toml +0 -0
  58. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/minimal.toml +0 -0
  59. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/no-latex.toml +0 -0
  60. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/notebook.toml +0 -0
  61. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/okabe-ito.toml +0 -0
  62. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/pgf.toml +0 -0
  63. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/presentation.toml +0 -0
  64. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/russian.toml +0 -0
  65. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/safe-grayscale.toml +0 -0
  66. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/scatter.toml +0 -0
  67. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/schema.py +0 -0
  68. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-bright.toml +0 -0
  69. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-high-contrast.toml +0 -0
  70. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-light.toml +0 -0
  71. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-muted.toml +0 -0
  72. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-10.toml +0 -0
  73. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-12.toml +0 -0
  74. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-4.toml +0 -0
  75. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-6.toml +0 -0
  76. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-8.toml +0 -0
  77. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-vibrant.toml +0 -0
  78. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/overlays/turkish.toml +0 -0
  79. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/preview/__init__.py +0 -0
  80. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/preview/print_size.py +0 -0
  81. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/py.typed +0 -0
  82. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/__init__.py +0 -0
  83. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/_templates.toml +0 -0
  84. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/acs.toml +0 -0
  85. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/cell.toml +0 -0
  86. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/elsevier.toml +0 -0
  87. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/ieee.toml +0 -0
  88. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/plos.toml +0 -0
  89. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/prl.toml +0 -0
  90. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/science.toml +0 -0
  91. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/springer.toml +0 -0
  92. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/units.py +0 -0
  93. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/specs/wiley.toml +0 -0
  94. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/__init__.py +0 -0
  95. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/checks/__init__.py +0 -0
  96. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/checks/_base.py +0 -0
  97. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/checks/colors.py +0 -0
  98. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/checks/dimensions.py +0 -0
  99. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/checks/export.py +0 -0
  100. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/checks/lines.py +0 -0
  101. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/checks/typography.py +0 -0
  102. {plotstyle-1.2.1 → plotstyle-1.2.3}/src/plotstyle/validation/report.py +0 -0
  103. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/conftest.py +0 -0
  104. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_cli/test_main.py +0 -0
  105. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_color/test_accessibility.py +0 -0
  106. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_color/test_grayscale.py +0 -0
  107. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_color/test_palettes.py +0 -0
  108. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_color/test_rendering.py +0 -0
  109. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_core/test_export.py +0 -0
  110. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_core/test_figure.py +0 -0
  111. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_core/test_migrate.py +0 -0
  112. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_engine/test_fonts.py +0 -0
  113. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_engine/test_latex.py +0 -0
  114. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_integrations/test_seaborn.py +0 -0
  115. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_preview/test_gallery.py +0 -0
  116. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_preview/test_print_size.py +0 -0
  117. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_specs/test_registry.py +0 -0
  118. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_specs/test_schema.py +0 -0
  119. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_specs/test_units.py +0 -0
  120. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_utils/test_io.py +0 -0
  121. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_utils/test_warnings.py +0 -0
  122. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_validation/test_checks.py +0 -0
  123. {plotstyle-1.2.1 → plotstyle-1.2.3}/tests/test_validation/test_report.py +0 -0
@@ -160,3 +160,5 @@ secrets.json
160
160
 
161
161
  # local files
162
162
  local/
163
+
164
+ .claude
@@ -13,6 +13,56 @@ _Nothing yet._
13
13
 
14
14
  ---
15
15
 
16
+ ## [1.2.3] - 2026-04-30
17
+
18
+ Minor release: automatic journal color cycle, `target_font_pt` typography field, Nature-specific rcParams, CLI improvements, a full documentation and example audit, and a new doc image generation script.
19
+
20
+ ### Added
21
+
22
+ - **Automatic journal palette as default color cycle** (`plotstyle.use()`): calling `use("nature")` (or any journal key) now sets the journal's recommended palette as `axes.prop_cycle` automatically. Every `ax.plot()`, `ax.bar()`, and `ax.scatter()` call draws from it without any `color=` argument. A color overlay applied in the same `use()` call overrides this default.
23
+ - **`target_font_pt` field on `TypographySpec`**: optional `float | None` field that records a journal's explicitly stated target font size (as opposed to only a min/max range). When set, `build_rcparams()` uses it as `font.size` instead of the midpoint of the range. `nature.toml` sets `target_font_pt = 7.0` (Nature's guidelines explicitly state 7 pt as the standard text size).
24
+ - **`plotstyle info` CLI shows `Target size:`**: when `target_font_pt` is set for a journal, the `plotstyle info <journal>` command now prints a `Target size:` line under Typography.
25
+ - **Nature-specific tick and legend rcParams** (`build_rcparams()`): the Nature preset now applies inward-facing ticks (`xtick.direction: in`, `ytick.direction: in`), minor ticks visible on all axes, mirrored tick marks (`xtick.top: True`, `ytick.right: True`), and `legend.frameon: False` - matching Nature's published figure style guidelines.
26
+ - **`scripts/generate_docs_images.py`**: new script that regenerates all 9 static PNG images used in the documentation (`docs/images/`) from the current codebase in one headless run.
27
+ - **Docs images regenerated**: all 9 images in `docs/images/` rebuilt using the updated codebase - `quickstart_nature.png`, `multi_panel_science.png`, `palette_comparison.png`, `accessibility_colorblind.png`, `accessibility_grayscale.png`, `gallery_nature.png`, `gallery_ieee.png`, `seaborn_scatter_nature.png`, `overlay_bar.png`.
28
+ - **New test coverage**: `TestUseColorCycle` (automatic palette cycle), `TestUseFontSizeTarget` (target_font_pt font size selection), `TestBuildRcparamsLegend` (Nature legend.frameon), and `TestBuildRcparamsTicks` (Nature inward/mirrored tick rcParams).
29
+
30
+ ### Changed
31
+
32
+ - **`examples/03_color_palettes.py`**: added Section 1 demonstrating the automatic default color cycle; renumbered remaining sections 2-6.
33
+ - **`examples/05_validation.py`**: added `is_failure` / `is_warning` convenience property usage.
34
+ - **`examples/09_registry_and_spec.py`**: expanded to cover `target_font_pt`, `is_official`, `assumed_fields`, and `registry.preload()`.
35
+ - **`examples/12_overlays.py`**: added color overlay, grid rendering overlay, scatter + IEEE warning, overlay inspection, and `list_overlays()` with category filter. Imports reorganized to comply with E402 (module-level imports at top); unused loop variable renamed to `_ls` to comply with B007.
36
+ - **Docs**: all docs updated to reflect the automatic palette cycle and `target_font_pt` changes; `colour` spelling standardized to `color` throughout.
37
+
38
+ ---
39
+
40
+ ## [1.2.2] - 2026-04-27
41
+
42
+ Patch release: docs improvements, README example quality, and CI action bump.
43
+
44
+ ### Added
45
+
46
+ - **`LatexNotFoundError` catch pattern in API docs** (`docs/api/style.md`): new "Catching LaTeX errors" section shows how to import and handle `LatexNotFoundError` directly, with a note on catching the base `RuntimeError` as an alternative.
47
+ - **`examples/output/accessibility_deuteranopia.png`**: new reference output image generated by the `simulate_cvd` section of `04_accessibility_checks.py`.
48
+
49
+ ### Changed
50
+
51
+ - **README overlay examples use realistic data**: notebook and okabe-ito overlay snippets now use `np.linspace` / `np.sin` / `np.cos` plots instead of trivial `[1, 2, 3]` lists; axes labels updated to match.
52
+ - **README overlay snippet import cleanup**: removed stray `import matplotlib.pyplot as plt` from the minimal overlay example where it was unused.
53
+ - **README validation report output updated**: sample terminal output now reflects a two-column figure width rather than a single-column one.
54
+ - **README `diff` output adds `Avoid: none`**: accessibility block in the `plotstyle diff` sample output now shows the `Avoid` field.
55
+ - **`download-artifact` action bumped to v8** in `.github/workflows/release.yml` (was v4).
56
+ - **Version references bumped to 1.2.2** in `README.md` (citation note) and `docs/installation.md` (version-check snippet).
57
+
58
+ ### Fixed
59
+
60
+ - **HiDPI/Retina crash in `_fig_to_rgb_array`** (`src/plotstyle/color/_rendering.py`): `get_width_height()` now passes `physical=True` so the returned pixel dimensions match the `buffer_rgba()` byte count on high-DPI displays, preventing a `ValueError` during the reshape.
61
+ - **Same HiDPI fix in `simulate_cvd` example** (`examples/04_accessibility_checks.py`): the inline canvas-to-array snippet now uses `get_width_height(physical=True)` to stay consistent with the library fix above.
62
+ - **Typo in `06_export_submission.py` docstring**: `"smit_"` author prefix corrected to `"smith_"`.
63
+
64
+ ---
65
+
16
66
  ## [1.2.1] - 2026-04-26
17
67
 
18
68
  Patch release: `simulate_cvd` example, warning quality improvements, and docs/example content fixes.
@@ -146,7 +196,9 @@ First public alpha release.
146
196
  - **Dynamic versioning**: version derived from git tags via `hatch-vcs` and `importlib.metadata`.
147
197
  - **CI/CD pipeline**: GitHub Actions workflows for lint, type-check, test matrix, and automated PyPI release via OIDC Trusted Publishing.
148
198
 
149
- [Unreleased]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.1...HEAD
199
+ [Unreleased]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.3...HEAD
200
+ [1.2.3]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.2...v1.2.3
201
+ [1.2.2]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.1...v1.2.2
150
202
  [1.2.1]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.0...v1.2.1
151
203
  [1.2.0]: https://github.com/rahulkaushal04/plotstyle/compare/v1.1.0...v1.2.0
152
204
  [1.1.0]: https://github.com/rahulkaushal04/plotstyle/compare/v1.0.0...v1.1.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotstyle
3
- Version: 1.2.1
3
+ Version: 1.2.3
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
@@ -99,6 +99,14 @@ Description-Content-Type: text/markdown
99
99
 
100
100
  **PlotStyle** makes it easy to produce Matplotlib figures that meet the exact typographic, dimensional, and export requirements of major academic journals. It also integrates with Seaborn, with more integrations planned. Pick a journal, create your figure, save it. PlotStyle handles the rest.
101
101
 
102
+ <p align="center">
103
+ <img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/before_after.png" width="90%" alt="Left: default Matplotlib output. Right: the same figure styled with plotstyle.use('nature').">
104
+ </p>
105
+
106
+ <p align="center">
107
+ <em>Left: default Matplotlib. Right: <code>plotstyle.use("nature")</code>. Same data, same code.</em>
108
+ </p>
109
+
102
110
  ---
103
111
 
104
112
  ## Table of Contents
@@ -115,6 +123,8 @@ Description-Content-Type: text/markdown
115
123
  - [CLI](#cli)
116
124
  - [Documentation](#documentation)
117
125
  - [Contributing](#contributing)
126
+ - [Code of Conduct](#code-of-conduct)
127
+ - [Security](#security)
118
128
  - [Citation](#citation)
119
129
  - [License](#license)
120
130
 
@@ -280,7 +290,6 @@ Overlays are additive patches that layer on top of a journal preset. They let yo
280
290
  Pass overlay names in the same list as the journal key:
281
291
 
282
292
  ```python
283
- import matplotlib.pyplot as plt
284
293
  import plotstyle
285
294
 
286
295
  # Strip top/right spines for a clean editorial look
@@ -298,15 +307,19 @@ with plotstyle.use(["nature", "minimal"]) as style:
298
307
  </p>
299
308
 
300
309
  ```python
310
+ import numpy as np
301
311
  import matplotlib.pyplot as plt
302
312
  import plotstyle
303
313
 
314
+ x = np.linspace(0, 2 * np.pi, 100)
315
+
304
316
  # Larger figure and fonts for Jupyter notebooks
305
317
  with plotstyle.use(["nature", "notebook"]) as style:
306
318
  fig, ax = plt.subplots() # plt.subplots() picks up the notebook figsize
307
- ax.plot([1, 2, 3], label="data")
308
- ax.set_xlabel("x")
309
- ax.set_ylabel("y")
319
+ ax.plot(x, np.sin(x), label="sin(x)")
320
+ ax.plot(x, np.cos(x), label="cos(x)")
321
+ ax.set_xlabel("Phase (rad)")
322
+ ax.set_ylabel("Amplitude")
310
323
  ax.legend()
311
324
  style.savefig(fig, "notebook_figure.pdf")
312
325
  ```
@@ -316,13 +329,16 @@ with plotstyle.use(["nature", "notebook"]) as style:
316
329
  </p>
317
330
 
318
331
  ```python
319
- import matplotlib.pyplot as plt
332
+ import numpy as np
320
333
  import plotstyle
321
334
 
335
+ x = np.linspace(0, 2 * np.pi, 100)
336
+
322
337
  # Swap the colour cycle to a specific palette
323
338
  with plotstyle.use(["ieee", "okabe-ito"]) as style:
324
339
  fig, ax = style.figure(columns=1)
325
- ax.plot([1, 2, 3], label="data")
340
+ for i in range(4):
341
+ ax.plot(x, np.sin(x + i * 0.5), label=f"Series {i + 1}")
326
342
  ax.set_xlabel("x")
327
343
  ax.set_ylabel("y")
328
344
  ax.legend()
@@ -409,7 +425,7 @@ import plotstyle
409
425
 
410
426
  x = np.linspace(0, 2 * np.pi, 100)
411
427
 
412
- # Outside plotstyle.use() some checks will fail
428
+ # Outside plotstyle.use(): some checks will fail
413
429
  fig, ax = plt.subplots()
414
430
  ax.plot(x, np.sin(x), label="sin(x)")
415
431
  ax.set_xlabel("Phase (rad)")
@@ -418,14 +434,14 @@ ax.legend()
418
434
 
419
435
  report = plotstyle.validate(fig, journal="nature")
420
436
  print(report) # formatted compliance table
421
- print(report.passed) # False rcParams not configured
437
+ print(report.passed) # False, rcParams not configured
422
438
 
423
439
  for failure in report.failures:
424
440
  print(failure.message) # what failed
425
441
  print(failure.fix_suggestion) # how to fix it
426
442
  plt.close(fig)
427
443
 
428
- # Inside plotstyle.use() all checks pass
444
+ # Inside plotstyle.use(): all checks pass
429
445
  with plotstyle.use("nature") as style:
430
446
  fig, ax = style.figure(columns=1)
431
447
  ax.plot(x, np.sin(x), label="sin(x)")
@@ -442,15 +458,15 @@ with plotstyle.use("nature") as style:
442
458
  ┌──────────────────────────────────────────────────────┐
443
459
  │ PlotStyle Validation Report: Nature │
444
460
  ├──────────┬───────────────────────────────────────────┤
445
- PASS │ Figure width 89.0mm matches single colu...│
446
- │ ✓ PASS │ Figure height 55.0mm is within the Natu...│
461
+ FAIL │ Figure width 162.6mm does not match Nat...│
462
+ │ ✓ PASS │ Figure height 121.9mm is within the Nat...│
447
463
  │ ✗ FAIL │ pdf.fonttype = 3; must be 42 for TrueTy...│
448
464
  │ ✗ FAIL │ ps.fonttype = 3; must be 42 for TrueTyp...│
449
465
  │ ⚠ WARN │ savefig.dpi = 'figure'; Nature requires...│
450
466
  │ ✓ PASS │ All plotted lines and spines meet the N...│
451
- │ ✗ FAIL │ 14 text element(s) outside the Nature r...│
467
+ │ ✗ FAIL │ 23 text element(s) outside the Nature r...│
452
468
  └──────────┴───────────────────────────────────────────┘
453
- 3/7 checks passed, 1 warning(s), 3 failure(s)
469
+ 2/7 checks passed, 1 warning(s), 4 failure(s)
454
470
 
455
471
  passed: False
456
472
 
@@ -580,6 +596,7 @@ Export:
580
596
  Accessibility:
581
597
  Colorblind safe: Not required
582
598
  Grayscale safe: Not required
599
+ Avoid: none
583
600
  ```
584
601
 
585
602
  **`plotstyle diff nature science`**
@@ -653,7 +670,34 @@ Full documentation at **[plotstyle.readthedocs.io](https://plotstyle.readthedocs
653
670
  - [CLI reference](https://plotstyle.readthedocs.io/en/stable/cli.html)
654
671
  - [FAQ](https://plotstyle.readthedocs.io/en/stable/faq.html)
655
672
 
656
- Working examples are in the [`examples/`](examples/) directory.
673
+ Working examples are in the [`examples/`](https://github.com/rahulkaushal04/plotstyle/tree/main/examples/) directory:
674
+
675
+ | Example | What it covers |
676
+ |---------|----------------|
677
+ | [`01_quickstart.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/01_quickstart.py) | Apply a journal preset, create a figure, and save |
678
+ | [`02_multi_panel_figure.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/02_multi_panel_figure.py) | Multi-panel layouts with automatic panel labels |
679
+ | [`03_color_palettes.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/03_color_palettes.py) | Journal palettes, grayscale-safe markers, `apply_palette` |
680
+ | [`04_accessibility_checks.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/04_accessibility_checks.py) | Colorblind simulation and grayscale print-safety |
681
+ | [`05_validation.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/05_validation.py) | Validate a figure against journal requirements |
682
+ | [`06_export_submission.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/06_export_submission.py) | Export in all required formats for submission |
683
+ | [`07_spec_diff_and_migrate.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/07_spec_diff_and_migrate.py) | Compare journals and migrate a figure between them |
684
+ | [`08_gallery_preview.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/08_gallery_preview.py) | Discover journals and preview their styles |
685
+ | [`09_registry_and_spec.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/09_registry_and_spec.py) | Inspect journal specs from the registry |
686
+ | [`10_context_manager_patterns.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/10_context_manager_patterns.py) | Patterns for managing rcParam lifetime |
687
+ | [`11_seaborn_integration.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/11_seaborn_integration.py) | Keep PlotStyle settings intact with Seaborn |
688
+ | [`12_overlays.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/12_overlays.py) | Overlays: context, color, and plot-type |
689
+ | [`14_print_size_preview.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/14_print_size_preview.py) | Preview a figure at its true physical print size |
690
+ | [`15_matplotlib_native_styles.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/15_matplotlib_native_styles.py) | Use PlotStyle presets with `plt.style` |
691
+ | [`16_latex_and_fonts.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/16_latex_and_fonts.py) | LaTeX modes and font availability checks |
692
+
693
+ Interactive Jupyter notebooks are in [`examples/notebooks/`](https://github.com/rahulkaushal04/plotstyle/tree/main/examples/notebooks/):
694
+
695
+ | Notebook | What it covers |
696
+ |----------|----------------|
697
+ | [`01_quickstart.ipynb`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/notebooks/01_quickstart.ipynb) | Full quickstart: style, figure, palette, validate, save, overlays |
698
+ | [`02_accessibility_and_validation.ipynb`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/notebooks/02_accessibility_and_validation.ipynb) | Colorblind and grayscale previews, validation reports |
699
+ | [`03_journal_comparison_and_migration.ipynb`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/notebooks/03_journal_comparison_and_migration.ipynb) | Diff journals and migrate figures between them |
700
+ | [`04_overlays.ipynb`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/notebooks/04_overlays.ipynb) | Overlays in depth: context, color, plot-type, combining |
657
701
 
658
702
  ---
659
703
 
@@ -661,21 +705,27 @@ Working examples are in the [`examples/`](examples/) directory.
661
705
 
662
706
  See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, adding journal specs, and pull request guidelines.
663
707
 
708
+ All contributors are expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md).
709
+
710
+ ---
711
+
712
+ ## Code of Conduct
713
+
714
+ This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this standard.
715
+
716
+ ---
717
+
718
+ ## Security
719
+
720
+ To report a security vulnerability, use [GitHub's private vulnerability reporting](https://github.com/rahulkaushal04/plotstyle/security/advisories/new) rather than opening a public issue. See [SECURITY.md](SECURITY.md) for scope, timeline, and disclosure guidelines.
721
+
664
722
  ---
665
723
 
666
724
  ## Citation
667
725
 
668
- If PlotStyle helps your research, a citation or star is appreciated:
726
+ If PlotStyle helps your research, a citation or star is appreciated.
669
727
 
670
- ```bibtex
671
- @misc{plotstyle,
672
- author = {Kaushal, Rahul},
673
- title = {PlotStyle: Publication-ready scientific figure presets for Matplotlib},
674
- year = {2026},
675
- url = {https://github.com/rahulkaushal04/plotstyle},
676
- note = {Version 1.2.1},
677
- }
678
- ```
728
+ Use the **"Cite this repository"** button on the GitHub sidebar to get a ready-to-use APA or BibTeX entry. It reads from [`CITATION.cff`](CITATION.cff) and is always up to date.
679
729
 
680
730
  ---
681
731
 
@@ -18,6 +18,14 @@
18
18
 
19
19
  **PlotStyle** makes it easy to produce Matplotlib figures that meet the exact typographic, dimensional, and export requirements of major academic journals. It also integrates with Seaborn, with more integrations planned. Pick a journal, create your figure, save it. PlotStyle handles the rest.
20
20
 
21
+ <p align="center">
22
+ <img src="https://raw.githubusercontent.com/rahulkaushal04/plotstyle/main/examples/output/before_after.png" width="90%" alt="Left: default Matplotlib output. Right: the same figure styled with plotstyle.use('nature').">
23
+ </p>
24
+
25
+ <p align="center">
26
+ <em>Left: default Matplotlib. Right: <code>plotstyle.use("nature")</code>. Same data, same code.</em>
27
+ </p>
28
+
21
29
  ---
22
30
 
23
31
  ## Table of Contents
@@ -34,6 +42,8 @@
34
42
  - [CLI](#cli)
35
43
  - [Documentation](#documentation)
36
44
  - [Contributing](#contributing)
45
+ - [Code of Conduct](#code-of-conduct)
46
+ - [Security](#security)
37
47
  - [Citation](#citation)
38
48
  - [License](#license)
39
49
 
@@ -199,7 +209,6 @@ Overlays are additive patches that layer on top of a journal preset. They let yo
199
209
  Pass overlay names in the same list as the journal key:
200
210
 
201
211
  ```python
202
- import matplotlib.pyplot as plt
203
212
  import plotstyle
204
213
 
205
214
  # Strip top/right spines for a clean editorial look
@@ -217,15 +226,19 @@ with plotstyle.use(["nature", "minimal"]) as style:
217
226
  </p>
218
227
 
219
228
  ```python
229
+ import numpy as np
220
230
  import matplotlib.pyplot as plt
221
231
  import plotstyle
222
232
 
233
+ x = np.linspace(0, 2 * np.pi, 100)
234
+
223
235
  # Larger figure and fonts for Jupyter notebooks
224
236
  with plotstyle.use(["nature", "notebook"]) as style:
225
237
  fig, ax = plt.subplots() # plt.subplots() picks up the notebook figsize
226
- ax.plot([1, 2, 3], label="data")
227
- ax.set_xlabel("x")
228
- ax.set_ylabel("y")
238
+ ax.plot(x, np.sin(x), label="sin(x)")
239
+ ax.plot(x, np.cos(x), label="cos(x)")
240
+ ax.set_xlabel("Phase (rad)")
241
+ ax.set_ylabel("Amplitude")
229
242
  ax.legend()
230
243
  style.savefig(fig, "notebook_figure.pdf")
231
244
  ```
@@ -235,13 +248,16 @@ with plotstyle.use(["nature", "notebook"]) as style:
235
248
  </p>
236
249
 
237
250
  ```python
238
- import matplotlib.pyplot as plt
251
+ import numpy as np
239
252
  import plotstyle
240
253
 
254
+ x = np.linspace(0, 2 * np.pi, 100)
255
+
241
256
  # Swap the colour cycle to a specific palette
242
257
  with plotstyle.use(["ieee", "okabe-ito"]) as style:
243
258
  fig, ax = style.figure(columns=1)
244
- ax.plot([1, 2, 3], label="data")
259
+ for i in range(4):
260
+ ax.plot(x, np.sin(x + i * 0.5), label=f"Series {i + 1}")
245
261
  ax.set_xlabel("x")
246
262
  ax.set_ylabel("y")
247
263
  ax.legend()
@@ -328,7 +344,7 @@ import plotstyle
328
344
 
329
345
  x = np.linspace(0, 2 * np.pi, 100)
330
346
 
331
- # Outside plotstyle.use() some checks will fail
347
+ # Outside plotstyle.use(): some checks will fail
332
348
  fig, ax = plt.subplots()
333
349
  ax.plot(x, np.sin(x), label="sin(x)")
334
350
  ax.set_xlabel("Phase (rad)")
@@ -337,14 +353,14 @@ ax.legend()
337
353
 
338
354
  report = plotstyle.validate(fig, journal="nature")
339
355
  print(report) # formatted compliance table
340
- print(report.passed) # False rcParams not configured
356
+ print(report.passed) # False, rcParams not configured
341
357
 
342
358
  for failure in report.failures:
343
359
  print(failure.message) # what failed
344
360
  print(failure.fix_suggestion) # how to fix it
345
361
  plt.close(fig)
346
362
 
347
- # Inside plotstyle.use() all checks pass
363
+ # Inside plotstyle.use(): all checks pass
348
364
  with plotstyle.use("nature") as style:
349
365
  fig, ax = style.figure(columns=1)
350
366
  ax.plot(x, np.sin(x), label="sin(x)")
@@ -361,15 +377,15 @@ with plotstyle.use("nature") as style:
361
377
  ┌──────────────────────────────────────────────────────┐
362
378
  │ PlotStyle Validation Report: Nature │
363
379
  ├──────────┬───────────────────────────────────────────┤
364
- PASS │ Figure width 89.0mm matches single colu...│
365
- │ ✓ PASS │ Figure height 55.0mm is within the Natu...│
380
+ FAIL │ Figure width 162.6mm does not match Nat...│
381
+ │ ✓ PASS │ Figure height 121.9mm is within the Nat...│
366
382
  │ ✗ FAIL │ pdf.fonttype = 3; must be 42 for TrueTy...│
367
383
  │ ✗ FAIL │ ps.fonttype = 3; must be 42 for TrueTyp...│
368
384
  │ ⚠ WARN │ savefig.dpi = 'figure'; Nature requires...│
369
385
  │ ✓ PASS │ All plotted lines and spines meet the N...│
370
- │ ✗ FAIL │ 14 text element(s) outside the Nature r...│
386
+ │ ✗ FAIL │ 23 text element(s) outside the Nature r...│
371
387
  └──────────┴───────────────────────────────────────────┘
372
- 3/7 checks passed, 1 warning(s), 3 failure(s)
388
+ 2/7 checks passed, 1 warning(s), 4 failure(s)
373
389
 
374
390
  passed: False
375
391
 
@@ -499,6 +515,7 @@ Export:
499
515
  Accessibility:
500
516
  Colorblind safe: Not required
501
517
  Grayscale safe: Not required
518
+ Avoid: none
502
519
  ```
503
520
 
504
521
  **`plotstyle diff nature science`**
@@ -572,7 +589,34 @@ Full documentation at **[plotstyle.readthedocs.io](https://plotstyle.readthedocs
572
589
  - [CLI reference](https://plotstyle.readthedocs.io/en/stable/cli.html)
573
590
  - [FAQ](https://plotstyle.readthedocs.io/en/stable/faq.html)
574
591
 
575
- Working examples are in the [`examples/`](examples/) directory.
592
+ Working examples are in the [`examples/`](https://github.com/rahulkaushal04/plotstyle/tree/main/examples/) directory:
593
+
594
+ | Example | What it covers |
595
+ |---------|----------------|
596
+ | [`01_quickstart.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/01_quickstart.py) | Apply a journal preset, create a figure, and save |
597
+ | [`02_multi_panel_figure.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/02_multi_panel_figure.py) | Multi-panel layouts with automatic panel labels |
598
+ | [`03_color_palettes.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/03_color_palettes.py) | Journal palettes, grayscale-safe markers, `apply_palette` |
599
+ | [`04_accessibility_checks.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/04_accessibility_checks.py) | Colorblind simulation and grayscale print-safety |
600
+ | [`05_validation.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/05_validation.py) | Validate a figure against journal requirements |
601
+ | [`06_export_submission.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/06_export_submission.py) | Export in all required formats for submission |
602
+ | [`07_spec_diff_and_migrate.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/07_spec_diff_and_migrate.py) | Compare journals and migrate a figure between them |
603
+ | [`08_gallery_preview.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/08_gallery_preview.py) | Discover journals and preview their styles |
604
+ | [`09_registry_and_spec.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/09_registry_and_spec.py) | Inspect journal specs from the registry |
605
+ | [`10_context_manager_patterns.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/10_context_manager_patterns.py) | Patterns for managing rcParam lifetime |
606
+ | [`11_seaborn_integration.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/11_seaborn_integration.py) | Keep PlotStyle settings intact with Seaborn |
607
+ | [`12_overlays.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/12_overlays.py) | Overlays: context, color, and plot-type |
608
+ | [`14_print_size_preview.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/14_print_size_preview.py) | Preview a figure at its true physical print size |
609
+ | [`15_matplotlib_native_styles.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/15_matplotlib_native_styles.py) | Use PlotStyle presets with `plt.style` |
610
+ | [`16_latex_and_fonts.py`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/16_latex_and_fonts.py) | LaTeX modes and font availability checks |
611
+
612
+ Interactive Jupyter notebooks are in [`examples/notebooks/`](https://github.com/rahulkaushal04/plotstyle/tree/main/examples/notebooks/):
613
+
614
+ | Notebook | What it covers |
615
+ |----------|----------------|
616
+ | [`01_quickstart.ipynb`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/notebooks/01_quickstart.ipynb) | Full quickstart: style, figure, palette, validate, save, overlays |
617
+ | [`02_accessibility_and_validation.ipynb`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/notebooks/02_accessibility_and_validation.ipynb) | Colorblind and grayscale previews, validation reports |
618
+ | [`03_journal_comparison_and_migration.ipynb`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/notebooks/03_journal_comparison_and_migration.ipynb) | Diff journals and migrate figures between them |
619
+ | [`04_overlays.ipynb`](https://github.com/rahulkaushal04/plotstyle/blob/main/examples/notebooks/04_overlays.ipynb) | Overlays in depth: context, color, plot-type, combining |
576
620
 
577
621
  ---
578
622
 
@@ -580,21 +624,27 @@ Working examples are in the [`examples/`](examples/) directory.
580
624
 
581
625
  See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, adding journal specs, and pull request guidelines.
582
626
 
627
+ All contributors are expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md).
628
+
629
+ ---
630
+
631
+ ## Code of Conduct
632
+
633
+ This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this standard.
634
+
635
+ ---
636
+
637
+ ## Security
638
+
639
+ To report a security vulnerability, use [GitHub's private vulnerability reporting](https://github.com/rahulkaushal04/plotstyle/security/advisories/new) rather than opening a public issue. See [SECURITY.md](SECURITY.md) for scope, timeline, and disclosure guidelines.
640
+
583
641
  ---
584
642
 
585
643
  ## Citation
586
644
 
587
- If PlotStyle helps your research, a citation or star is appreciated:
645
+ If PlotStyle helps your research, a citation or star is appreciated.
588
646
 
589
- ```bibtex
590
- @misc{plotstyle,
591
- author = {Kaushal, Rahul},
592
- title = {PlotStyle: Publication-ready scientific figure presets for Matplotlib},
593
- year = {2026},
594
- url = {https://github.com/rahulkaushal04/plotstyle},
595
- note = {Version 1.2.1},
596
- }
597
- ```
647
+ Use the **"Cite this repository"** button on the GitHub sidebar to get a ready-to-use APA or BibTeX entry. It reads from [`CITATION.cff`](CITATION.cff) and is always up to date.
598
648
 
599
649
  ---
600
650
 
@@ -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.1'
22
- __version_tuple__ = version_tuple = (1, 2, 1)
21
+ __version__ = version = '1.2.3'
22
+ __version_tuple__ = version_tuple = (1, 2, 3)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -82,6 +82,8 @@ def _cmd_info(journal: str) -> int:
82
82
  print("Typography:")
83
83
  print(f" Font: {fonts} (fallback: {typo.font_fallback})")
84
84
  print(f" Size range: {typo.min_font_pt}-{typo.max_font_pt}pt")
85
+ if typo.target_font_pt is not None:
86
+ print(f" Target size: {typo.target_font_pt}pt")
85
87
  print(
86
88
  f" Panel labels: {typo.panel_label_pt}pt "
87
89
  f"{typo.panel_label_weight} {typo.panel_label_case} "
@@ -30,9 +30,8 @@ def _fig_to_rgb_array(fig: Figure) -> NDArray[np.uint8]:
30
30
  """
31
31
  fig.canvas.draw()
32
32
 
33
- # get_width_height() reads actual canvas pixel dimensions; avoids
34
- # off-by-one from float rounding in int(fig_in * dpi).
35
- width, height = fig.canvas.get_width_height()
33
+ # physical=True matches the buffer_rgba() byte count on HiDPI/Retina screens.
34
+ width, height = fig.canvas.get_width_height(physical=True)
36
35
 
37
36
  # buffer_rgba() returns a read-only memoryview; .copy() makes it writeable
38
37
  rgba = np.frombuffer(fig.canvas.buffer_rgba(), dtype=np.uint8).reshape(height, width, 4)
@@ -771,6 +771,14 @@ def use(
771
771
  if journal_key is not None:
772
772
  spec = registry.get(journal_key)
773
773
  params = build_rcparams(spec, latex=effective_latex)
774
+
775
+ from cycler import cycler as _cycler
776
+
777
+ from plotstyle.color.palettes import JOURNAL_PALETTE_MAP, load_palette
778
+
779
+ _palette_name = JOURNAL_PALETTE_MAP.get(journal_key)
780
+ if _palette_name:
781
+ params["axes.prop_cycle"] = _cycler("color", load_palette(_palette_name))
774
782
  else:
775
783
  spec = None
776
784
  use_latex = _resolve_latex_mode(effective_latex)
@@ -174,7 +174,13 @@ def build_rcparams(
174
174
  font_name = spec.typography.font_fallback
175
175
 
176
176
  figsize = _compute_figure_size(spec)
177
- font_size = _compute_base_font_size(spec)
177
+ # Use the journal's explicit target when available; fall back to the
178
+ # midpoint heuristic for specs that only publish a compliance range.
179
+ font_size = (
180
+ spec.typography.target_font_pt
181
+ if spec.typography.target_font_pt is not None
182
+ else _compute_base_font_size(spec)
183
+ )
178
184
 
179
185
  params: dict[str, Any] = {
180
186
  "pdf.fonttype": _FONTTYPE_TRUETYPE,
@@ -194,12 +200,25 @@ def build_rcparams(
194
200
  "xtick.labelsize": font_size,
195
201
  "ytick.labelsize": font_size,
196
202
  "legend.fontsize": font_size,
197
- # Clamped to physically reproducible minimums; thinner lines vanish in print.
198
203
  "lines.linewidth": max(spec.line.min_weight_pt, 1.0),
199
204
  "axes.linewidth": max(spec.line.min_weight_pt, 0.5),
200
- # "none" keeps text editable in SVG; "path" converts to outlines (more portable).
201
205
  "svg.fonttype": "none" if spec.export.editable_text else "path",
202
206
  "axes.grid": False,
207
+ "legend.frameon": False,
208
+ "xtick.direction": "in",
209
+ "xtick.major.size": 3.0,
210
+ "xtick.major.width": 0.5,
211
+ "xtick.minor.size": 1.5,
212
+ "xtick.minor.width": 0.5,
213
+ "xtick.minor.visible": True,
214
+ "xtick.top": True,
215
+ "ytick.direction": "in",
216
+ "ytick.major.size": 3.0,
217
+ "ytick.major.width": 0.5,
218
+ "ytick.minor.size": 1.5,
219
+ "ytick.minor.width": 0.5,
220
+ "ytick.minor.visible": True,
221
+ "ytick.right": True,
203
222
  }
204
223
  )
205
224
 
@@ -69,7 +69,7 @@ def _draw_line_panel(ax: Axes) -> None:
69
69
  ax.plot(x, y, label=f"Series {i + 1}")
70
70
  ax.set_xlabel("x")
71
71
  ax.set_ylabel("y")
72
- ax.legend(fontsize="small")
72
+ ax.legend(fontsize="small", loc="upper right")
73
73
  ax.set_title("Line Plot", fontsize="small")
74
74
 
75
75
 
@@ -81,7 +81,7 @@ def _draw_scatter_panel(ax: Axes) -> None:
81
81
  ax.scatter(x[mask], y[mask], label=str(group_label), s=15, alpha=0.8)
82
82
  ax.set_xlabel("x")
83
83
  ax.set_ylabel("y")
84
- ax.legend(fontsize="small")
84
+ ax.legend(fontsize="small", loc="lower right")
85
85
  ax.set_title("Scatter Plot", fontsize="small")
86
86
 
87
87
 
@@ -15,6 +15,7 @@ font_family = ["Helvetica", "Arial"]
15
15
  font_fallback = "sans-serif"
16
16
  min_font_pt = 5.0
17
17
  max_font_pt = 7.0
18
+ target_font_pt = 7.0
18
19
 
19
20
  [export]
20
21
  preferred_formats = ["ai", "eps", "pdf"]