Skip to main content

Matplotlib/seaborn style presets matching scientific journal requirements, with validation, export safety, and preview capabilities.

Project description

plotstyle

Matplotlib figures formatted for journal submission, automatically.

PyPI version Python versions License: MIT CI Docs


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.


Table of Contents


Installation

Requires Python 3.10+ and Matplotlib >= 3.9.

pip install plotstyle

Optional extras:

pip install "plotstyle[color]"     # colorblind / grayscale previews
pip install "plotstyle[seaborn]"   # seaborn integration
pip install "plotstyle[all]"       # everything

Quick Start

import numpy as np
import plotstyle

with plotstyle.use("nature") as style:
    fig, ax = style.figure(columns=1)   # sized to Nature's single-column width (89 mm)

    x = np.linspace(0, 2 * np.pi, 200)
    ax.plot(x, np.sin(x), label="sin(x)")
    ax.plot(x, np.cos(x), label="cos(x)")
    ax.set_xlabel("Phase (rad)")
    ax.set_ylabel("Amplitude (a.u.)")
    ax.legend()

    style.savefig(fig, "figure.pdf")    # 300 DPI minimum, TrueType fonts embedded

Quickstart output: sin and cos figure styled for Nature

The with block is the recommended pattern. Matplotlib's rcParams are restored automatically when it exits, even if an exception occurs.


Examples

Multi-panel figures

style.subplots() works like plt.subplots() but sizes the figure to the journal spec and adds panel labels automatically, styled to each journal's convention (A, B, C for Science; a, b, c for Nature; (a), (b), (c) for IEEE).

import numpy as np
import plotstyle

rng = np.random.default_rng(42)

with plotstyle.use("science") as style:
    fig, axes = style.subplots(nrows=2, ncols=2, columns=2)

    x = np.linspace(0, 10, 100)
    axes[0, 0].plot(x, np.sin(x), label="sin")
    axes[0, 0].plot(x, np.cos(x), label="cos")
    axes[0, 0].set_xlabel("x")
    axes[0, 0].set_ylabel("f(x)")
    axes[0, 0].legend()

    xs = rng.normal(0, 1, 60)
    ys = 0.7 * xs + rng.normal(0, 0.3, 60)
    axes[0, 1].scatter(xs, ys, s=12, alpha=0.7)
    axes[0, 1].set_xlabel("Variable X")
    axes[0, 1].set_ylabel("Variable Y")

    axes[1, 0].bar(["A", "B", "C", "D"], [3.2, 5.8, 4.1, 6.5])
    axes[1, 0].set_xlabel("Category")
    axes[1, 0].set_ylabel("Count")

    axes[1, 1].hist(rng.normal(0, 1, 500), bins=25, edgecolor="white", linewidth=0.5)
    axes[1, 1].set_xlabel("Value")
    axes[1, 1].set_ylabel("Frequency")

    style.savefig(fig, "multi_panel.pdf")

2x2 multi-panel Science figure with automatic panel labels A B C D

axes is always a 2-D NumPy array. Use axes[0, 0] to access a single panel or axes.flat to iterate. Pass panels=False to suppress the automatic labels.


Color palettes

Each journal has a recommended colorblind-safe palette. plotstyle.palette() returns hex color strings, cycling if you need more than the palette length.

import matplotlib.pyplot as plt
import plotstyle

journals = ["nature", "science", "ieee", "acs"]
fig, axes = plt.subplots(len(journals), 1, figsize=(6, 0.6 * len(journals)))

for ax, journal in zip(axes, journals):
    pal = plotstyle.palette(journal, n=8)
    for i, color in enumerate(pal):
        ax.barh(0, 1, left=i, color=color, edgecolor="none", height=0.8)
    ax.set_xlim(0, 8)
    ax.set_yticks([])
    ax.set_ylabel(journal, rotation=0, ha="right", va="center")
    ax.set_xticks([])

fig.suptitle("Journal Color Palettes")
fig.tight_layout()
fig.savefig("palette_comparison.png", dpi=150)

Color swatch comparison for Nature, Science, IEEE, and ACS palettes

Pass with_markers=True to get (color, linestyle, marker) tuples, useful for journals like IEEE that print in grayscale:

styled = plotstyle.palette("ieee", n=4, with_markers=True)
for color, ls, marker in styled:
    ax.plot(x, y, color=color, linestyle=ls, marker=marker)

Colorblind and grayscale previews

