Skip to main content

Generic matplotlib brand/corporate-design framework — patcher, pyplot hooks, style registry, and pandas hook for building company-specific plot packages

Project description

PyPI Python License matplotlib Ruff uv ty prek

mpl-brandpacker

Package your brand design into a matplotlib.pyplot drop-in replacement. Define titles, headers styling, colors, and axes styling as Python classes — mpl-brandpacker handles the patching so your_brand.pyplot.subplots() returns fully branded figures and axes.

Install

pip install mpl-brandpacker

Quick start

1. Define your brand

# my_brand/colors.py
import mpl_brandpacker as mbp

class Colors(mbp.ColorsBase):
    primary = "#1a5276"
    accent = "#e67e22"
    dark = "#2c3e50"
    muted = "slategray"       # named colors work too
    cycle_0 = "C0"            # matplotlib cycle colors
    highlight = "coral"       # CSS named colors

Colors.plot()  # → swatch grid for documentation

ColorsBase accepts any matplotlib color string (#RRGGBB, #RRGGBBAA, #RGB, named colors, C0C9, tab:blue, etc.) and normalizes to #rrggbb at definition time.

# my_brand/sizes.py
from mpl_brandpacker.sizes import MM_TO_INCH

class Sizes(mbp.FigsizesBase):
    half = (88 * MM_TO_INCH, 76 * MM_TO_INCH)
    full = (181 * MM_TO_INCH, 76 * MM_TO_INCH)

class FontSizes(mbp.SizesBase):
    title = 10
    body = 8
    footer = 6.5

    _scalers = {"presentation": 2.0}

SizesBase.scaled() is thread-safe — concurrent threads and async tasks each get their own scaled values.

# my_brand/figure.py
from mpl_brandpacker import BrandFigure, brand_method

class MyFigure(BrandFigure):
    @brand_method
    def set_title(self, title, **kw):
        self.mpl.suptitle(title, fontsize=10, weight="bold", x=0.02, ha="left", **kw)

    @brand_method
    def set_sources(self, sources, **kw):
        self.text(0.02, 0.02, f"Source: {sources}", fontsize=6.5,
                  color="#888", transform=self.transFigure, **kw)

    @brand_method(overwrite="savefig")
    def _branded_save(self, *args, **kw):
        """Override savefig with branded defaults.

        Pylance still shows the original Figure.savefig docstring
        because the implementation is underscore-prefixed.
        """
        kw.setdefault("dpi", 300)
        kw.setdefault("bbox_inches", "tight")
        self.mpl.savefig(*args, **kw)

Use @brand_method(overwrite="name") to override a built-in method while keeping IDE autocompletion on the original.

# my_brand/axes.py
from mpl_brandpacker import BrandAxes, brand_method

class MyAxes(BrandAxes):
    @brand_method
    def set_xlabel(self, label, **kw):
        self.mpl.set_xlabel(label, fontsize=8, **kw)

    @brand_method
    def set_ylabel(self, label, **kw):
        self.mpl.set_ylabel(label, fontsize=8, rotation="horizontal", **kw)

def set_style(ax, **kw):
    ax.grid(True, alpha=0.2)
    for spine in ("top", "right"):
        ax.spines[spine].set_visible(False)

2. Configure

# my_brand/__init__.py
import mpl_brandpacker as mbp
from pathlib import Path

mbp.configure(
    figure_cls=MyFigure,
    axes_cls=MyAxes,
    style_fn=set_style,
    stylesheet=Path(__file__).parent,  # dir with .mplstyle + data/fonts/
    pandas=True,                        # also hook df.plot()
)

3. Re-export pyplot

# my_brand/pyplot.py
from mpl_brandpacker.pyplot import *  # noqa
from mpl_brandpacker.pyplot import gcf

# pyplot-level shortcuts for brand methods (like plt.title in matplotlib)
def title(title, **kw):     gcf().set_title(title, **kw)
def subtitle(sub, **kw):    gcf().set_subtitle(sub, **kw)
def sources(src, **kw):     gcf().set_sources(src, **kw)
def footnote(note, **kw):   gcf().set_footnote(note, **kw)

For IDE autocompletion of brand methods on fig and ax, add a pyplot.pyi stub file — see the template for a complete example.

4. Use it

import my_brand.pyplot as plt

fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
ax.set_xlabel("Quarter")

plt.title("Revenue")
plt.sources("Bloomberg")
plt.show()

Everything is branded. Original matplotlib methods are accessible via .mpl:

fig.mpl.legend()       # original Figure.legend
ax.mpl.set_xlabel()    # original Axes.set_xlabel

5. Reset (notebooks)

When iterating on your brand in a notebook, use reset() to start fresh:

import mpl_brandpacker as mbp

mbp.reset()                          # clears all hooks, reverts pandas
mbp.configure(figure_cls=..., ...)   # re-configure

What it provides

Export Purpose
configure() Wire everything up — one call
reset() Clear all hooks (for notebook iteration)
brand_method Decorator to auto-register methods for patching
BrandFigure Base class for figure methods (subclass of Figure)
BrandAxes Base class for axes methods (subclass of Axes)
ColorsBase Color enum — accepts any matplotlib color string, normalizes to hex
FigsizesBase Validated (w,h) size enum with .plot()
SizesBase Font sizes with thread-safe context-managed scaling
PrintableEnum Generic enum base

Submodules (advanced)

Module Purpose
mpl_brandpacker.pyplot Branded drop-in for matplotlib.pyplot
mpl_brandpacker.pandas use_for_pandas() for df.plot()
mpl_brandpacker.patcher brand_method, patch_method(), MethodProxy
mpl_brandpacker.style register_stylesheet()
mpl_brandpacker.sizes MM_TO_INCH, POINTS_TO_INCH
mpl_brandpacker.utils get_text_bbox(), separate_kwargs()

How it works

configure() builds two functions — make_fig(fig) and make_ax(ax) — that patch matplotlib objects using Python's descriptor protocol. When you import my_brand.pyplot as plt, three pyplot entry points are intercepted:

  • figure() → patches the new figure + wraps its axes creation methods
  • gcf() → patches the current figure
  • gca() → patches the current axes

All other pyplot functions (subplots, show, savefig, etc.) work unchanged because they internally call figure() or gcf().

@brand_method decorator

@brand_method                         # patches fig.set_title
def set_title(self, title): ...

@brand_method(overwrite="savefig")    # patches fig.savefig with this method
def _branded_save(self, *a, **kw):    # underscore name → invisible to Pylance
    self.mpl.savefig(*a, dpi=300)     # .mpl accesses the original

The overwrite parameter lets you override built-in matplotlib methods while keeping Pylance's autocompletion on the original signature.

Scaffold a new brand

python -m mpl_brandpacker.create_brand acme_corp --author "Jane Doe"

Generates a complete brand package from the built-in template with colors, sizes, figure, axes, header/footer layout, and a pyplot.pyi stub for IDE support.

Template

See template/ for a complete working example.

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

mpl_brandpacker-0.0.2.tar.gz (177.6 kB view details)

Uploaded Source

Built Distribution

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

mpl_brandpacker-0.0.2-py3-none-any.whl (37.2 kB view details)

Uploaded Python 3

File details

Details for the file mpl_brandpacker-0.0.2.tar.gz.

File metadata

  • Download URL: mpl_brandpacker-0.0.2.tar.gz
  • Upload date:
  • Size: 177.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mpl_brandpacker-0.0.2.tar.gz
Algorithm Hash digest
SHA256 96efd7993272e287b246348c245c40c3604a0dafb6ad31cf4aa01dd4a6dce39f
MD5 f094238af188ab3ae14af7ec077aea30
BLAKE2b-256 942c33f578cb9b9e299719ae80141596ee6c7d5b241a1d12d34d0d1e236266d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for mpl_brandpacker-0.0.2.tar.gz:

Publisher: publish.yml on saemeon/mpl-brandpacker

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

File details

Details for the file mpl_brandpacker-0.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for mpl_brandpacker-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3430b7c11ec5bcde04519f8278922cde9781eec395ae87e75eebccd54c3bc4ea
MD5 72aeb809af289db71e70a1bd8a28d586
BLAKE2b-256 7cd4df412b06b12db143b7a852c0f7dc4928b48bce120d9c9cf8e7d84a3c7e94

See more details on using hashes here.

Provenance

The following attestation bundles were made for mpl_brandpacker-0.0.2-py3-none-any.whl:

Publisher: publish.yml on saemeon/mpl-brandpacker

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