plotstyle 1.2.2__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.2 → plotstyle-1.2.3}/.gitignore +2 -0
  2. {plotstyle-1.2.2 → plotstyle-1.2.3}/CHANGELOG.md +26 -1
  3. {plotstyle-1.2.2 → plotstyle-1.2.3}/PKG-INFO +58 -15
  4. {plotstyle-1.2.2 → plotstyle-1.2.3}/README.md +57 -14
  5. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/_version.py +2 -2
  6. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/cli/main.py +2 -0
  7. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/core/style.py +8 -0
  8. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/engine/rcparams.py +22 -3
  9. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/preview/gallery.py +2 -2
  10. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/nature.toml +1 -0
  11. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/schema.py +26 -0
  12. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_core/test_style.py +107 -0
  13. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_engine/test_rcparams.py +177 -3
  14. {plotstyle-1.2.2 → plotstyle-1.2.3}/LICENSE +0 -0
  15. {plotstyle-1.2.2 → plotstyle-1.2.3}/pyproject.toml +0 -0
  16. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/__init__.py +0 -0
  17. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/_compat/__init__.py +0 -0
  18. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/_compat/mpl_style.py +0 -0
  19. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/_utils/__init__.py +0 -0
  20. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/_utils/io.py +0 -0
  21. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/_utils/warnings.py +0 -0
  22. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/cli/__init__.py +0 -0
  23. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/__init__.py +0 -0
  24. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/_rendering.py +0 -0
  25. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/accessibility.py +0 -0
  26. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/okabe_ito.json +0 -0
  27. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/safe_grayscale.json +0 -0
  28. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_bright.json +0 -0
  29. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_high_contrast.json +0 -0
  30. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_light.json +0 -0
  31. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_muted.json +0 -0
  32. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_10.json +0 -0
  33. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_12.json +0 -0
  34. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_4.json +0 -0
  35. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_6.json +0 -0
  36. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_rainbow_8.json +0 -0
  37. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/data/tol_vibrant.json +0 -0
  38. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/grayscale.py +0 -0
  39. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/color/palettes.py +0 -0
  40. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/core/__init__.py +0 -0
  41. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/core/export.py +0 -0
  42. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/core/figure.py +0 -0
  43. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/core/migrate.py +0 -0
  44. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/engine/__init__.py +0 -0
  45. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/engine/fonts.py +0 -0
  46. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/engine/latex.py +0 -0
  47. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/integrations/__init__.py +0 -0
  48. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/integrations/seaborn.py +0 -0
  49. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/__init__.py +0 -0
  50. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/bar.toml +0 -0
  51. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/cjk-japanese.toml +0 -0
  52. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/cjk-korean.toml +0 -0
  53. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/cjk-simplified.toml +0 -0
  54. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/cjk-traditional.toml +0 -0
  55. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/grid.toml +0 -0
  56. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/high-vis.toml +0 -0
  57. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/latex-sans.toml +0 -0
  58. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/minimal.toml +0 -0
  59. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/no-latex.toml +0 -0
  60. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/notebook.toml +0 -0
  61. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/okabe-ito.toml +0 -0
  62. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/pgf.toml +0 -0
  63. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/presentation.toml +0 -0
  64. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/russian.toml +0 -0
  65. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/safe-grayscale.toml +0 -0
  66. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/scatter.toml +0 -0
  67. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/schema.py +0 -0
  68. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-bright.toml +0 -0
  69. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-high-contrast.toml +0 -0
  70. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-light.toml +0 -0
  71. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-muted.toml +0 -0
  72. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-10.toml +0 -0
  73. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-12.toml +0 -0
  74. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-4.toml +0 -0
  75. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-6.toml +0 -0
  76. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-rainbow-8.toml +0 -0
  77. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/tol-vibrant.toml +0 -0
  78. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/overlays/turkish.toml +0 -0
  79. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/preview/__init__.py +0 -0
  80. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/preview/print_size.py +0 -0
  81. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/py.typed +0 -0
  82. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/__init__.py +0 -0
  83. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/_templates.toml +0 -0
  84. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/acs.toml +0 -0
  85. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/cell.toml +0 -0
  86. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/elsevier.toml +0 -0
  87. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/ieee.toml +0 -0
  88. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/plos.toml +0 -0
  89. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/prl.toml +0 -0
  90. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/science.toml +0 -0
  91. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/springer.toml +0 -0
  92. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/units.py +0 -0
  93. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/specs/wiley.toml +0 -0
  94. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/__init__.py +0 -0
  95. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/checks/__init__.py +0 -0
  96. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/checks/_base.py +0 -0
  97. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/checks/colors.py +0 -0
  98. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/checks/dimensions.py +0 -0
  99. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/checks/export.py +0 -0
  100. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/checks/lines.py +0 -0
  101. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/checks/typography.py +0 -0
  102. {plotstyle-1.2.2 → plotstyle-1.2.3}/src/plotstyle/validation/report.py +0 -0
  103. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/conftest.py +0 -0
  104. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_cli/test_main.py +0 -0
  105. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_color/test_accessibility.py +0 -0
  106. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_color/test_grayscale.py +0 -0
  107. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_color/test_palettes.py +0 -0
  108. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_color/test_rendering.py +0 -0
  109. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_core/test_export.py +0 -0
  110. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_core/test_figure.py +0 -0
  111. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_core/test_migrate.py +0 -0
  112. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_engine/test_fonts.py +0 -0
  113. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_engine/test_latex.py +0 -0
  114. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_integrations/test_seaborn.py +0 -0
  115. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_preview/test_gallery.py +0 -0
  116. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_preview/test_print_size.py +0 -0
  117. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_specs/test_registry.py +0 -0
  118. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_specs/test_schema.py +0 -0
  119. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_specs/test_units.py +0 -0
  120. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_utils/test_io.py +0 -0
  121. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_utils/test_warnings.py +0 -0
  122. {plotstyle-1.2.2 → plotstyle-1.2.3}/tests/test_validation/test_checks.py +0 -0
  123. {plotstyle-1.2.2 → 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,30 @@ _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
+
16
40
  ## [1.2.2] - 2026-04-27
17
41
 
18
42
  Patch release: docs improvements, README example quality, and CI action bump.
@@ -172,7 +196,8 @@ First public alpha release.
172
196
  - **Dynamic versioning**: version derived from git tags via `hatch-vcs` and `importlib.metadata`.
173
197
  - **CI/CD pipeline**: GitHub Actions workflows for lint, type-check, test matrix, and automated PyPI release via OIDC Trusted Publishing.
174
198
 
175
- [Unreleased]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.2...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
176
201
  [1.2.2]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.1...v1.2.2
177
202
  [1.2.1]: https://github.com/rahulkaushal04/plotstyle/compare/v1.2.0...v1.2.1
178
203
  [1.2.0]: https://github.com/rahulkaushal04/plotstyle/compare/v1.1.0...v1.2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotstyle
3
- Version: 1.2.2
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
 
@@ -415,7 +425,7 @@ import plotstyle
415
425
 
416
426
  x = np.linspace(0, 2 * np.pi, 100)
417
427
 
418
- # Outside plotstyle.use() some checks will fail
428
+ # Outside plotstyle.use(): some checks will fail
419
429
  fig, ax = plt.subplots()
420
430
  ax.plot(x, np.sin(x), label="sin(x)")
421
431
  ax.set_xlabel("Phase (rad)")
@@ -424,14 +434,14 @@ ax.legend()
424
434
 
425
435
  report = plotstyle.validate(fig, journal="nature")
426
436
  print(report) # formatted compliance table
427
- print(report.passed) # False rcParams not configured
437
+ print(report.passed) # False, rcParams not configured
428
438
 
429
439
  for failure in report.failures:
430
440
  print(failure.message) # what failed
431
441
  print(failure.fix_suggestion) # how to fix it
432
442
  plt.close(fig)
433
443
 
434
- # Inside plotstyle.use() all checks pass
444
+ # Inside plotstyle.use(): all checks pass
435
445
  with plotstyle.use("nature") as style:
436
446
  fig, ax = style.figure(columns=1)
437
447
  ax.plot(x, np.sin(x), label="sin(x)")
@@ -660,7 +670,34 @@ Full documentation at **[plotstyle.readthedocs.io](https://plotstyle.readthedocs
660
670
  - [CLI reference](https://plotstyle.readthedocs.io/en/stable/cli.html)
661
671
  - [FAQ](https://plotstyle.readthedocs.io/en/stable/faq.html)
662
672
 
663
- 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 |
664
701
 
665
702
  ---
666
703
 
@@ -668,21 +705,27 @@ Working examples are in the [`examples/`](examples/) directory.
668
705
 
669
706
  See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, adding journal specs, and pull request guidelines.
670
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
+
671
722
  ---
672
723
 
673
724
  ## Citation
674
725
 
675
- If PlotStyle helps your research, a citation or star is appreciated:
726
+ If PlotStyle helps your research, a citation or star is appreciated.
676
727
 
677
- ```bibtex
678
- @misc{plotstyle,
679
- author = {Kaushal, Rahul},
680
- title = {PlotStyle: Publication-ready scientific figure presets for Matplotlib},
681
- year = {2026},
682
- url = {https://github.com/rahulkaushal04/plotstyle},
683
- note = {Version 1.2.2},
684
- }
685
- ```
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.
686
729
 
687
730
  ---
688
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
 
@@ -334,7 +344,7 @@ import plotstyle
334
344
 
335
345
  x = np.linspace(0, 2 * np.pi, 100)
336
346
 
337
- # Outside plotstyle.use() some checks will fail
347
+ # Outside plotstyle.use(): some checks will fail
338
348
  fig, ax = plt.subplots()
339
349
  ax.plot(x, np.sin(x), label="sin(x)")
340
350
  ax.set_xlabel("Phase (rad)")
@@ -343,14 +353,14 @@ ax.legend()
343
353
 
344
354
  report = plotstyle.validate(fig, journal="nature")
345
355
  print(report) # formatted compliance table
346
- print(report.passed) # False rcParams not configured
356
+ print(report.passed) # False, rcParams not configured
347
357
 
348
358
  for failure in report.failures:
349
359
  print(failure.message) # what failed
350
360
  print(failure.fix_suggestion) # how to fix it
351
361
  plt.close(fig)
352
362
 
353
- # Inside plotstyle.use() all checks pass
363
+ # Inside plotstyle.use(): all checks pass
354
364
  with plotstyle.use("nature") as style:
355
365
  fig, ax = style.figure(columns=1)
356
366
  ax.plot(x, np.sin(x), label="sin(x)")
@@ -579,7 +589,34 @@ Full documentation at **[plotstyle.readthedocs.io](https://plotstyle.readthedocs
579
589
  - [CLI reference](https://plotstyle.readthedocs.io/en/stable/cli.html)
580
590
  - [FAQ](https://plotstyle.readthedocs.io/en/stable/faq.html)
581
591
 
582
- 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 |
583
620
 
584
621
  ---
585
622
 
@@ -587,21 +624,27 @@ Working examples are in the [`examples/`](examples/) directory.
587
624
 
588
625
  See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, adding journal specs, and pull request guidelines.
589
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
+
590
641
  ---
591
642
 
592
643
  ## Citation
593
644
 
594
- If PlotStyle helps your research, a citation or star is appreciated:
645
+ If PlotStyle helps your research, a citation or star is appreciated.
595
646
 
596
- ```bibtex
597
- @misc{plotstyle,
598
- author = {Kaushal, Rahul},
599
- title = {PlotStyle: Publication-ready scientific figure presets for Matplotlib},
600
- year = {2026},
601
- url = {https://github.com/rahulkaushal04/plotstyle},
602
- note = {Version 1.2.2},
603
- }
604
- ```
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.
605
648
 
606
649
  ---
607
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.2'
22
- __version_tuple__ = version_tuple = (1, 2, 2)
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} "
@@ -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"]
@@ -538,6 +538,12 @@ class TypographySpec:
538
538
  Font weight for panel labels (e.g. ``"bold"``).
539
539
  panel_label_case : str
540
540
  Case transformation for panel labels (e.g. ``"lower"``, ``"upper"``).
541
+ target_font_pt : float | None
542
+ Recommended rendering font size in points, when the journal's
543
+ guidelines state a preferred target distinct from the midpoint of
544
+ ``[min_font_pt, max_font_pt]``. ``None`` when absent from the TOML,
545
+ in which case ``build_rcparams`` falls back to the midpoint heuristic.
546
+ Must be within ``[min_font_pt, max_font_pt]`` when set.
541
547
  """
542
548
 
543
549
  font_family: list[str]
@@ -547,6 +553,7 @@ class TypographySpec:
547
553
  panel_label_pt: float
548
554
  panel_label_weight: str
549
555
  panel_label_case: str
556
+ target_font_pt: float | None = None
550
557
 
551
558
 
552
559
  @dataclass(frozen=True, slots=True)
@@ -872,6 +879,24 @@ class JournalSpec:
872
879
  f"must be ≥ min_font_pt ({min_pt}), got {max_pt}",
873
880
  )
874
881
 
882
+ # target_font_pt is optional. When present it must be a non-negative
883
+ # float within the journal's compliance range [min_pt, max_pt].
884
+ target_pt: float | None = None
885
+ if "target_font_pt" in raw:
886
+ raw_target = raw["target_font_pt"]
887
+ try:
888
+ target_pt = float(raw_target)
889
+ except (TypeError, ValueError):
890
+ raise FieldTypeError(t, "target_font_pt", "float", raw_target) from None
891
+ if target_pt < 0.0:
892
+ raise FieldValueError(t, "target_font_pt", f"must be ≥ 0, got {target_pt}")
893
+ if not (min_pt <= target_pt <= max_pt):
894
+ raise FieldValueError(
895
+ t,
896
+ "target_font_pt",
897
+ f"must be within [min_font_pt={min_pt}, max_font_pt={max_pt}], got {target_pt}",
898
+ )
899
+
875
900
  return TypographySpec(
876
901
  font_family=_cast_str_list(
877
902
  raw,
@@ -890,6 +915,7 @@ class JournalSpec:
890
915
  panel_label_case=_cast_str(
891
916
  raw, t, "panel_label_case", default="lower", allowed=_KNOWN_LABEL_CASES
892
917
  ),
918
+ target_font_pt=target_pt,
893
919
  )
894
920
 
895
921
  @staticmethod
@@ -740,6 +740,113 @@ class TestJournalStyleRestore:
740
740
  # ---------------------------------------------------------------------------
741
741
 
742
742
 
743
+ # ===========================================================================
744
+ # use(): journal color cycle
745
+ # ===========================================================================
746
+
747
+
748
+ class TestUseColorCycle:
749
+ """Verify that use() applies the journal-recommended default color cycle."""
750
+
751
+ @pytest.mark.filterwarnings("ignore::plotstyle._utils.warnings.SpecAssumptionWarning")
752
+ @pytest.mark.filterwarnings("ignore::plotstyle._utils.warnings.FontFallbackWarning")
753
+ def test_nature_gets_okabe_ito_palette(self) -> None:
754
+ """
755
+ Description: use('nature') must apply okabe_ito as the default color
756
+ cycle. The JOURNAL_PALETTE_MAP maps 'nature' to okabe_ito.
757
+ Scenario: Call use('nature') and inspect axes.prop_cycle.
758
+ Expectation: The cycle colors match the okabe_ito palette.
759
+ """
760
+ from plotstyle.color.palettes import JOURNAL_PALETTE_MAP, load_palette
761
+
762
+ expected = load_palette(JOURNAL_PALETTE_MAP["nature"])
763
+ style = use("nature")
764
+ try:
765
+ actual = [item["color"] for item in mpl.rcParams["axes.prop_cycle"]]
766
+ assert actual == expected
767
+ finally:
768
+ style.restore()
769
+
770
+ @pytest.mark.filterwarnings("ignore::plotstyle._utils.warnings.SpecAssumptionWarning")
771
+ @pytest.mark.filterwarnings("ignore::plotstyle._utils.warnings.FontFallbackWarning")
772
+ def test_ieee_gets_safe_grayscale_palette(self) -> None:
773
+ """
774
+ Description: use('ieee') must apply safe_grayscale by default. IEEE
775
+ requires colorblind-safe and grayscale-compatible figures;
776
+ the matplotlib default blue-orange-green cycle would fail.
777
+ Scenario: Call use('ieee') and inspect axes.prop_cycle.
778
+ Expectation: The cycle colors match the safe_grayscale palette.
779
+ """
780
+ from plotstyle.color.palettes import JOURNAL_PALETTE_MAP, load_palette
781
+
782
+ expected = load_palette(JOURNAL_PALETTE_MAP["ieee"])
783
+ style = use("ieee")
784
+ try:
785
+ actual = [item["color"] for item in mpl.rcParams["axes.prop_cycle"]]
786
+ assert actual == expected
787
+ finally:
788
+ style.restore()
789
+
790
+ @pytest.mark.filterwarnings("ignore::plotstyle._utils.warnings.SpecAssumptionWarning")
791
+ @pytest.mark.filterwarnings("ignore::plotstyle._utils.warnings.FontFallbackWarning")
792
+ def test_color_overlay_overrides_default_palette(self) -> None:
793
+ """
794
+ Description: An explicit color overlay applied after use() must win
795
+ over the journal's default palette. Overlay precedence
796
+ must be preserved.
797
+ Scenario: use(['nature', 'tol-bright']) - tol-bright colors differ
798
+ from nature's default okabe-ito.
799
+ Expectation: The cycle reflects tol-bright, not okabe-ito.
800
+ """
801
+ from plotstyle.color.palettes import load_palette
802
+
803
+ tol_bright = load_palette("tol_bright")
804
+ with use(["nature", "tol-bright"]) as _style:
805
+ actual = [item["color"] for item in mpl.rcParams["axes.prop_cycle"]]
806
+ assert actual == tol_bright
807
+
808
+ @pytest.mark.filterwarnings("ignore::plotstyle._utils.warnings.FontFallbackWarning")
809
+ def test_overlay_only_mode_does_not_apply_palette(self) -> None:
810
+ """
811
+ Description: When use() is called with overlays only (no journal key),
812
+ no palette is applied from JOURNAL_PALETTE_MAP.
813
+ Scenario: use(['notebook']) - no journal key.
814
+ Expectation: axes.prop_cycle is unchanged from before the call.
815
+ """
816
+ before = list(mpl.rcParams["axes.prop_cycle"])
817
+ with use(["notebook"]):
818
+ after = list(mpl.rcParams["axes.prop_cycle"])
819
+ assert after == before
820
+
821
+
822
+ # ===========================================================================
823
+ # use(): font size target
824
+ # ===========================================================================
825
+
826
+
827
+ class TestUseFontSizeTarget:
828
+ """Verify that use('nature') applies 7 pt (target) not 6 pt (midpoint)."""
829
+
830
+ @pytest.mark.filterwarnings("ignore::plotstyle._utils.warnings.FontFallbackWarning")
831
+ def test_nature_font_size_is_7pt(self) -> None:
832
+ """
833
+ Description: Nature's TOML sets target_font_pt=7.0. build_rcparams
834
+ must use 7 pt, not the 6 pt midpoint of the 5-7 pt range.
835
+ Scenario: use('nature') and read font.size.
836
+ Expectation: mpl.rcParams['font.size'] == 7.0.
837
+ """
838
+ style = use("nature")
839
+ try:
840
+ assert mpl.rcParams["font.size"] == pytest.approx(7.0)
841
+ finally:
842
+ style.restore()
843
+
844
+
845
+ # ===========================================================================
846
+ # Public API
847
+ # ===========================================================================
848
+
849
+
743
850
  class TestPublicAPI:
744
851
  """Validate the module's public API surface."""
745
852