rcParams and building a house style

Matplotlib · Advanced · 10 min

Teams want every chart to share fonts, sizes and colors without repeating twenty keyword arguments in every plot.

Every default, from font size to the color cycle, lives in matplotlib.rcParams, a dict-like object with keys such as "font.size", "axes.spines.top", "lines.linewidth", "figure.dpi" and "axes.prop_cycle". Defaults are read when an artist is created, so changes affect figures made afterwards.

Ways to change them, from most to least local:

  • keyword arguments on one call (linewidth=2);
  • with mpl.rc_context({"font.size": 9}): for a block of code;
  • mpl.rcParams.update({...}) or plt.style.use(...) for the rest of the session;
  • a style file house.mplstyle with lines like axes.grid: True, applied with plt.style.use("path/to/house.mplstyle");
  • a matplotlibrc file in the working directory or config dir (mpl.get_configdir()), loaded at import.

Styles compose: plt.style.use(["seaborn-v0_8-whitegrid", "./house.mplstyle"]) applies them in order, later ones overriding. A style file only needs the keys it changes. Distributing it inside a Python package lets you call plt.style.use("mypkg.house") by dotted name.

mpl.rcdefaults() restores the library defaults, useful in tests. The color cycle is set with cycler: mpl.rcParams["axes.prop_cycle"] = cycler(color=[...]).

Style files deliberately ignore settings unrelated to style, such as the backend, so a style cannot change how figures are displayed.

Example

import matplotlib as mpl
mpl.use("Agg")
import matplotlib.pyplot as plt
from cycler import cycler
from matplotlib.colors import to_hex
from pathlib import Path

Path("house.mplstyle").write_text(
    "axes.spines.top: False\n"
    "axes.spines.right: False\n"
    "axes.grid: True\n"
    "font.size: 11\n"
)
plt.style.use("./house.mplstyle")
print(mpl.rcParams["axes.spines.top"], mpl.rcParams["font.size"])  # False 11.0

with mpl.rc_context({"axes.prop_cycle": cycler(color=["#11557C", "#E8A33D"])}):
    fig, ax = plt.subplots()
    ax.plot([1, 2]); ax.plot([2, 1])
    print([l.get_color() for l in ax.lines])  # ['#11557C', '#E8A33D']

print(to_hex(mpl.rcParams["axes.prop_cycle"].by_key()["color"][0]))  # #1f77b4

Remember

  • rcParams hold every default and are read when artists are created
  • Use rc_context for local changes and .mplstyle files for a team style
  • Styles compose in order; rcdefaults() resets everything

Watch out for

  • Changing rcParams after creating a figure and expecting existing text and lines to update.

Check yourself

  1. You need 8-point fonts only for one helper that creates a small figure. What is the cleanest approach?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: matplotlib.org/stable/users/explain/customizing.html