Build a figure, then simulate how it looks under color vision deficiency or grayscale printing before you submit.

import numpy as np
import plotstyle

with plotstyle.use("nature") as style:
    colors = style.palette(n=4)
    fig, ax = style.figure(columns=1)
    x = np.linspace(0, 5, 80)
    for i, c in enumerate(colors):
        ax.plot(x, np.sin(x + i), color=c, linewidth=1.5, label=f"Series {i + 1}")
    ax.set_xlabel("Time (s)")
    ax.set_ylabel("Signal")
    ax.legend()

    cvd_fig = plotstyle.preview_colorblind(fig)
    cvd_fig.savefig("accessibility_colorblind.png", dpi=150, bbox_inches="tight")

Colorblind simulation: original, deuteranopia, protanopia, tritanopia

    gray_fig = plotstyle.preview_grayscale(fig)
    gray_fig.savefig("accessibility_grayscale.png", dpi=150, bbox_inches="tight")

Grayscale simulation: original vs grayscale rendering


Validation and submission export

Validate a figure against the journal's requirements, then export in all required formats at once.

report = plotstyle.validate(fig, journal="nature")
print(report)          # formatted compliance table
print(report.passed)   # True if everything is OK

for failure in report.failures:
    print(failure.message)         # what failed
    print(failure.fix_suggestion)  # how to fix it
paths = plotstyle.export_submission(
    fig,
    "figure1",
    journal="ieee",
    author_surname="Smith",     # IEEE prepends the surname prefix to filenames
    output_dir="submission/",
)
# Produces: submission/smith_figure1.pdf (and any other IEEE-required formats)

Supported Journals

Key Journal Publisher
acs ACS (JACS) American Chemical Society
cell Cell Cell Press
elsevier Elsevier Elsevier
ieee IEEE Transactions IEEE
nature Nature Springer Nature
plos PLOS ONE Public Library of Science
prl Physical Review Letters American Physical Society
science Science AAAS
springer Springer Springer
wiley Wiley Wiley

Need another journal? See CONTRIBUTING.md.


CLI

plotstyle list                                 # list all journal presets
plotstyle info <journal>                       # show spec details
plotstyle diff <journal_a> <journal_b>         # compare two journals
plotstyle fonts --journal <journal>            # check font availability
plotstyle validate <file> --journal <journal>  # validate a saved figure
plotstyle export <file> --journal <journal>    # print snippet for re-exporting

Documentation

Full documentation at plotstyle.readthedocs.io:

Working examples are in the examples/ directory.


Contributing

See CONTRIBUTING.md for development setup, adding journal specs, and pull request guidelines.


Citation

If PlotStyle helps your research, a citation or star is appreciated:

@misc{plotstyle,
  author  = {Kaushal, Rahul},
  title   = {PlotStyle: Publication-ready scientific figure presets for Matplotlib},
  year    = {2026},
  url     = {https://github.com/rahulkaushal04/plotstyle},
  note    = {Version 1.1.0},
}

License

MIT © 2026 Rahul Kaushal

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

plotstyle-1.1.0.tar.gz (191.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

plotstyle-1.1.0-py3-none-any.whl (83.4 kB view details)

Uploaded Python 3

File details

Details for the file plotstyle-1.1.0.tar.gz.

File metadata

  • Download URL: plotstyle-1.1.0.tar.gz
  • Upload date:
  • Size: 191.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for plotstyle-1.1.0.tar.gz
Algorithm Hash digest
SHA256 942d9e3ae6205be43e50b11c261f77f25f4511946f0a1bd619eb33d70ae9c323
MD5 9b476302adb23f3850fc2cdfb07dd1c2
BLAKE2b-256 c53a7d58ce0c47ce500d47f17bf7cde6fcee55b13f0cae522e240c5df1f132cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for plotstyle-1.1.0.tar.gz:

Publisher: release.yml on rahulkaushal04/plotstyle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file plotstyle-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: plotstyle-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 83.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for plotstyle-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e7c4cc3d4aac47a90d09d3de651f86f8cf8a07cff3f1a1d5aabdcec98ecae818
MD5 0e756e1dab36ca2c5d3ce90634093fcb
BLAKE2b-256 fd71c95856d17ca3af2a23ce427cf562e50c5145482ba534baa4063de78b9e9a

See more details on using hashes here.

Provenance

The following attestation bundles were made for plotstyle-1.1.0-py3-none-any.whl:

Publisher: release.yml on rahulkaushal04/plotstyle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page