pythonforbio.
[WASM idle]
Plotting12/14

rcParams and Style Sheets

Starting sandbox…
Beginnerlesson

rcParams and Style Sheets

In one line: set your defaults once at the top of a script instead of restyling every figure — it is the highest-leverage plotting habit there is.

rcParams

A dict of ~300 defaults controlling every aspect of rendering:

import matplotlib as mpl

mpl.rcParams["font.size"] = 9
mpl.rcParams["figure.figsize"] = (5, 3.5)
mpl.rcParams["axes.grid"] = True

mpl.rcParams.update({
    "font.size": 9,
    "axes.labelsize": 9,
    "axes.titlesize": 10,
    "xtick.labelsize": 8,
    "ytick.labelsize": 8,
    "legend.fontsize": 8,
    "figure.dpi": 100,
    "savefig.dpi": 300,
    "savefig.bbox": "tight",
    "pdf.fonttype": 42,
    "axes.spines.top": False,
    "axes.spines.right": False,
    "axes.grid": True,
    "grid.alpha": 0.3,
    "grid.linewidth": 0.5,
    "axes.axisbelow": True,
    "lines.linewidth": 1.5,
    "figure.autolayout": False,      # use layout="constrained" instead
})

mpl.rcParamsDefault                   # the pristine defaults
mpl.rcdefaults()                      # reset
print(mpl.matplotlib_fname())         # where the config file lives

Setting pdf.fonttype: 42 and axes.spines.top/right: False here means you never think about them again. See Saving Figures.

Style sheets

plt.style.available                       # list them
plt.style.use("seaborn-v0_8-whitegrid")
plt.style.use("ggplot")
plt.style.use(["seaborn-v0_8-paper", "custom.mplstyle"])   # layered

with plt.style.context("dark_background"):     # temporary
    fig, ax = plt.subplots()

Note the seaborn-v0_8- prefix: matplotlib renamed the bundled seaborn styles when seaborn 0.12 changed. Old code using plt.style.use("seaborn") breaks on modern matplotlib.

A project style file

Create paper.mplstyle:

font.family        : sans-serif
font.sans-serif    : Arial, Helvetica, DejaVu Sans
font.size          : 8
axes.labelsize     : 8
axes.titlesize     : 9
axes.titlelocation : left
xtick.labelsize    : 7
ytick.labelsize    : 7
legend.fontsize    : 7
legend.frameon     : False
axes.spines.top    : False
axes.spines.right  : False
axes.grid          : True
axes.axisbelow     : True
grid.alpha         : 0.3
grid.linewidth     : 0.4
lines.linewidth    : 1.2
figure.figsize     : 3.5, 2.6
figure.dpi         : 110
savefig.dpi        : 300
savefig.bbox       : tight
pdf.fonttype       : 42
ps.fonttype        : 42
svg.fonttype       : none
axes.prop_cycle    : cycler('color', ['4C72B0','DD8452','55A868','C44E52','8172B3','937860'])
plt.style.use("paper.mplstyle")

Commit this file to your repository. It makes every figure in the paper consistent, it documents your choices, and a collaborator regenerating your figures gets the same output. Note that hex colours in a style file have no # prefix — a common gotcha.

seaborn's set_theme

Usually easier than raw rcParams, because it sets a coherent group at once:

sns.set_theme(
    style="whitegrid",       # darkgrid, whitegrid, dark, white, ticks
    context="paper",         # paper, notebook, talk, poster
    palette="colorblind",
    font="Arial",
    font_scale=1.0,
    rc={"figure.figsize": (5, 3.5), "pdf.fonttype": 42},
)

sns.set_theme() modifies matplotlib's rcParams, so it affects your raw matplotlib plots too. One call at the top of a script styles everything.

context scales all font and line sizes together:

context For
paper journal figures — smallest
notebook the default
talk slides
poster largest

Building a figure for a talk is sns.set_theme(context="talk") and re-running, not manually bumping fifteen font sizes.

sns.set_context("talk", font_scale=1.1)
sns.axes_style()                      # inspect the current style dict
with sns.axes_style("white"):         # temporary
    ...

Fonts

mpl.rcParams["font.family"] = "sans-serif"
mpl.rcParams["font.sans-serif"] = ["Arial", "Helvetica", "DejaVu Sans"]

from matplotlib import font_manager
sorted({f.name for f in font_manager.fontManager.ttflist})   # what's available

Most journals want Arial or Helvetica. Give a fallback list — a cluster or CI container may not have Arial installed, and matplotlib silently substitutes DejaVu Sans while emitting a findfont warning.

For LaTeX-quality maths without a LaTeX install:

mpl.rcParams["mathtext.fontset"] = "stixsans"    # matches sans-serif body text

The script header worth copying

import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns

sns.set_theme(style="ticks", context="paper", palette="colorblind")
mpl.rcParams.update({
    "pdf.fonttype": 42, "ps.fonttype": 42, "svg.fonttype": "none",
    "savefig.bbox": "tight", "savefig.dpi": 300,
    "figure.dpi": 110,
    "axes.titlelocation": "left",
    "font.sans-serif": ["Arial", "Helvetica", "DejaVu Sans"],
})

CONDITION_COLORS = {"control": "#4C72B0", "treated": "#DD8452"}

Six lines that make every figure in the project consistent, publication-sized, colourblind-safe and editable. The CONDITION_COLORS dict belongs here too — see Colormaps and Color.

Precedence

Explicit arguments beat everything:

rcParamsDefault  <  style sheet  <  sns.set_theme()  <  rcParams.update()  <  call arguments

So ax.plot(x, y, lw=3) overrides lines.linewidth regardless of what you set.

Common mistakes

  • Restyling every figure by hand instead of setting defaults once.
  • plt.style.use("seaborn") — renamed to seaborn-v0_8-*.
  • Setting rcParams after creating the figure. Most apply at draw time, but figure-level ones like figure.figsize do not.
  • # prefix on hex colours in a .mplstyle file. Omit it.
  • Assuming Arial exists on every machine. Provide fallbacks.
  • Not committing the style file, so nobody can reproduce your figures.
  • sns.set() — deprecated alias; use sns.set_theme().
  • Global rcParams in a library, silently changing your users' plots. Use a context manager.

See also

Saving Figures · seaborn Themes and Palettes · Axes Styling and Annotation · Colormaps and Color · Applied - Reproducible Environment

lesson example

No output yet — run the code to populate this drawer.